s/DP4/DP3/
[mesa.git] / progs / demos / osdemo.c
1
2 /*
3 * Demo of off-screen Mesa rendering
4 *
5 * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
6 *
7 * If you want to render BIG images you'll probably have to increase
8 * MAX_WIDTH and MAX_HEIGHT in src/config.h.
9 *
10 * This program is in the public domain.
11 *
12 * Brian Paul
13 *
14 * PPM output provided by Joerg Schmalzl.
15 * ASCII PPM output added by Brian Paul.
16 *
17 * Usage: osdemo [-perf] [filename]
18 *
19 * -perf: Redraws the image 1000 times, displaying the FPS every 5 secs.
20 * filename: file to store the TGA or PPM output
21 */
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "GL/osmesa.h"
28 #include "GL/glut.h"
29
30
31 #define SAVE_TARGA
32
33
34 #define WIDTH 400
35 #define HEIGHT 400
36
37 static GLint T0 = 0;
38 static GLint Frames = 0;
39 static int perf = 0;
40
41 static void render_image( void )
42 {
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 };
50
51
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);
56
57 glEnable(GL_LIGHTING);
58 glEnable(GL_LIGHT0);
59 glEnable(GL_DEPTH_TEST);
60
61 glMatrixMode(GL_PROJECTION);
62 glLoadIdentity();
63 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
64 glMatrixMode(GL_MODELVIEW);
65
66 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
67
68 glPushMatrix();
69 glRotatef(20.0, 1.0, 0.0, 0.0);
70
71 glPushMatrix();
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);
76 glPopMatrix();
77
78 glPushMatrix();
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);
83 glPopMatrix();
84
85 #ifdef GL_HP_occlusion_test
86 if (perf == 0) {
87 GLboolean bRet;
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);
92
93 glPushMatrix();
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);
97 glPopMatrix();
98
99 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
100 printf("Occlusion test 1 (result should be 1): %d\n",bRet);
101
102 glDepthMask(GL_TRUE);
103 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
104 glDisable(GL_OCCLUSION_TEST_HP);
105 }
106 #endif
107
108 glPushMatrix();
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);
112 glPopMatrix();
113
114 #ifdef GL_HP_occlusion_test
115 if (perf == 0){
116 GLboolean bRet;
117
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);
122
123 /* draw a sphere inside the previous sphere */
124 glPushMatrix();
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);
128 glPopMatrix();
129
130 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
131 printf("Occlusion test 2 (result should be 0): %d\n",bRet);
132
133 glDepthMask(GL_TRUE);
134 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
135 glDisable(GL_OCCLUSION_TEST_HP);
136 }
137 #endif
138
139 glPopMatrix();
140
141 /* This is very important!!!
142 * Make sure buffered commands are finished!!!
143 */
144 glFinish();
145
146 Frames++;
147 if (perf) {
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);
153 T0 = t;
154 Frames = 0;
155 }
156 }
157 }
158
159
160 #ifdef SAVE_TARGA
161
162 static void
163 write_targa(const char *filename, const GLubyte *buffer, int width, int height)
164 {
165 FILE *f = fopen( filename, "w" );
166 if (f) {
167 int i, x, y;
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 */
175 fputc (0x00, f);
176 fputc (0x00, f);
177 fputc (0x00, f);
178 fputc (0x00, f); /* X-origin of Image */
179 fputc (0x00, f);
180 fputc (0x00, f); /* Y-origin of Image */
181 fputc (0x00, f);
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 */
188 fclose(f);
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 */
196 }
197 }
198 }
199 }
200
201 #else
202
203 static void
204 write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
205 {
206 const int binary = 0;
207 FILE *f = fopen( filename, "w" );
208 if (f) {
209 int i, x, y;
210 const GLubyte *ptr = buffer;
211 if (binary) {
212 fprintf(f,"P6\n");
213 fprintf(f,"# ppm-file created by osdemo.c\n");
214 fprintf(f,"%i %i\n", width,height);
215 fprintf(f,"255\n");
216 fclose(f);
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 */
224 }
225 }
226 }
227 else {
228 /*ASCII*/
229 int counter = 0;
230 fprintf(f,"P3\n");
231 fprintf(f,"# ascii ppm file created by osdemo.c\n");
232 fprintf(f,"%i %i\n", width, height);
233 fprintf(f,"255\n");
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]);
238 counter++;
239 if (counter % 5 == 0)
240 fprintf(f, "\n");
241 }
242 }
243 }
244 fclose(f);
245 }
246 }
247
248 #endif
249
250
251
252 int main( int argc, char *argv[] )
253 {
254 void *buffer;
255 int i;
256 char *filename = NULL;
257
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 );
262 #else
263 OSMesaContext ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
264 #endif
265 if (!ctx) {
266 printf("OSMesaCreateContext failed!\n");
267 return 0;
268 }
269
270 for ( i=1; i<argc; i++ ) {
271 if (argv[i][0] != '-') filename = argv[i];
272 if (strcmp(argv[i], "-perf")==0) perf = 1;
273 }
274
275 /* Allocate the image buffer */
276 buffer = malloc( WIDTH * HEIGHT * 4 * sizeof(GLubyte) );
277 if (!buffer) {
278 printf("Alloc image buffer failed!\n");
279 return 0;
280 }
281
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");
285 return 0;
286 }
287
288
289 {
290 int z, s, a;
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);
295 }
296
297 render_image();
298 if (perf)
299 for(i=0; i< 1000; i++)
300 render_image();
301
302 if (filename != NULL) {
303 #ifdef SAVE_TARGA
304 write_targa(filename, buffer, WIDTH, HEIGHT);
305 #else
306 write_ppm(filename, buffer, WIDTH, HEIGHT);
307 #endif
308 }
309 else {
310 printf("Specify a filename if you want to make an image file\n");
311 }
312
313 printf("all done\n");
314
315 /* free the image buffer */
316 free( buffer );
317
318 /* destroy the context */
319 OSMesaDestroyContext( ctx );
320
321 return 0;
322 }