blob: 22321cc10f1a135e388f77508a860aa2ecd85088 [file] [log] [blame]
Brian Paul07841822003-03-03 03:14:25 +00001/* $Id: osdemo.c,v 1.10 2003/03/03 03:14:25 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Demo of off-screen Mesa rendering
5 *
6 * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
7 *
8 * If you want to render BIG images you'll probably have to increase
9 * MAX_WIDTH and MAX_HEIGHT in src/config.h.
10 *
11 * This program is in the public domain.
12 *
13 * Brian Paul
14 *
15 * PPM output provided by Joerg Schmalzl.
16 * ASCII PPM output added by Brian Paul.
Karl Schultz17642ed2002-04-05 17:40:20 +000017 *
18 * Usage: osdemo [-perf] [filename]
19 *
20 * -perf: Redraws the image 1000 times, displaying the FPS every 5 secs.
21 * filename: file to store the TGA or PPM output
jtgafb833d1999-08-19 00:55:39 +000022 */
23
24
jtgafb833d1999-08-19 00:55:39 +000025#include <stdio.h>
26#include <stdlib.h>
Brian Paule2374912002-07-12 15:54:19 +000027#include <string.h>
jtgafb833d1999-08-19 00:55:39 +000028#include "GL/osmesa.h"
29#include "GL/glut.h"
30
31
Brian Paule02ffc12000-03-06 23:56:21 +000032#define SAVE_TARGA
33
jtgafb833d1999-08-19 00:55:39 +000034
35#define WIDTH 400
36#define HEIGHT 400
37
Karl Schultz17642ed2002-04-05 17:40:20 +000038static GLint T0 = 0;
39static GLint Frames = 0;
40static int perf = 0;
jtgafb833d1999-08-19 00:55:39 +000041
42static void render_image( void )
43{
44 GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
45 GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
46 GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
47 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
48 GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 };
49 GLfloat green_mat[] = { 0.2, 1.0, 0.2, 1.0 };
50 GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 };
51
52
53 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
54 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
55 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
56 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
57
58 glEnable(GL_LIGHTING);
59 glEnable(GL_LIGHT0);
60 glEnable(GL_DEPTH_TEST);
61
62 glMatrixMode(GL_PROJECTION);
63 glLoadIdentity();
64 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
65 glMatrixMode(GL_MODELVIEW);
66
67 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
68
69 glPushMatrix();
70 glRotatef(20.0, 1.0, 0.0, 0.0);
71
72 glPushMatrix();
73 glTranslatef(-0.75, 0.5, 0.0);
74 glRotatef(90.0, 1.0, 0.0, 0.0);
75 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
76 glutSolidTorus(0.275, 0.85, 20, 20);
77 glPopMatrix();
78
79 glPushMatrix();
80 glTranslatef(-0.75, -0.5, 0.0);
81 glRotatef(270.0, 1.0, 0.0, 0.0);
82 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
83 glutSolidCone(1.0, 2.0, 16, 1);
84 glPopMatrix();
85
Randy Frank23ee0492000-03-28 16:59:39 +000086#ifdef GL_HP_occlusion_test
Karl Schultz17642ed2002-04-05 17:40:20 +000087 if (perf == 0) {
Randy Franked236aa2000-01-15 06:11:33 +000088 GLboolean bRet;
Randy Franked236aa2000-01-15 06:11:33 +000089 glDepthMask(GL_FALSE);
90 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
Randy Frank23ee0492000-03-28 16:59:39 +000091 glEnable(GL_OCCLUSION_TEST_HP);
92 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +000093
94 glPushMatrix();
Randy Frank23ee0492000-03-28 16:59:39 +000095 glTranslatef(0.75, 0.0, -1.0);
Randy Franked236aa2000-01-15 06:11:33 +000096 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
97 glutSolidSphere(1.0, 20, 20);
98 glPopMatrix();
99
Randy Frank23ee0492000-03-28 16:59:39 +0000100 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000101 printf("Occlusion test 1 (result should be 1): %d\n",bRet);
102
103 glDepthMask(GL_TRUE);
104 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
Randy Frank23ee0492000-03-28 16:59:39 +0000105 glDisable(GL_OCCLUSION_TEST_HP);
Randy Franked236aa2000-01-15 06:11:33 +0000106 }
107#endif
108
jtgafb833d1999-08-19 00:55:39 +0000109 glPushMatrix();
110 glTranslatef(0.75, 0.0, -1.0);
111 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
112 glutSolidSphere(1.0, 20, 20);
113 glPopMatrix();
114
Randy Frank23ee0492000-03-28 16:59:39 +0000115#ifdef GL_HP_occlusion_test
Karl Schultz17642ed2002-04-05 17:40:20 +0000116 if (perf == 0){
Randy Franked236aa2000-01-15 06:11:33 +0000117 GLboolean bRet;
118
Randy Franked236aa2000-01-15 06:11:33 +0000119 glDepthMask(GL_FALSE);
120 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
Randy Frank23ee0492000-03-28 16:59:39 +0000121 glEnable(GL_OCCLUSION_TEST_HP);
122 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000123
124 /* draw a sphere inside the previous sphere */
125 glPushMatrix();
Randy Frank23ee0492000-03-28 16:59:39 +0000126 glTranslatef(0.75, 0.0, -1.0);
Randy Franked236aa2000-01-15 06:11:33 +0000127 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
128 glutSolidSphere(0.5, 20, 20);
129 glPopMatrix();
130
Randy Frank23ee0492000-03-28 16:59:39 +0000131 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000132 printf("Occlusion test 2 (result should be 0): %d\n",bRet);
133
134 glDepthMask(GL_TRUE);
135 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
Randy Frank23ee0492000-03-28 16:59:39 +0000136 glDisable(GL_OCCLUSION_TEST_HP);
Randy Franked236aa2000-01-15 06:11:33 +0000137 }
138#endif
139
jtgafb833d1999-08-19 00:55:39 +0000140 glPopMatrix();
Karl Schultz17642ed2002-04-05 17:40:20 +0000141
Brian Paul07841822003-03-03 03:14:25 +0000142 /* This is very important!!!
143 * Make sure buffered commands are finished!!!
144 */
145 glFinish();
146
Karl Schultz17642ed2002-04-05 17:40:20 +0000147 Frames++;
148 if (perf) {
149 GLint t = glutGet(GLUT_ELAPSED_TIME);
150 if (t - T0 >= 5000) {
151 GLfloat seconds = (t - T0) / 1000.0;
152 GLfloat fps = Frames / seconds;
153 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
154 T0 = t;
155 Frames = 0;
156 }
157 }
jtgafb833d1999-08-19 00:55:39 +0000158}
159
160
Brian Paule2374912002-07-12 15:54:19 +0000161#ifdef SAVE_TARGA
jtgafb833d1999-08-19 00:55:39 +0000162
Brian Paule02ffc12000-03-06 23:56:21 +0000163static void
164write_targa(const char *filename, const GLubyte *buffer, int width, int height)
165{
166 FILE *f = fopen( filename, "w" );
167 if (f) {
168 int i, x, y;
169 const GLubyte *ptr = buffer;
170 printf ("osdemo, writing tga file \n");
171 fputc (0x00, f); /* ID Length, 0 => No ID */
172 fputc (0x00, f); /* Color Map Type, 0 => No color map included */
173 fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */
174 fputc (0x00, f); /* Next five bytes are about the color map entries */
175 fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */
176 fputc (0x00, f);
177 fputc (0x00, f);
178 fputc (0x00, f);
179 fputc (0x00, f); /* X-origin of Image */
180 fputc (0x00, f);
181 fputc (0x00, f); /* Y-origin of Image */
182 fputc (0x00, f);
183 fputc (WIDTH & 0xff, f); /* Image Width */
184 fputc ((WIDTH>>8) & 0xff, f);
185 fputc (HEIGHT & 0xff, f); /* Image Height */
186 fputc ((HEIGHT>>8) & 0xff, f);
187 fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */
188 fputc (0x20, f); /* Image Descriptor */
189 fclose(f);
190 f = fopen( filename, "ab" ); /* reopen in binary append mode */
191 for (y=height-1; y>=0; y--) {
192 for (x=0; x<width; x++) {
193 i = (y*width + x) * 4;
194 fputc(ptr[i+2], f); /* write blue */
195 fputc(ptr[i+1], f); /* write green */
196 fputc(ptr[i], f); /* write red */
197 }
198 }
199 }
200}
201
Brian Paule2374912002-07-12 15:54:19 +0000202#else
Brian Paule02ffc12000-03-06 23:56:21 +0000203
204static void
205write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
206{
207 const int binary = 0;
208 FILE *f = fopen( filename, "w" );
209 if (f) {
210 int i, x, y;
211 const GLubyte *ptr = buffer;
212 if (binary) {
213 fprintf(f,"P6\n");
214 fprintf(f,"# ppm-file created by osdemo.c\n");
215 fprintf(f,"%i %i\n", width,height);
216 fprintf(f,"255\n");
217 fclose(f);
218 f = fopen( filename, "ab" ); /* reopen in binary append mode */
219 for (y=height-1; y>=0; y--) {
220 for (x=0; x<width; x++) {
221 i = (y*width + x) * 4;
222 fputc(ptr[i], f); /* write red */
223 fputc(ptr[i+1], f); /* write green */
224 fputc(ptr[i+2], f); /* write blue */
225 }
226 }
227 }
228 else {
229 /*ASCII*/
230 int counter = 0;
231 fprintf(f,"P3\n");
232 fprintf(f,"# ascii ppm file created by osdemo.c\n");
233 fprintf(f,"%i %i\n", width, height);
234 fprintf(f,"255\n");
235 for (y=height-1; y>=0; y--) {
236 for (x=0; x<width; x++) {
237 i = (y*width + x) * 4;
238 fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]);
239 counter++;
240 if (counter % 5 == 0)
241 fprintf(f, "\n");
242 }
243 }
244 }
245 fclose(f);
246 }
247}
248
Brian Paule2374912002-07-12 15:54:19 +0000249#endif
250
Brian Paule02ffc12000-03-06 23:56:21 +0000251
252
jtgafb833d1999-08-19 00:55:39 +0000253int main( int argc, char *argv[] )
254{
Brian Paul46dbaec2000-09-08 16:42:06 +0000255 void *buffer;
Karl Schultz17642ed2002-04-05 17:40:20 +0000256 int i;
257 char *filename = NULL;
Brian Paul46dbaec2000-09-08 16:42:06 +0000258
jtgafb833d1999-08-19 00:55:39 +0000259 /* Create an RGBA-mode context */
Brian Paul46dbaec2000-09-08 16:42:06 +0000260#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
261 /* specify Z, stencil, accum sizes */
Karl Schultz220e77a2001-09-24 15:29:27 +0000262 OSMesaContext ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000263#else
Karl Schultz220e77a2001-09-24 15:29:27 +0000264 OSMesaContext ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000265#endif
266 if (!ctx) {
267 printf("OSMesaCreateContext failed!\n");
268 return 0;
269 }
jtgafb833d1999-08-19 00:55:39 +0000270
Karl Schultz17642ed2002-04-05 17:40:20 +0000271 for ( i=1; i<argc; i++ ) {
272 if (argv[i][0] != '-') filename = argv[i];
273 if (strcmp(argv[i], "-perf")==0) perf = 1;
274 }
275
jtgafb833d1999-08-19 00:55:39 +0000276 /* Allocate the image buffer */
Brian Paul601ce1d2001-07-13 20:09:18 +0000277 buffer = malloc( WIDTH * HEIGHT * 4 * sizeof(GLubyte) );
Brian Paul46dbaec2000-09-08 16:42:06 +0000278 if (!buffer) {
279 printf("Alloc image buffer failed!\n");
280 return 0;
281 }
jtgafb833d1999-08-19 00:55:39 +0000282
283 /* Bind the buffer to the context and make it current */
Brian Paul601ce1d2001-07-13 20:09:18 +0000284 if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, WIDTH, HEIGHT )) {
285 printf("OSMesaMakeCurrent failed!\n");
286 return 0;
287 }
288
jtgafb833d1999-08-19 00:55:39 +0000289
Brian Paul46dbaec2000-09-08 16:42:06 +0000290 {
291 int z, s, a;
292 glGetIntegerv(GL_DEPTH_BITS, &z);
293 glGetIntegerv(GL_STENCIL_BITS, &s);
294 glGetIntegerv(GL_ACCUM_RED_BITS, &a);
Karl Schultz17642ed2002-04-05 17:40:20 +0000295 printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
Brian Paul46dbaec2000-09-08 16:42:06 +0000296 }
297
jtgafb833d1999-08-19 00:55:39 +0000298 render_image();
Karl Schultz17642ed2002-04-05 17:40:20 +0000299 if (perf)
300 for(i=0; i< 1000; i++)
301 render_image();
jtgafb833d1999-08-19 00:55:39 +0000302
Karl Schultz17642ed2002-04-05 17:40:20 +0000303 if (filename != NULL) {
Brian Paule02ffc12000-03-06 23:56:21 +0000304#ifdef SAVE_TARGA
Karl Schultz17642ed2002-04-05 17:40:20 +0000305 write_targa(filename, buffer, WIDTH, HEIGHT);
Brian Paule02ffc12000-03-06 23:56:21 +0000306#else
Karl Schultz17642ed2002-04-05 17:40:20 +0000307 write_ppm(filename, buffer, WIDTH, HEIGHT);
jtgafb833d1999-08-19 00:55:39 +0000308#endif
jtgafb833d1999-08-19 00:55:39 +0000309 }
310 else {
Brian Paule02ffc12000-03-06 23:56:21 +0000311 printf("Specify a filename if you want to make an image file\n");
jtgafb833d1999-08-19 00:55:39 +0000312 }
313
314 printf("all done\n");
315
316 /* free the image buffer */
317 free( buffer );
318
319 /* destroy the context */
320 OSMesaDestroyContext( ctx );
321
322 return 0;
323}