Merge branch 'mesa_7_7_branch'
[mesa.git] / progs / osdemos / osdemo.c
1 /*
2 * Demo of off-screen Mesa rendering
3 *
4 * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
5 *
6 * If you want to render BIG images you'll probably have to increase
7 * MAX_WIDTH and MAX_Height in src/config.h.
8 *
9 * This program is in the public domain.
10 *
11 * Brian Paul
12 *
13 * PPM output provided by Joerg Schmalzl.
14 * ASCII PPM output added by Brian Paul.
15 *
16 * Usage: osdemo [filename]
17 */
18
19
20 #include <math.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "GL/osmesa.h"
25 #include "GL/glu.h"
26
27
28 #define SAVE_TARGA
29
30 static int Width = 400;
31 static int Height = 400;
32
33
34 static void
35 Sphere(float radius, int slices, int stacks)
36 {
37 GLUquadric *q = gluNewQuadric();
38 gluQuadricNormals(q, GLU_SMOOTH);
39 gluSphere(q, radius, slices, stacks);
40 gluDeleteQuadric(q);
41 }
42
43
44 static void
45 Cone(float base, float height, int slices, int stacks)
46 {
47 GLUquadric *q = gluNewQuadric();
48 gluQuadricDrawStyle(q, GLU_FILL);
49 gluQuadricNormals(q, GLU_SMOOTH);
50 gluCylinder(q, base, 0.0, height, slices, stacks);
51 gluDeleteQuadric(q);
52 }
53
54
55 static void
56 Torus(float innerRadius, float outerRadius, int sides, int rings)
57 {
58 /* from GLUT... */
59 int i, j;
60 GLfloat theta, phi, theta1;
61 GLfloat cosTheta, sinTheta;
62 GLfloat cosTheta1, sinTheta1;
63 const GLfloat ringDelta = 2.0 * M_PI / rings;
64 const GLfloat sideDelta = 2.0 * M_PI / sides;
65
66 theta = 0.0;
67 cosTheta = 1.0;
68 sinTheta = 0.0;
69 for (i = rings - 1; i >= 0; i--) {
70 theta1 = theta + ringDelta;
71 cosTheta1 = cos(theta1);
72 sinTheta1 = sin(theta1);
73 glBegin(GL_QUAD_STRIP);
74 phi = 0.0;
75 for (j = sides; j >= 0; j--) {
76 GLfloat cosPhi, sinPhi, dist;
77
78 phi += sideDelta;
79 cosPhi = cos(phi);
80 sinPhi = sin(phi);
81 dist = outerRadius + innerRadius * cosPhi;
82
83 glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
84 glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi);
85 glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
86 glVertex3f(cosTheta * dist, -sinTheta * dist, innerRadius * sinPhi);
87 }
88 glEnd();
89 theta = theta1;
90 cosTheta = cosTheta1;
91 sinTheta = sinTheta1;
92 }
93 }
94
95
96 static void
97 render_image(void)
98 {
99 GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
100 GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
101 GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
102 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
103 GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 };
104 GLfloat green_mat[] = { 0.2, 1.0, 0.2, 1.0 };
105 GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 };
106
107
108 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
109 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
110 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
111 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
112
113 glEnable(GL_LIGHTING);
114 glEnable(GL_LIGHT0);
115 glEnable(GL_DEPTH_TEST);
116
117 glMatrixMode(GL_PROJECTION);
118 glLoadIdentity();
119 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
120 glMatrixMode(GL_MODELVIEW);
121
122 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
123
124 glPushMatrix();
125 glRotatef(20.0, 1.0, 0.0, 0.0);
126
127 glPushMatrix();
128 glTranslatef(-0.75, 0.5, 0.0);
129 glRotatef(90.0, 1.0, 0.0, 0.0);
130 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
131 Torus(0.275, 0.85, 20, 20);
132 glPopMatrix();
133
134 glPushMatrix();
135 glTranslatef(-0.75, -0.5, 0.0);
136 glRotatef(270.0, 1.0, 0.0, 0.0);
137 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
138 Cone(1.0, 2.0, 16, 1);
139 glPopMatrix();
140
141 glPushMatrix();
142 glTranslatef(0.75, 0.0, -1.0);
143 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
144 Sphere(1.0, 20, 20);
145 glPopMatrix();
146
147 glPopMatrix();
148
149 /* This is very important!!!
150 * Make sure buffered commands are finished!!!
151 */
152 glFinish();
153 }
154
155
156 #ifdef SAVE_TARGA
157
158 static void
159 write_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
197 #else
198
199 static void
200 write_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
244 #endif
245
246
247
248 int
249 main(int argc, char *argv[])
250 {
251 OSMesaContext ctx;
252 void *buffer;
253 char *filename = NULL;
254
255 if (argc < 2) {
256 fprintf(stderr, "Usage:\n");
257 fprintf(stderr, " osdemo filename [width height]\n");
258 return 0;
259 }
260
261 filename = argv[1];
262 if (argc == 4) {
263 Width = atoi(argv[2]);
264 Height = atoi(argv[3]);
265 }
266
267 /* Create an RGBA-mode context */
268 #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
269 /* specify Z, stencil, accum sizes */
270 ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
271 #else
272 ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
273 #endif
274 if (!ctx) {
275 printf("OSMesaCreateContext failed!\n");
276 return 0;
277 }
278
279 /* Allocate the image buffer */
280 buffer = malloc( Width * Height * 4 * sizeof(GLubyte) );
281 if (!buffer) {
282 printf("Alloc image buffer failed!\n");
283 return 0;
284 }
285
286 /* Bind the buffer to the context and make it current */
287 if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, Width, Height )) {
288 printf("OSMesaMakeCurrent failed!\n");
289 return 0;
290 }
291
292
293 {
294 int z, s, a;
295 glGetIntegerv(GL_DEPTH_BITS, &z);
296 glGetIntegerv(GL_STENCIL_BITS, &s);
297 glGetIntegerv(GL_ACCUM_RED_BITS, &a);
298 printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
299 }
300
301 render_image();
302
303 if (filename != NULL) {
304 #ifdef SAVE_TARGA
305 write_targa(filename, buffer, Width, Height);
306 #else
307 write_ppm(filename, buffer, Width, Height);
308 #endif
309 }
310 else {
311 printf("Specify a filename if you want to make an image file\n");
312 }
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 }