Skip to content

Instantly share code, notes, and snippets.

@mborgerson
Last active March 9, 2022 17:18
Show Gist options
  • Save mborgerson/6236caa80e0b920f5e99 to your computer and use it in GitHub Desktop.
Save mborgerson/6236caa80e0b920f5e99 to your computer and use it in GitHub Desktop.
Mesa Offscreen Software Rendering

Build Mesa Off-Screen Software Renderer

Last tested on October 6th, 2020, using a fresh Ubuntu 20.04 Docker image. Works with latest version of mesa (20.2.0), at time of writing.

# Install build dependencies
apt update
apt install build-essential git python3 python3-setuptools python3-mako bison flex meson pkg-config wget

# Create a working dir, install dir
mkdir mesa_offscreen
cd mesa_offscreen
mkdir -p install
pushd install
INSTALL_DIR=$PWD
popd

# Build mesa library
git clone --depth=1 -b mesa-20.2.0 https://github.com/mesa3d/mesa
pushd mesa
mkdir build
meson setup \
	-Ddri-drivers=  \
	-Ddri3=disabled  \
	-Degl=disabled  \
	-Dgallium-drivers=swrast  \
	-Dgles1=disabled  \
	-Dgles2=disabled  \
	-Dglx-direct=false  \
	-Dglx=disabled  \
	-Dosmesa=gallium  \
	-Dplatforms=  \
	-Dprefix=$INSTALL_DIR \
	-Dvulkan-drivers=  \
	build .
ninja -C build install
popd

# Build GLU
mkdir glu
pushd glu
wget ftp://ftp.freedesktop.org/pub/mesa/glu/glu-9.0.1.tar.xz
tar xvf glu-9.0.1.tar.xz
cd glu-9.0.1
./configure \
	--prefix=$INSTALL_DIR \
	--enable-osmesa \
	PKG_CONFIG_PATH=$INSTALL_DIR/lib/x86_64-linux-gnu/pkgconfig
make -j12 install
popd

# Build osdemo
mkdir demo
pushd demo
wget ftp://ftp.freedesktop.org/pub/mesa/demos/8.3.0/mesa-demos-8.3.0.tar.gz
tar xvf mesa-demos-8.3.0.tar.gz
cd mesa-demos-8.3.0/src/osdemos
gcc -o osdemo osdemo.c \
	-I$INSTALL_DIR/include/ \
	-L$INSTALL_DIR/lib \
	-L$INSTALL_DIR/lib/x86_64-linux-gnu \
	-Xlinker -rpath $INSTALL_DIR/lib/x86_64-linux-gnu/ \
	-I../util -lOSMesa -lm -lGLU

# Verify not using system GL
LD_LIBRARY_PATH=$INSTALL_DIR/lib/x86_64-linux-gnu/:$INSTALL_DIR/lib ldd osdemo
# linux-vdso.so.1 (0x00007ffe61b70000)
# libOSMesa.so.8 => /mesa_offscreen/install/lib/x86_64-linux-gnu/libOSMesa.so.8 (0x00007f40d538d000)
# libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f40d523a000)
# libGLU.so.1 => /mesa_offscreen/install/lib/libGLU.so.1 (0x00007f40d51c8000)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f40d4fd6000)
# libz.so => /mesa_offscreen/install/lib/x86_64-linux-gnu/libz.so (0x00007f40d4fbc000)
# libglapi.so.0 => /mesa_offscreen/install/lib/x86_64-linux-gnu/libglapi.so.0 (0x00007f40d4f82000)
# libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f40d4d9f000)
# libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f40d4d84000)
# libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f40d4d61000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f40d5e8c000)

# Run the demo
LD_LIBRARY_PATH=$INSTALL_DIR/lib/x86_64-linux-gnu/:$INSTALL_DIR/lib ./osdemo test.tga

Output image (test.tga), will be the following:

Build teapot.c

For slightly more interesting geometry, download teapot.c in this gist and build/run it just like osdemo.c.

