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
);
402 assert(cBits
== bits
);
403 glGetIntegerv(GL_GREEN_BITS
, &cBits
);
404 assert(cBits
== bits
);
405 glGetIntegerv(GL_BLUE_BITS
, &cBits
);
406 assert(cBits
== bits
);
407 glGetIntegerv(GL_ALPHA_BITS
, &cBits
);
408 assert(cBits
== bits
);
411 printf("Rendering %d bit/channel image: %s\n", bits
, filename
);
413 printf("Rendering %d bit/channel image\n", bits
);
415 OSMesaColorClamp(GL_TRUE
);
422 /* Make sure buffered commands are finished! */
426 if (WriteFiles
&& filename
!= NULL
) {
427 if (type
== GL_UNSIGNED_SHORT
) {
428 GLushort
*buffer16
= (GLushort
*) buffer
;
429 GLubyte
*buffer8
= (GLubyte
*) malloc(WIDTH
* HEIGHT
* 4);
431 for (i
= 0; i
< WIDTH
* HEIGHT
* 4; i
++)
432 buffer8
[i
] = buffer16
[i
] >> 8;
433 write_ppm(filename
, buffer8
, WIDTH
, HEIGHT
);
436 else if (type
== GL_FLOAT
) {
437 GLfloat
*buffer32
= (GLfloat
*) buffer
;
438 GLubyte
*buffer8
= (GLubyte
*) malloc(WIDTH
* HEIGHT
* 4);
440 /* colors may be outside [0,1] so we need to clamp */
441 for (i
= 0; i
< WIDTH
* HEIGHT
* 4; i
++)
442 buffer8
[i
] = (GLubyte
) (buffer32
[i
] * 255.0);
443 write_ppm(filename
, buffer8
, WIDTH
, HEIGHT
);
447 write_ppm(filename
, buffer
, WIDTH
, HEIGHT
);
451 OSMesaDestroyContext(ctx
);
460 main( int argc
, char *argv
[] )
464 printf("Use -f to write image files\n");
466 for (i
= 1; i
< argc
; i
++) {
467 if (strcmp(argv
[i
], "-f") == 0)
468 WriteFiles
= GL_TRUE
;
469 else if (strcmp(argv
[i
], "-g") == 0)
473 test(GL_UNSIGNED_BYTE
, 8, "image8.ppm");
474 test(GL_UNSIGNED_SHORT
, 16, "image16.ppm");
475 test(GL_FLOAT
, 32, "image32.ppm");