2
* Test OSMesa interface at 8, 16 and 32 bits/channel.
4
* Usage: osdemo [options]
7
* -f generate image files
8
* -g render gradient and print color values
16
#include "GL/osmesa.h"
23
static GLboolean WriteFiles = GL_FALSE;
24
static GLboolean Gradient = GL_FALSE;
28
Sphere(float radius, int slices, int stacks)
30
GLUquadric *q = gluNewQuadric();
31
gluQuadricNormals(q, GLU_SMOOTH);
32
gluSphere(q, radius, slices, stacks);
38
Cone(float base, float height, int slices, int stacks)
40
GLUquadric *q = gluNewQuadric();
41
gluQuadricDrawStyle(q, GLU_FILL);
42
gluQuadricNormals(q, GLU_SMOOTH);
43
gluCylinder(q, base, 0.0, height, slices, stacks);
49
Torus(float innerRadius, float outerRadius, int sides, int rings)
53
GLfloat theta, phi, theta1;
54
GLfloat cosTheta, sinTheta;
55
GLfloat cosTheta1, sinTheta1;
56
const GLfloat ringDelta = 2.0 * M_PI / rings;
57
const GLfloat sideDelta = 2.0 * M_PI / sides;
62
for (i = rings - 1; i >= 0; i--) {
63
theta1 = theta + ringDelta;
64
cosTheta1 = cos(theta1);
65
sinTheta1 = sin(theta1);
66
glBegin(GL_QUAD_STRIP);
68
for (j = sides; j >= 0; j--) {
69
GLfloat cosPhi, sinPhi, dist;
74
dist = outerRadius + innerRadius * cosPhi;
76
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
77
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi);
78
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
79
glVertex3f(cosTheta * dist, -sinTheta * dist, innerRadius * sinPhi);
89
static void Cube(float size)
96
glVertex3f(size, -size, size);
97
glVertex3f(size, -size, -size);
98
glVertex3f(size, size, -size);
99
glVertex3f(size, size, size);
102
glNormal3f(-1, 0, 0);
103
glVertex3f(-size, size, size);
104
glVertex3f(-size, size, -size);
105
glVertex3f(-size, -size, -size);
106
glVertex3f(-size, -size, size);
110
glVertex3f(-size, size, size);
111
glVertex3f( size, size, size);
112
glVertex3f( size, size, -size);
113
glVertex3f(-size, size, -size);
116
glNormal3f(0, -1, 0);
117
glVertex3f(-size, -size, -size);
118
glVertex3f( size, -size, -size);
119
glVertex3f( size, -size, size);
120
glVertex3f(-size, -size, size);
124
glVertex3f(-size, -size, size);
125
glVertex3f( size, -size, size);
126
glVertex3f( size, size, size);
127
glVertex3f(-size, size, size);
130
glNormal3f(0, 0, -1);
131
glVertex3f(-size, size, -size);
132
glVertex3f( size, size, -size);
133
glVertex3f( size, -size, -size);
134
glVertex3f(-size, -size, -size);
142
* Draw red/green gradient across bottom of image.
143
* Read pixels to check deltas.
146
render_gradient(void)
148
GLfloat row[WIDTH][4];
151
glMatrixMode(GL_PROJECTION);
153
glOrtho(-1, 1, -1, 1, -1, 1);
154
glMatrixMode(GL_MODELVIEW);
159
glVertex2f(-1, -1.0);
160
glVertex2f(-1, -0.9);
167
glReadPixels(0, 0, WIDTH, 1, GL_RGBA, GL_FLOAT, row);
168
for (i = 0; i < 4; i++) {
169
printf("row[i] = %f, %f, %f\n", row[i][0], row[i][1], row[i][2]);
177
static const GLfloat light_ambient[4] = { 0.0, 0.0, 0.0, 1.0 };
178
static const GLfloat light_diffuse[4] = { 1.0, 1.0, 1.0, 1.0 };
179
static const GLfloat light_specular[4] = { 1.0, 1.0, 1.0, 1.0 };
180
static const GLfloat light_position[4] = { 1.0, 1.0, 1.0, 0.0 };
181
static const GLfloat red_mat[4] = { 1.0, 0.2, 0.2, 1.0 };
182
static const GLfloat green_mat[4] = { 0.2, 1.0, 0.2, 1.0 };
183
static const GLfloat blue_mat[4] = { 0.2, 0.2, 1.0, 1.0 };
185
static const GLfloat yellow_mat[4] = { 0.8, 0.8, 0.0, 1.0 };
187
static const GLfloat purple_mat[4] = { 0.8, 0.4, 0.8, 0.6 };
189
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
190
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
191
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
192
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
194
glEnable(GL_DEPTH_TEST);
197
glMatrixMode(GL_PROJECTION);
199
glFrustum(-1.0, 1.0, -1.0, 1.0, 2.0, 50.0);
200
glMatrixMode(GL_MODELVIEW);
201
glTranslatef(0, 0.5, -7);
203
glClearColor(0.3, 0.3, 0.7, 0.0);
204
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
207
glRotatef(20.0, 1.0, 0.0, 0.0);
210
glEnable(GL_TEXTURE_2D);
213
glTexCoord2f(0, 0); glVertex3f(-5, -1, -5);
214
glTexCoord2f(1, 0); glVertex3f( 5, -1, -5);
215
glTexCoord2f(1, 1); glVertex3f( 5, -1, 5);
216
glTexCoord2f(0, 1); glVertex3f(-5, -1, 5);
218
glDisable(GL_TEXTURE_2D);
220
glEnable(GL_LIGHTING);
223
glTranslatef(-1.5, 0.5, 0.0);
224
glRotatef(90.0, 1.0, 0.0, 0.0);
225
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
226
Torus(0.275, 0.85, 20, 20);
230
glTranslatef(-1.5, -0.5, 0.0);
231
glRotatef(270.0, 1.0, 0.0, 0.0);
232
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
233
Cone(1.0, 2.0, 16, 1);
237
glTranslatef(0.95, 0.0, -0.8);
238
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
240
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
242
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
247
glTranslatef(0.75, 0.0, 1.3);
248
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow_mat );
254
glTranslatef(-0.25, 0.0, 2.5);
255
glRotatef(40, 0, 1, 0);
256
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
258
glEnable(GL_CULL_FACE);
259
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, purple_mat );
262
glDisable(GL_CULL_FACE);
265
glDisable(GL_LIGHTING);
269
glDisable(GL_DEPTH_TEST);
276
const GLint texWidth = 64, texHeight = 64;
281
texImage = malloc(texWidth * texHeight * 4);
282
for (i = 0; i < texHeight; i++) {
283
for (j = 0; j < texWidth; j++) {
284
int k = (i * texWidth + j) * 4;
285
if ((i % 5) == 0 || (j % 5) == 0) {
292
if ((i % 5) == 1 || (j % 5) == 1) {
308
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0,
309
GL_RGBA, GL_UNSIGNED_BYTE, texImage);
310
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
311
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
318
write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
320
const int binary = 0;
321
FILE *f = fopen( filename, "w" );
324
const GLubyte *ptr = buffer;
327
fprintf(f,"# ppm-file created by osdemo.c\n");
328
fprintf(f,"%i %i\n", width,height);
331
f = fopen( filename, "ab" ); /* reopen in binary append mode */
332
for (y=height-1; y>=0; y--) {
333
for (x=0; x<width; x++) {
334
i = (y*width + x) * 4;
335
fputc(ptr[i], f); /* write red */
336
fputc(ptr[i+1], f); /* write green */
337
fputc(ptr[i+2], f); /* write blue */
345
fprintf(f,"# ascii ppm file created by osdemo.c\n");
346
fprintf(f,"%i %i\n", width, height);
348
for (y=height-1; y>=0; y--) {
349
for (x=0; x<width; x++) {
350
i = (y*width + x) * 4;
351
fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]);
353
if (counter % 5 == 0)
364
test(GLenum type, GLint bits, const char *filename)
366
const GLint z = 16, stencil = 0, accum = 0;
375
assert(type == GL_UNSIGNED_BYTE ||
376
type == GL_UNSIGNED_SHORT ||
379
ctx = OSMesaCreateContextExt(OSMESA_RGBA, z, stencil, accum, NULL );
381
printf("OSMesaCreateContextExt() failed!\n");
385
/* Allocate the image buffer */
386
buffer = malloc(WIDTH * HEIGHT * 4 * bits / 8);
388
printf("Alloc image buffer failed!\n");
392
/* Bind the buffer to the context and make it current */
393
if (!OSMesaMakeCurrent( ctx, buffer, type, WIDTH, HEIGHT )) {
394
printf("OSMesaMakeCurrent (%d bits/channel) failed!\n", bits);
396
OSMesaDestroyContext(ctx);
401
glGetIntegerv(GL_RED_BITS, &cBits);
403
fprintf(stderr, "Unable to create %d-bit/channel renderbuffer.\n", bits);
404
fprintf(stderr, "May need to recompile Mesa with CHAN_BITS=16 or 32.\n");
407
glGetIntegerv(GL_GREEN_BITS, &cBits);
408
assert(cBits == bits);
409
glGetIntegerv(GL_BLUE_BITS, &cBits);
410
assert(cBits == bits);
411
glGetIntegerv(GL_ALPHA_BITS, &cBits);
412
assert(cBits == bits);
415
printf("Rendering %d bit/channel image: %s\n", bits, filename);
417
printf("Rendering %d bit/channel image\n", bits);
419
OSMesaColorClamp(GL_TRUE);
426
/* Make sure buffered commands are finished! */
430
if (WriteFiles && filename != NULL) {
431
if (type == GL_UNSIGNED_SHORT) {
432
GLushort *buffer16 = (GLushort *) buffer;
433
GLubyte *buffer8 = (GLubyte *) malloc(WIDTH * HEIGHT * 4);
435
for (i = 0; i < WIDTH * HEIGHT * 4; i++)
436
buffer8[i] = buffer16[i] >> 8;
437
write_ppm(filename, buffer8, WIDTH, HEIGHT);
440
else if (type == GL_FLOAT) {
441
GLfloat *buffer32 = (GLfloat *) buffer;
442
GLubyte *buffer8 = (GLubyte *) malloc(WIDTH * HEIGHT * 4);
444
/* colors may be outside [0,1] so we need to clamp */
445
for (i = 0; i < WIDTH * HEIGHT * 4; i++)
446
buffer8[i] = (GLubyte) (buffer32[i] * 255.0);
447
write_ppm(filename, buffer8, WIDTH, HEIGHT);
451
write_ppm(filename, buffer, WIDTH, HEIGHT);
455
OSMesaDestroyContext(ctx);
464
main( int argc, char *argv[] )
468
printf("Use -f to write image files\n");
470
for (i = 1; i < argc; i++) {
471
if (strcmp(argv[i], "-f") == 0)
472
WriteFiles = GL_TRUE;
473
else if (strcmp(argv[i], "-g") == 0)
477
test(GL_UNSIGNED_BYTE, 8, "image8.ppm");
478
test(GL_UNSIGNED_SHORT, 16, "image16.ppm");
479
test(GL_FLOAT, 32, "image32.ppm");