/*
* This is a modified version of osdemo.c that will draw the utah teapot in an
* offscreen buffer, then write it to a file. - Matt
*
* Hacked together from:
* - osdemo.c (ftp://ftp.freedesktop.org/pub/mesa/demos/8.3.0/mesa-demos-8.3.0.tar.gz)
* - glut_teapot.c (https://www.opengl.org/resources/libraries/glut/glut37.zip)
* - teapot.c (https://www.cs.uaf.edu/~cs381/examples/teapot.c)
*/
/*
* Demo of off-screen Mesa rendering
*
* See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
*
* If you want to render BIG images you'll probably have to increase
* MAX_WIDTH and MAX_Height in src/config.h.
*
* This program is in the public domain.
*
* Brian Paul
*
* PPM output provided by Joerg Schmalzl.
* ASCII PPM output added by Brian Paul.
*
* Usage: osdemo [filename]
*/
/* Copyright (c) Mark J. Kilgard, 1994. */
/**
(c) Copyright 1993, Silicon Graphics, Inc.
ALL RIGHTS RESERVED
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that
both the copyright notice and this permission notice appear in
supporting documentation, and that the name of Silicon
Graphics, Inc. not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission.
THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
PERFORMANCE OF THIS SOFTWARE.
US Government Users Restricted Rights
Use, duplication, or disclosure by the Government is subject to
restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
(c)(1)(ii) of the Rights in Technical Data and Computer
Software clause at DFARS 252.227-7013 and/or in similar or
successor clauses in the FAR or the DOD or NASA FAR
Supplement. Unpublished-- rights reserved under the copyright
laws of the United States. Contractor/manufacturer is Silicon
Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
94039-7311.
OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
/*
* teapot.c
* This program displays the Utah teapot.
* Modified from OpenGL Programming Guide (red book) by MGR - 071103
*
* Copyright (c) 1993-1999, Silicon Graphics, Inc.
* OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/osmesa.h"
#include "gl_wrap.h"
#include <stdlib.h>
static int Width = 400;
static int Height = 400;
GLuint teapotList;
/* Rim, body, lid, and bottom data must be reflected in x and
y; handle and spout data across the y axis only. */
static int patchdata[][16] =
{
/* rim */
{102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15},
/* body */
{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27},
{24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40},
/* lid */
{96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101,
101, 0, 1, 2, 3,},
{0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117},
/* bottom */
{118, 118, 118, 118, 124, 122, 119, 121, 123, 126,
125, 120, 40, 39, 38, 37},
/* handle */
{41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56},
{53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
28, 65, 66, 67},
/* spout */
{68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83},
{80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95}
};
/* *INDENT-OFF* */
static float cpdata[][3] =
{
{0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
-0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
{0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
{1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
{0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
{1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
{1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
-1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
-0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
{-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
-0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
-0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
{2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
-0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
{3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
{3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
{2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
-0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
{0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
-0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
{0.84, -1.5, 0.075}
};
static float tex[2][2][2] =
{
{ {0, 0},
{1, 0}},
{ {0, 1},
{1, 1}}
};
static void
teapot(GLint grid, GLdouble scale, GLenum type)
{
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;
glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_2);
glPushMatrix();
glRotatef(270.0, 1.0, 0.0, 0.0);
glScalef(0.5 * scale, 0.5 * scale, 0.5 * scale);
glTranslatef(0.0, 0.0, -1.5);
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 3; l++) {
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 1)
q[j][k][l] *= -1.0;
if (i < 6) {
r[j][k][l] =
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 0)
r[j][k][l] *= -1.0;
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
if (l == 0)
s[j][k][l] *= -1.0;
if (l == 1)
s[j][k][l] *= -1.0;
}
}
}
}
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2,
&tex[0][0][0]);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&p[0][0][0]);
glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&q[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
if (i < 6) {
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&r[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&s[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
}
}
glPopMatrix();
glPopAttrib();
}
void APIENTRY
glutSolidTeapot(GLdouble scale)
{
teapot(14, scale, GL_FILL);
}
void APIENTRY
glutWireTeapot(GLdouble scale)
{
teapot(10, scale, GL_LINE);
}
/*
* Initialize depth buffer, projection matrix, light source, and lighting
* model. Do not specify a material property here.
*/
void init(void)
{
GLfloat ambient[] = {0.1, 0.1, 0.1, 1.0};
GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat position[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0};
GLfloat local_view[] = {0.0};
glShadeModel(GL_FLAT);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
glFrontFace(GL_CW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glEnable(GL_DEPTH_TEST);
/* be efficient--make teapot display list */
teapotList = glGenLists(1);
glNewList (teapotList, GL_COMPILE);
glutSolidTeapot(5.0);
glEndList ();
}
/*
* Move object into position. Use 3rd through 12th
* parameters to specify the material property. Draw a teapot.
*/
void renderTeapot(GLfloat x, GLfloat y,
GLfloat ambr, GLfloat ambg, GLfloat ambb,
GLfloat difr, GLfloat difg, GLfloat difb,
GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
{
GLfloat mat[4];
glPushMatrix();
glTranslatef(x, y, 0.0);
mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;
glMaterialfv(GL_FRONT, GL_AMBIENT, mat);
mat[0] = difr; mat[1] = difg; mat[2] = difb;
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat);
mat[0] = specr; mat[1] = specg; mat[2] = specb;
glMaterialfv(GL_FRONT, GL_SPECULAR, mat);
glMaterialf(GL_FRONT, GL_SHININESS, shine * 128.0);
glCallList(teapotList);
glPopMatrix();
}
/**
* First column: emerald, jade, obsidian, pearl, ruby, turquoise
* 2nd column: brass, bronze, chrome, copper, gold, silver
* 3rd column: black, cyan, green, red, white, yellow plastic
* 4th column: black, cyan, green, red, white, yellow rubber
*/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderTeapot(8.0, 8.0,
0.1, 0.5, 0.1,
0.1, 0.5, 0.1,
0.1, 0.5, 0.1, 0.25);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(0.0, 16.0, 0.0, 16.0*(GLfloat)h/(GLfloat)w,
-10.0, 10.0);
else
glOrtho(0.0, 16.0*(GLfloat)w/(GLfloat)h, 0.0, 16.0,
-10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}
static void
render_image(void)
{
init();
reshape(Width, Height);
display();
/* This is very important!!!
* Make sure buffered commands are finished!!!
*/
glFinish();
}
static void
write_targa(const char *filename, const GLubyte *buffer, int width, int height)
{
FILE *f = fopen( filename, "w" );
if (f) {
int i, x, y;
const GLubyte *ptr = buffer;
printf ("osdemo, writing tga file \n");
fputc (0x00, f); /* ID Length, 0 => No ID */
fputc (0x00, f); /* Color Map Type, 0 => No color map included */
fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */
fputc (0x00, f); /* Next five bytes are about the color map entries */
fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */
fputc (0x00, f);
fputc (0x00, f);
fputc (0x00, f);
fputc (0x00, f); /* X-origin of Image */
fputc (0x00, f);
fputc (0x00, f); /* Y-origin of Image */
fputc (0x00, f);
fputc (Width & 0xff, f); /* Image Width */
fputc ((Width>>8) & 0xff, f);
fputc (Height & 0xff, f); /* Image Height */
fputc ((Height>>8) & 0xff, f);
fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */
fputc (0x20, f); /* Image Descriptor */
fclose(f);
f = fopen( filename, "ab" ); /* reopen in binary append mode */
for (y=height-1; y>=0; y--) {
for (x=0; x<width; x++) {
i = (y*width + x) * 4;
fputc(ptr[i+2], f); /* write blue */
fputc(ptr[i+1], f); /* write green */
fputc(ptr[i], f); /* write red */
}
}
}
}
int
main(int argc, char *argv[])
{
OSMesaContext ctx;
void *buffer;
char *filename = NULL;
if (argc < 2) {
fprintf(stderr, "Usage:\n");
fprintf(stderr, " teapot filename [width height]\n");
return 0;
}
filename = argv[1];
if (argc == 4) {
Width = atoi(argv[2]);
Height = atoi(argv[3]);
}
/* Create an RGBA-mode context */
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
/* specify Z, stencil, accum sizes */
ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
#else
ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
#endif
if (!ctx) {
printf("OSMesaCreateContext failed!\n");
return 0;
}
/* Allocate the image buffer */
buffer = malloc( Width * Height * 4 * sizeof(GLubyte) );
if (!buffer) {
printf("Alloc image buffer failed!\n");
return 0;
}
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, Width, Height )) {
printf("OSMesaMakeCurrent failed!\n");
return 0;
}
{
int z, s, a;
glGetIntegerv(GL_DEPTH_BITS, &z);
glGetIntegerv(GL_STENCIL_BITS, &s);
glGetIntegerv(GL_ACCUM_RED_BITS, &a);
printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
}
render_image();
if (filename != NULL) {
write_targa(filename, buffer, Width, Height);
}
else {
printf("Specify a filename if you want to make an image file\n");
}
printf("all done\n");
/* free the image buffer */
free( buffer );
/* destroy the context */
OSMesaDestroyContext( ctx );
return 0;
}
@mborgerson
Copy link
Author

osdemo output

## teapot.c output

@cs01
Copy link

cs01 commented Apr 8, 2020

This is great, thanks for sharing. Here are the things I needed to do to get this to work.

  • wget ftp://ftp.freedesktop.org/pub/mesa/older-versions/11.x/11.0.0/mesa-11.0.0.tar.xz (url in gist has moved)
  • Had to remove -l: in the command to build the demo. It ended up being gcc -o osdemo osdemo.c -I$MESA_OUTPUT_PATH/include/ -L$MESA_OUTPUT_PATH/lib -I../util -lOSMesa -lm $MESA_OUTPUT_PATH/lib/libGLU.a.
  • Did not seem to need mako. I didn't install it, but was able to run the demo without an issue.

Finally, when viewing the shared objects with ldd, we can have them all resolve by adding LD_LIBRARY_PATH so we don't get any "not found", and dependencies can be resolved, making the list comprehensive:

>> LD_LIBRARY_PATH=$MESA_OUTPUT_PATH/lib ldd osdemo
linux-vdso.so.1 (0x00007ffc7e9d3000)
libOSMesa.so.8 => /home/user/work/mesa/lib/libOSMesa.so.8 (0x00007f0606d54000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f06069b6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f06065c5000)
libglapi.so.0 => /home/user/work/mesa/lib/libglapi.so.0 (0x00007f060635f000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0606140000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0605f3c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0605bb3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f060599b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f060754d000)

@mborgerson
Copy link
Author

@cs01 Glad it was useful! Thanks for the updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment