blob: 1827e867d64bbeb0d396969405becedf64a883e1 [file] [log] [blame]
Karl Schultz17642ed2002-04-05 17:40:20 +00001/* $Id: osdemo.c,v 1.8 2002/04/05 17:40:20 kschultz 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>
27#include "GL/osmesa.h"
28#include "GL/glut.h"
29
30
Brian Paule02ffc12000-03-06 23:56:21 +000031#define SAVE_TARGA
32
jtgafb833d1999-08-19 00:55:39 +000033
34#define WIDTH 400
35#define HEIGHT 400
36
Karl Schultz17642ed2002-04-05 17:40:20 +000037static GLint T0 = 0;
38static GLint Frames = 0;
39static int perf = 0;
jtgafb833d1999-08-19 00:55:39 +000040
41static 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
Randy Frank23ee0492000-03-28 16:59:39 +000085#ifdef GL_HP_occlusion_test
Karl Schultz17642ed2002-04-05 17:40:20 +000086 if (perf == 0) {
Randy Franked236aa2000-01-15 06:11:33 +000087 GLboolean bRet;
Randy Franked236aa2000-01-15 06:11:33 +000088 glDepthMask(GL_FALSE);
89 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
Randy Frank23ee0492000-03-28 16:59:39 +000090 glEnable(GL_OCCLUSION_TEST_HP);
91 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +000092
93 glPushMatrix();
Randy Frank23ee0492000-03-28 16:59:39 +000094 glTranslatef(0.75, 0.0, -1.0);
Randy Franked236aa2000-01-15 06:11:33 +000095 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
96 glutSolidSphere(1.0, 20, 20);
97 glPopMatrix();
98
Randy Frank23ee0492000-03-28 16:59:39 +000099 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000100 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);
Randy Frank23ee0492000-03-28 16:59:39 +0000104 glDisable(GL_OCCLUSION_TEST_HP);
Randy Franked236aa2000-01-15 06:11:33 +0000105 }
106#endif
107
jtgafb833d1999-08-19 00:55:39 +0000108 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
Randy Frank23ee0492000-03-28 16:59:39 +0000114#ifdef GL_HP_occlusion_test
Karl Schultz17642ed2002-04-05 17:40:20 +0000115 if (perf == 0){
Randy Franked236aa2000-01-15 06:11:33 +0000116 GLboolean bRet;
117
Randy Franked236aa2000-01-15 06:11:33 +0000118 glDepthMask(GL_FALSE);
119 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
Randy Frank23ee0492000-03-28 16:59:39 +0000120 glEnable(GL_OCCLUSION_TEST_HP);
121 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000122
123 /* draw a sphere inside the previous sphere */
124 glPushMatrix();
Randy Frank23ee0492000-03-28 16:59:39 +0000125 glTranslatef(0.75, 0.0, -1.0);
Randy Franked236aa2000-01-15 06:11:33 +0000126 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
127 glutSolidSphere(0.5, 20, 20);
128 glPopMatrix();
129
Randy Frank23ee0492000-03-28 16:59:39 +0000130 glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP,&bRet);
Randy Franked236aa2000-01-15 06:11:33 +0000131 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);
Randy Frank23ee0492000-03-28 16:59:39 +0000135 glDisable(GL_OCCLUSION_TEST_HP);
Randy Franked236aa2000-01-15 06:11:33 +0000136 }
137#endif
138
jtgafb833d1999-08-19 00:55:39 +0000139 glPopMatrix();
Karl Schultz17642ed2002-04-05 17:40:20 +0000140
141 Frames++;
142 if (perf) {
143 GLint t = glutGet(GLUT_ELAPSED_TIME);
144 if (t - T0 >= 5000) {
145 GLfloat seconds = (t - T0) / 1000.0;
146 GLfloat fps = Frames / seconds;
147 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
148 T0 = t;
149 Frames = 0;
150 }
151 }
jtgafb833d1999-08-19 00:55:39 +0000152}
153
154
155
Brian Paule02ffc12000-03-06 23:56:21 +0000156static void
157write_targa(const char *filename, const GLubyte *buffer, int width, int height)
158{
159 FILE *f = fopen( filename, "w" );
160 if (f) {
161 int i, x, y;
162 const GLubyte *ptr = buffer;
163 printf ("osdemo, writing tga file \n");
164 fputc (0x00, f); /* ID Length, 0 => No ID */
165 fputc (0x00, f); /* Color Map Type, 0 => No color map included */
166 fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */
167 fputc (0x00, f); /* Next five bytes are about the color map entries */
168 fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */
169 fputc (0x00, f);
170 fputc (0x00, f);
171 fputc (0x00, f);
172 fputc (0x00, f); /* X-origin of Image */
173 fputc (0x00, f);
174 fputc (0x00, f); /* Y-origin of Image */
175 fputc (0x00, f);
176 fputc (WIDTH & 0xff, f); /* Image Width */
177 fputc ((WIDTH>>8) & 0xff, f);
178 fputc (HEIGHT & 0xff, f); /* Image Height */
179 fputc ((HEIGHT>>8) & 0xff, f);
180 fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */
181 fputc (0x20, f); /* Image Descriptor */
182 fclose(f);
183 f = fopen( filename, "ab" ); /* reopen in binary append mode */
184 for (y=height-1; y>=0; y--) {
185 for (x=0; x<width; x++) {
186 i = (y*width + x) * 4;
187 fputc(ptr[i+2], f); /* write blue */
188 fputc(ptr[i+1], f); /* write green */
189 fputc(ptr[i], f); /* write red */
190 }
191 }
192 }
193}
194
195
196static void
197write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
198{
199 const int binary = 0;
200 FILE *f = fopen( filename, "w" );
201 if (f) {
202 int i, x, y;
203 const GLubyte *ptr = buffer;
204 if (binary) {
205 fprintf(f,"P6\n");
206 fprintf(f,"# ppm-file created by osdemo.c\n");
207 fprintf(f,"%i %i\n", width,height);
208 fprintf(f,"255\n");
209 fclose(f);
210 f = fopen( filename, "ab" ); /* reopen in binary append mode */
211 for (y=height-1; y>=0; y--) {
212 for (x=0; x<width; x++) {
213 i = (y*width + x) * 4;
214 fputc(ptr[i], f); /* write red */
215 fputc(ptr[i+1], f); /* write green */
216 fputc(ptr[i+2], f); /* write blue */
217 }
218 }
219 }
220 else {
221 /*ASCII*/
222 int counter = 0;
223 fprintf(f,"P3\n");
224 fprintf(f,"# ascii ppm file created by osdemo.c\n");
225 fprintf(f,"%i %i\n", width, height);
226 fprintf(f,"255\n");
227 for (y=height-1; y>=0; y--) {
228 for (x=0; x<width; x++) {
229 i = (y*width + x) * 4;
230 fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]);
231 counter++;
232 if (counter % 5 == 0)
233 fprintf(f, "\n");
234 }
235 }
236 }
237 fclose(f);
238 }
239}
240
241
242
jtgafb833d1999-08-19 00:55:39 +0000243int main( int argc, char *argv[] )
244{
Brian Paul46dbaec2000-09-08 16:42:06 +0000245 void *buffer;
Karl Schultz17642ed2002-04-05 17:40:20 +0000246 int i;
247 char *filename = NULL;
Brian Paul46dbaec2000-09-08 16:42:06 +0000248
jtgafb833d1999-08-19 00:55:39 +0000249 /* Create an RGBA-mode context */
Brian Paul46dbaec2000-09-08 16:42:06 +0000250#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
251 /* specify Z, stencil, accum sizes */
Karl Schultz220e77a2001-09-24 15:29:27 +0000252 OSMesaContext ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000253#else
Karl Schultz220e77a2001-09-24 15:29:27 +0000254 OSMesaContext ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000255#endif
256 if (!ctx) {
257 printf("OSMesaCreateContext failed!\n");
258 return 0;
259 }
jtgafb833d1999-08-19 00:55:39 +0000260
Karl Schultz17642ed2002-04-05 17:40:20 +0000261 for ( i=1; i<argc; i++ ) {
262 if (argv[i][0] != '-') filename = argv[i];
263 if (strcmp(argv[i], "-perf")==0) perf = 1;
264 }
265
jtgafb833d1999-08-19 00:55:39 +0000266 /* Allocate the image buffer */
Brian Paul601ce1d2001-07-13 20:09:18 +0000267 buffer = malloc( WIDTH * HEIGHT * 4 * sizeof(GLubyte) );
Brian Paul46dbaec2000-09-08 16:42:06 +0000268 if (!buffer) {
269 printf("Alloc image buffer failed!\n");
270 return 0;
271 }
jtgafb833d1999-08-19 00:55:39 +0000272
273 /* Bind the buffer to the context and make it current */
Brian Paul601ce1d2001-07-13 20:09:18 +0000274 if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, WIDTH, HEIGHT )) {
275 printf("OSMesaMakeCurrent failed!\n");
276 return 0;
277 }
278
jtgafb833d1999-08-19 00:55:39 +0000279
Brian Paul46dbaec2000-09-08 16:42:06 +0000280 {
281 int z, s, a;
282 glGetIntegerv(GL_DEPTH_BITS, &z);
283 glGetIntegerv(GL_STENCIL_BITS, &s);
284 glGetIntegerv(GL_ACCUM_RED_BITS, &a);
Karl Schultz17642ed2002-04-05 17:40:20 +0000285 printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
Brian Paul46dbaec2000-09-08 16:42:06 +0000286 }
287
jtgafb833d1999-08-19 00:55:39 +0000288 render_image();
Karl Schultz17642ed2002-04-05 17:40:20 +0000289 if (perf)
290 for(i=0; i< 1000; i++)
291 render_image();
jtgafb833d1999-08-19 00:55:39 +0000292
Karl Schultz17642ed2002-04-05 17:40:20 +0000293 if (filename != NULL) {
Brian Paule02ffc12000-03-06 23:56:21 +0000294#ifdef SAVE_TARGA
Karl Schultz17642ed2002-04-05 17:40:20 +0000295 write_targa(filename, buffer, WIDTH, HEIGHT);
Brian Paule02ffc12000-03-06 23:56:21 +0000296#else
Karl Schultz17642ed2002-04-05 17:40:20 +0000297 write_ppm(filename, buffer, WIDTH, HEIGHT);
jtgafb833d1999-08-19 00:55:39 +0000298#endif
jtgafb833d1999-08-19 00:55:39 +0000299 }
300 else {
Brian Paule02ffc12000-03-06 23:56:21 +0000301 printf("Specify a filename if you want to make an image file\n");
jtgafb833d1999-08-19 00:55:39 +0000302 }
303
304 printf("all done\n");
305
306 /* free the image buffer */
307 free( buffer );
308
309 /* destroy the context */
310 OSMesaDestroyContext( ctx );
311
312 return 0;
313}