3 * Demo of off-screen Mesa rendering
5 * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
7 * If you want to render BIG images you'll probably have to increase
8 * MAX_WIDTH and MAX_HEIGHT in src/config.h.
10 * This program is in the public domain.
14 * PPM output provided by Joerg Schmalzl.
15 * ASCII PPM output added by Brian Paul.
17 * Usage: osdemo [-perf] [filename]
19 * -perf: Redraws the image 1000 times, displaying the FPS every 5 secs.
20 * filename: file to store the TGA or PPM output
27 #include "GL/osmesa.h"
38 static GLint Frames
= 0;
41 static void render_image( void )
43 GLfloat light_ambient
[] = { 0.0, 0.0, 0.0, 1.0 };
44 GLfloat light_diffuse
[] = { 1.0, 1.0, 1.0, 1.0 };
45 GLfloat light_specular
[] = { 1.0, 1.0, 1.0, 1.0 };
46 GLfloat light_position
[] = { 1.0, 1.0, 1.0, 0.0 };
47 GLfloat red_mat
[] = { 1.0, 0.2, 0.2, 1.0 };
48 GLfloat green_mat
[] = { 0.2, 1.0, 0.2, 1.0 };
49 GLfloat blue_mat
[] = { 0.2, 0.2, 1.0, 1.0 };
52 glLightfv(GL_LIGHT0
, GL_AMBIENT
, light_ambient
);
53 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, light_diffuse
);
54 glLightfv(GL_LIGHT0
, GL_SPECULAR
, light_specular
);
55 glLightfv(GL_LIGHT0
, GL_POSITION
, light_position
);
57 glEnable(GL_LIGHTING
);
59 glEnable(GL_DEPTH_TEST
);
61 glMatrixMode(GL_PROJECTION
);
63 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
64 glMatrixMode(GL_MODELVIEW
);
66 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
69 glRotatef(20.0, 1.0, 0.0, 0.0);
72 glTranslatef(-0.75, 0.5, 0.0);
73 glRotatef(90.0, 1.0, 0.0, 0.0);
74 glMaterialfv( GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red_mat
);
75 glutSolidTorus(0.275, 0.85, 20, 20);
79 glTranslatef(-0.75, -0.5, 0.0);
80 glRotatef(270.0, 1.0, 0.0, 0.0);
81 glMaterialfv( GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, green_mat
);
82 glutSolidCone(1.0, 2.0, 16, 1);
85 #ifdef GL_HP_occlusion_test
88 glDepthMask(GL_FALSE
);
89 glColorMask(GL_FALSE
,GL_FALSE
,GL_FALSE
,GL_FALSE
);
90 glEnable(GL_OCCLUSION_TEST_HP
);
91 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP
,&bRet
);
94 glTranslatef(0.75, 0.0, -1.0);
95 glMaterialfv( GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, blue_mat
);
96 glutSolidSphere(1.0, 20, 20);
99 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP
,&bRet
);
100 printf("Occlusion test 1 (result should be 1): %d\n",bRet
);
102 glDepthMask(GL_TRUE
);
103 glColorMask(GL_TRUE
,GL_TRUE
,GL_TRUE
,GL_TRUE
);
104 glDisable(GL_OCCLUSION_TEST_HP
);
109 glTranslatef(0.75, 0.0, -1.0);
110 glMaterialfv( GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, blue_mat
);
111 glutSolidSphere(1.0, 20, 20);
114 #ifdef GL_HP_occlusion_test
118 glDepthMask(GL_FALSE
);
119 glColorMask(GL_FALSE
,GL_FALSE
,GL_FALSE
,GL_FALSE
);
120 glEnable(GL_OCCLUSION_TEST_HP
);
121 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP
,&bRet
);
123 /* draw a sphere inside the previous sphere */
125 glTranslatef(0.75, 0.0, -1.0);
126 glMaterialfv( GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, blue_mat
);
127 glutSolidSphere(0.5, 20, 20);
130 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP
,&bRet
);
131 printf("Occlusion test 2 (result should be 0): %d\n",bRet
);
133 glDepthMask(GL_TRUE
);
134 glColorMask(GL_TRUE
,GL_TRUE
,GL_TRUE
,GL_TRUE
);
135 glDisable(GL_OCCLUSION_TEST_HP
);
141 /* This is very important!!!
142 * Make sure buffered commands are finished!!!
148 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
149 if (t
- T0
>= 5000) {
150 GLfloat seconds
= (t
- T0
) / 1000.0;
151 GLfloat fps
= Frames
/ seconds
;
152 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames
, seconds
, fps
);
163 write_targa(const char *filename
, const GLubyte
*buffer
, int width
, int height
)
165 FILE *f
= fopen( filename
, "w" );
168 const GLubyte
*ptr
= buffer
;
169 printf ("osdemo, writing tga file \n");
170 fputc (0x00, f
); /* ID Length, 0 => No ID */
171 fputc (0x00, f
); /* Color Map Type, 0 => No color map included */
172 fputc (0x02, f
); /* Image Type, 2 => Uncompressed, True-color Image */
173 fputc (0x00, f
); /* Next five bytes are about the color map entries */
174 fputc (0x00, f
); /* 2 bytes Index, 2 bytes length, 1 byte size */
178 fputc (0x00, f
); /* X-origin of Image */
180 fputc (0x00, f
); /* Y-origin of Image */
182 fputc (WIDTH
& 0xff, f
); /* Image Width */
183 fputc ((WIDTH
>>8) & 0xff, f
);
184 fputc (HEIGHT
& 0xff, f
); /* Image Height */
185 fputc ((HEIGHT
>>8) & 0xff, f
);
186 fputc (0x18, f
); /* Pixel Depth, 0x18 => 24 Bits */
187 fputc (0x20, f
); /* Image Descriptor */
189 f
= fopen( filename
, "ab" ); /* reopen in binary append mode */
190 for (y
=height
-1; y
>=0; y
--) {
191 for (x
=0; x
<width
; x
++) {
192 i
= (y
*width
+ x
) * 4;
193 fputc(ptr
[i
+2], f
); /* write blue */
194 fputc(ptr
[i
+1], f
); /* write green */
195 fputc(ptr
[i
], f
); /* write red */
204 write_ppm(const char *filename
, const GLubyte
*buffer
, int width
, int height
)
206 const int binary
= 0;
207 FILE *f
= fopen( filename
, "w" );
210 const GLubyte
*ptr
= buffer
;
213 fprintf(f
,"# ppm-file created by osdemo.c\n");
214 fprintf(f
,"%i %i\n", width
,height
);
217 f
= fopen( filename
, "ab" ); /* reopen in binary append mode */
218 for (y
=height
-1; y
>=0; y
--) {
219 for (x
=0; x
<width
; x
++) {
220 i
= (y
*width
+ x
) * 4;
221 fputc(ptr
[i
], f
); /* write red */
222 fputc(ptr
[i
+1], f
); /* write green */
223 fputc(ptr
[i
+2], f
); /* write blue */
231 fprintf(f
,"# ascii ppm file created by osdemo.c\n");
232 fprintf(f
,"%i %i\n", width
, height
);
234 for (y
=height
-1; y
>=0; y
--) {
235 for (x
=0; x
<width
; x
++) {
236 i
= (y
*width
+ x
) * 4;
237 fprintf(f
, " %3d %3d %3d", ptr
[i
], ptr
[i
+1], ptr
[i
+2]);
239 if (counter
% 5 == 0)
252 int main( int argc
, char *argv
[] )
256 char *filename
= NULL
;
258 /* Create an RGBA-mode context */
259 #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
260 /* specify Z, stencil, accum sizes */
261 OSMesaContext ctx
= OSMesaCreateContextExt( OSMESA_RGBA
, 16, 0, 0, NULL
);
263 OSMesaContext ctx
= OSMesaCreateContext( OSMESA_RGBA
, NULL
);
266 printf("OSMesaCreateContext failed!\n");
270 for ( i
=1; i
<argc
; i
++ ) {
271 if (argv
[i
][0] != '-') filename
= argv
[i
];
272 if (strcmp(argv
[i
], "-perf")==0) perf
= 1;
275 /* Allocate the image buffer */
276 buffer
= malloc( WIDTH
* HEIGHT
* 4 * sizeof(GLubyte
) );
278 printf("Alloc image buffer failed!\n");
282 /* Bind the buffer to the context and make it current */
283 if (!OSMesaMakeCurrent( ctx
, buffer
, GL_UNSIGNED_BYTE
, WIDTH
, HEIGHT
)) {
284 printf("OSMesaMakeCurrent failed!\n");
291 glGetIntegerv(GL_DEPTH_BITS
, &z
);
292 glGetIntegerv(GL_STENCIL_BITS
, &s
);
293 glGetIntegerv(GL_ACCUM_RED_BITS
, &a
);
294 printf("Depth=%d Stencil=%d Accum=%d\n", z
, s
, a
);
299 for(i
=0; i
< 1000; i
++)
302 if (filename
!= NULL
) {
304 write_targa(filename
, buffer
, WIDTH
, HEIGHT
);
306 write_ppm(filename
, buffer
, WIDTH
, HEIGHT
);
310 printf("Specify a filename if you want to make an image file\n");
313 printf("all done\n");
315 /* free the image buffer */
318 /* destroy the context */
319 OSMesaDestroyContext( ctx
);