blob: 25632bc276003d02cd88442085990d1473606c32 [file] [log] [blame]
Brian Paule2374912002-07-12 15:54:19 +00001/* $Id: osdemo.c,v 1.9 2002/07/12 15:54:19 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
142 Frames++;
143 if (perf) {
144 GLint t = glutGet(GLUT_ELAPSED_TIME);
145 if (t - T0 >= 5000) {
146 GLfloat seconds = (t - T0) / 1000.0;
147 GLfloat fps = Frames / seconds;
148 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
149 T0 = t;
150 Frames = 0;
151 }
152 }
jtgafb833d1999-08-19 00:55:39 +0000153}
154
155
Brian Paule2374912002-07-12 15:54:19 +0000156#ifdef SAVE_TARGA
jtgafb833d1999-08-19 00:55:39 +0000157
Brian Paule02ffc12000-03-06 23:56:21 +0000158static void
159write_targa(const char *filename, const GLubyte *buffer, int width, int height)
160{
161 FILE *f = fopen( filename, "w" );
162 if (f) {
163 int i, x, y;
164 const GLubyte *ptr = buffer;
165 printf ("osdemo, writing tga file \n");
166 fputc (0x00, f); /* ID Length, 0 => No ID */
167 fputc (0x00, f); /* Color Map Type, 0 => No color map included */
168 fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */
169 fputc (0x00, f); /* Next five bytes are about the color map entries */
170 fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */
171 fputc (0x00, f);
172 fputc (0x00, f);
173 fputc (0x00, f);
174 fputc (0x00, f); /* X-origin of Image */
175 fputc (0x00, f);
176 fputc (0x00, f); /* Y-origin of Image */
177 fputc (0x00, f);
178 fputc (WIDTH & 0xff, f); /* Image Width */
179 fputc ((WIDTH>>8) & 0xff, f);
180 fputc (HEIGHT & 0xff, f); /* Image Height */
181 fputc ((HEIGHT>>8) & 0xff, f);
182 fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */
183 fputc (0x20, f); /* Image Descriptor */
184 fclose(f);
185 f = fopen( filename, "ab" ); /* reopen in binary append mode */
186 for (y=height-1; y>=0; y--) {
187 for (x=0; x<width; x++) {
188 i = (y*width + x) * 4;
189 fputc(ptr[i+2], f); /* write blue */
190 fputc(ptr[i+1], f); /* write green */
191 fputc(ptr[i], f); /* write red */
192 }
193 }
194 }
195}
196
Brian Paule2374912002-07-12 15:54:19 +0000197#else
Brian Paule02ffc12000-03-06 23:56:21 +0000198
199static void
200write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
201{
202 const int binary = 0;
203 FILE *f = fopen( filename, "w" );
204 if (f) {
205 int i, x, y;
206 const GLubyte *ptr = buffer;
207 if (binary) {
208 fprintf(f,"P6\n");
209 fprintf(f,"# ppm-file created by osdemo.c\n");
210 fprintf(f,"%i %i\n", width,height);
211 fprintf(f,"255\n");
212 fclose(f);
213 f = fopen( filename, "ab" ); /* reopen in binary append mode */
214 for (y=height-1; y>=0; y--) {
215 for (x=0; x<width; x++) {
216 i = (y*width + x) * 4;
217 fputc(ptr[i], f); /* write red */
218 fputc(ptr[i+1], f); /* write green */
219 fputc(ptr[i+2], f); /* write blue */
220 }
221 }
222 }
223 else {
224 /*ASCII*/
225 int counter = 0;
226 fprintf(f,"P3\n");
227 fprintf(f,"# ascii ppm file created by osdemo.c\n");
228 fprintf(f,"%i %i\n", width, height);
229 fprintf(f,"255\n");
230 for (y=height-1; y>=0; y--) {
231 for (x=0; x<width; x++) {
232 i = (y*width + x) * 4;
233 fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]);
234 counter++;
235 if (counter % 5 == 0)
236 fprintf(f, "\n");
237 }
238 }
239 }
240 fclose(f);
241 }
242}
243
Brian Paule2374912002-07-12 15:54:19 +0000244#endif
245
Brian Paule02ffc12000-03-06 23:56:21 +0000246
247
jtgafb833d1999-08-19 00:55:39 +0000248int main( int argc, char *argv[] )
249{
Brian Paul46dbaec2000-09-08 16:42:06 +0000250 void *buffer;
Karl Schultz17642ed2002-04-05 17:40:20 +0000251 int i;
252 char *filename = NULL;
Brian Paul46dbaec2000-09-08 16:42:06 +0000253
jtgafb833d1999-08-19 00:55:39 +0000254 /* Create an RGBA-mode context */
Brian Paul46dbaec2000-09-08 16:42:06 +0000255#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
256 /* specify Z, stencil, accum sizes */
Karl Schultz220e77a2001-09-24 15:29:27 +0000257 OSMesaContext ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000258#else
Karl Schultz220e77a2001-09-24 15:29:27 +0000259 OSMesaContext ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000260#endif
261 if (!ctx) {
262 printf("OSMesaCreateContext failed!\n");
263 return 0;
264 }
jtgafb833d1999-08-19 00:55:39 +0000265
Karl Schultz17642ed2002-04-05 17:40:20 +0000266 for ( i=1; i<argc; i++ ) {
267 if (argv[i][0] != '-') filename = argv[i];
268 if (strcmp(argv[i], "-perf")==0) perf = 1;
269 }
270
jtgafb833d1999-08-19 00:55:39 +0000271 /* Allocate the image buffer */
Brian Paul601ce1d2001-07-13 20:09:18 +0000272 buffer = malloc( WIDTH * HEIGHT * 4 * sizeof(GLubyte) );
Brian Paul46dbaec2000-09-08 16:42:06 +0000273 if (!buffer) {
274 printf("Alloc image buffer failed!\n");
275 return 0;
276 }
jtgafb833d1999-08-19 00:55:39 +0000277
278 /* Bind the buffer to the context and make it current */
Brian Paul601ce1d2001-07-13 20:09:18 +0000279 if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, WIDTH, HEIGHT )) {
280 printf("OSMesaMakeCurrent failed!\n");
281 return 0;
282 }
283
jtgafb833d1999-08-19 00:55:39 +0000284
Brian Paul46dbaec2000-09-08 16:42:06 +0000285 {
286 int z, s, a;
287 glGetIntegerv(GL_DEPTH_BITS, &z);
288 glGetIntegerv(GL_STENCIL_BITS, &s);
289 glGetIntegerv(GL_ACCUM_RED_BITS, &a);
Karl Schultz17642ed2002-04-05 17:40:20 +0000290 printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
Brian Paul46dbaec2000-09-08 16:42:06 +0000291 }
292
jtgafb833d1999-08-19 00:55:39 +0000293 render_image();
Karl Schultz17642ed2002-04-05 17:40:20 +0000294 if (perf)
295 for(i=0; i< 1000; i++)
296 render_image();
jtgafb833d1999-08-19 00:55:39 +0000297
Karl Schultz17642ed2002-04-05 17:40:20 +0000298 if (filename != NULL) {
Brian Paule02ffc12000-03-06 23:56:21 +0000299#ifdef SAVE_TARGA
Karl Schultz17642ed2002-04-05 17:40:20 +0000300 write_targa(filename, buffer, WIDTH, HEIGHT);
Brian Paule02ffc12000-03-06 23:56:21 +0000301#else
Karl Schultz17642ed2002-04-05 17:40:20 +0000302 write_ppm(filename, buffer, WIDTH, HEIGHT);
jtgafb833d1999-08-19 00:55:39 +0000303#endif
jtgafb833d1999-08-19 00:55:39 +0000304 }
305 else {
Brian Paule02ffc12000-03-06 23:56:21 +0000306 printf("Specify a filename if you want to make an image file\n");
jtgafb833d1999-08-19 00:55:39 +0000307 }
308
309 printf("all done\n");
310
311 /* free the image buffer */
312 free( buffer );
313
314 /* destroy the context */
315 OSMesaDestroyContext( ctx );
316
317 return 0;
318}