progs/tests: also test stencil INCR_WRAP mode if supported
[mesa.git] / progs / tests / auxbuffer.c
1 /*
2 * Test AUX buffer rendering
3 * Use GLX since GLUT doesn't support AUX buffers
4 */
5
6
7 /*
8 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 /*
29 * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
30 * Port by Brian Paul 23 March 2001
31 *
32 * Command line options:
33 * -info print GL implementation information
34 *
35 */
36
37
38 #include <math.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <X11/Xlib.h>
43 #include <X11/keysym.h>
44 #include <GL/gl.h>
45 #include <GL/glx.h>
46
47
48 static int
49 current_time(void)
50 {
51 return 0;
52 }
53
54
55
56
57 #ifndef M_PI
58 #define M_PI 3.14159265
59 #endif
60
61 static int WinWidth = 300, WinHeight = 300;
62 static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
63 static GLint gear1, gear2, gear3;
64 static GLfloat angle = 0.0;
65
66
67 /*
68 *
69 * Draw a gear wheel. You'll probably want to call this function when
70 * building a display list since we do a lot of trig here.
71 *
72 * Input: inner_radius - radius of hole at center
73 * outer_radius - radius at center of teeth
74 * width - width of gear
75 * teeth - number of teeth
76 * tooth_depth - depth of tooth
77 */
78 static void
79 gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
80 GLint teeth, GLfloat tooth_depth)
81 {
82 GLint i;
83 GLfloat r0, r1, r2;
84 GLfloat angle, da;
85 GLfloat u, v, len;
86
87 r0 = inner_radius;
88 r1 = outer_radius - tooth_depth / 2.0;
89 r2 = outer_radius + tooth_depth / 2.0;
90
91 da = 2.0 * M_PI / teeth / 4.0;
92
93 glShadeModel(GL_FLAT);
94
95 glNormal3f(0.0, 0.0, 1.0);
96
97 /* draw front face */
98 glBegin(GL_QUAD_STRIP);
99 for (i = 0; i <= teeth; i++) {
100 angle = i * 2.0 * M_PI / teeth;
101 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
102 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
103 if (i < teeth) {
104 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
105 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
106 width * 0.5);
107 }
108 }
109 glEnd();
110
111 /* draw front sides of teeth */
112 glBegin(GL_QUADS);
113 da = 2.0 * M_PI / teeth / 4.0;
114 for (i = 0; i < teeth; i++) {
115 angle = i * 2.0 * M_PI / teeth;
116
117 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
118 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
119 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
120 width * 0.5);
121 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
122 width * 0.5);
123 }
124 glEnd();
125
126 glNormal3f(0.0, 0.0, -1.0);
127
128 /* draw back face */
129 glBegin(GL_QUAD_STRIP);
130 for (i = 0; i <= teeth; i++) {
131 angle = i * 2.0 * M_PI / teeth;
132 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
133 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
134 if (i < teeth) {
135 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
136 -width * 0.5);
137 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
138 }
139 }
140 glEnd();
141
142 /* draw back sides of teeth */
143 glBegin(GL_QUADS);
144 da = 2.0 * M_PI / teeth / 4.0;
145 for (i = 0; i < teeth; i++) {
146 angle = i * 2.0 * M_PI / teeth;
147
148 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
149 -width * 0.5);
150 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
151 -width * 0.5);
152 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
153 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
154 }
155 glEnd();
156
157 /* draw outward faces of teeth */
158 glBegin(GL_QUAD_STRIP);
159 for (i = 0; i < teeth; i++) {
160 angle = i * 2.0 * M_PI / teeth;
161
162 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
163 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
164 u = r2 * cos(angle + da) - r1 * cos(angle);
165 v = r2 * sin(angle + da) - r1 * sin(angle);
166 len = sqrt(u * u + v * v);
167 u /= len;
168 v /= len;
169 glNormal3f(v, -u, 0.0);
170 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
171 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
172 glNormal3f(cos(angle), sin(angle), 0.0);
173 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
174 width * 0.5);
175 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
176 -width * 0.5);
177 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
178 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
179 glNormal3f(v, -u, 0.0);
180 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
181 width * 0.5);
182 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
183 -width * 0.5);
184 glNormal3f(cos(angle), sin(angle), 0.0);
185 }
186
187 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
188 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
189
190 glEnd();
191
192 glShadeModel(GL_SMOOTH);
193
194 /* draw inside radius cylinder */
195 glBegin(GL_QUAD_STRIP);
196 for (i = 0; i <= teeth; i++) {
197 angle = i * 2.0 * M_PI / teeth;
198 glNormal3f(-cos(angle), -sin(angle), 0.0);
199 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
200 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
201 }
202 glEnd();
203 }
204
205
206 static void
207 draw(void)
208 {
209 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
210
211 glPushMatrix();
212 glRotatef(view_rotx, 1.0, 0.0, 0.0);
213 glRotatef(view_roty, 0.0, 1.0, 0.0);
214 glRotatef(view_rotz, 0.0, 0.0, 1.0);
215
216 glPushMatrix();
217 glTranslatef(-3.0, -2.0, 0.0);
218 glRotatef(angle, 0.0, 0.0, 1.0);
219 glCallList(gear1);
220 glPopMatrix();
221
222 glPushMatrix();
223 glTranslatef(3.1, -2.0, 0.0);
224 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
225 glCallList(gear2);
226 glPopMatrix();
227
228 glPushMatrix();
229 glTranslatef(-3.1, 4.2, 0.0);
230 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
231 glCallList(gear3);
232 glPopMatrix();
233
234 glPopMatrix();
235 }
236
237
238 /* new window size or exposure */
239 static void
240 reshape(int width, int height)
241 {
242 GLfloat h = (GLfloat) height / (GLfloat) width;
243
244 WinWidth = width;
245 WinHeight = height;
246 glViewport(0, 0, (GLint) width, (GLint) height);
247 glMatrixMode(GL_PROJECTION);
248 glLoadIdentity();
249 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
250 glMatrixMode(GL_MODELVIEW);
251 glLoadIdentity();
252 glTranslatef(0.0, 0.0, -40.0);
253 }
254
255
256 static void
257 init(void)
258 {
259 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
260 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
261 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
262 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
263 int i;
264
265 glGetIntegerv(GL_AUX_BUFFERS, &i);
266 printf("AUX BUFFERS: %d\n", i);
267
268 glLightfv(GL_LIGHT0, GL_POSITION, pos);
269 glEnable(GL_CULL_FACE);
270 glEnable(GL_LIGHTING);
271 glEnable(GL_LIGHT0);
272 glEnable(GL_DEPTH_TEST);
273
274 /* make the gears */
275 gear1 = glGenLists(1);
276 glNewList(gear1, GL_COMPILE);
277 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
278 gear(1.0, 4.0, 1.0, 20, 0.7);
279 glEndList();
280
281 gear2 = glGenLists(1);
282 glNewList(gear2, GL_COMPILE);
283 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
284 gear(0.5, 2.0, 2.0, 10, 0.7);
285 glEndList();
286
287 gear3 = glGenLists(1);
288 glNewList(gear3, GL_COMPILE);
289 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
290 gear(1.3, 2.0, 0.5, 10, 0.7);
291 glEndList();
292
293 glEnable(GL_NORMALIZE);
294 }
295
296
297 /*
298 * Create an RGB, double-buffered window.
299 * Return the window and context handles.
300 */
301 static void
302 make_window( Display *dpy, const char *name,
303 int x, int y, int width, int height,
304 Window *winRet, GLXContext *ctxRet)
305 {
306 int attrib[] = { GLX_RGBA,
307 GLX_RED_SIZE, 1,
308 GLX_GREEN_SIZE, 1,
309 GLX_BLUE_SIZE, 1,
310 GLX_DOUBLEBUFFER,
311 GLX_DEPTH_SIZE, 1,
312 GLX_AUX_BUFFERS, 1,
313 None };
314 int scrnum;
315 XSetWindowAttributes attr;
316 unsigned long mask;
317 Window root;
318 Window win;
319 GLXContext ctx;
320 XVisualInfo *visinfo;
321
322 scrnum = DefaultScreen( dpy );
323 root = RootWindow( dpy, scrnum );
324
325 visinfo = glXChooseVisual( dpy, scrnum, attrib );
326 if (!visinfo) {
327 printf("Error: couldn't get an RGB, Double-buffered visual\n");
328 exit(1);
329 }
330
331 /* window attributes */
332 attr.background_pixel = 0;
333 attr.border_pixel = 0;
334 attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
335 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
336 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
337
338 win = XCreateWindow( dpy, root, 0, 0, width, height,
339 0, visinfo->depth, InputOutput,
340 visinfo->visual, mask, &attr );
341
342 /* set hints and properties */
343 {
344 XSizeHints sizehints;
345 sizehints.x = x;
346 sizehints.y = y;
347 sizehints.width = width;
348 sizehints.height = height;
349 sizehints.flags = USSize | USPosition;
350 XSetNormalHints(dpy, win, &sizehints);
351 XSetStandardProperties(dpy, win, name, name,
352 None, (char **)NULL, 0, &sizehints);
353 }
354
355 ctx = glXCreateContext( dpy, visinfo, NULL, True );
356 if (!ctx) {
357 printf("Error: glXCreateContext failed\n");
358 exit(1);
359 }
360
361 XFree(visinfo);
362
363 *winRet = win;
364 *ctxRet = ctx;
365 }
366
367
368 static void
369 event_loop(Display *dpy, Window win)
370 {
371 while (1) {
372 while (XPending(dpy) > 0) {
373 XEvent event;
374 XNextEvent(dpy, &event);
375 switch (event.type) {
376 case Expose:
377 /* we'll redraw below */
378 break;
379 case ConfigureNotify:
380 reshape(event.xconfigure.width, event.xconfigure.height);
381 break;
382 case KeyPress:
383 {
384 char buffer[10];
385 int r, code;
386 code = XLookupKeysym(&event.xkey, 0);
387 if (code == XK_Left) {
388 view_roty += 5.0;
389 }
390 else if (code == XK_Right) {
391 view_roty -= 5.0;
392 }
393 else if (code == XK_Up) {
394 view_rotx += 5.0;
395 }
396 else if (code == XK_Down) {
397 view_rotx -= 5.0;
398 }
399 else {
400 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
401 NULL, NULL);
402 if (buffer[0] == 27) {
403 /* escape */
404 return;
405 }
406 }
407 }
408 }
409 }
410
411 /* next frame */
412 angle += 2.0;
413
414 /* draw to aux buffer */
415 glDrawBuffer(GL_AUX0);
416
417 draw();
418
419 /* Copy aux buffer image to back color buffer */
420 glReadBuffer(GL_AUX0);
421 glDrawBuffer(GL_BACK);
422 glWindowPos2iARB(0, 0);
423 glDisable(GL_DEPTH_TEST);
424 glCopyPixels(0, 0, WinWidth, WinHeight, GL_COLOR);
425 glEnable(GL_DEPTH_TEST);
426
427 glXSwapBuffers(dpy, win);
428
429 /* calc framerate */
430 {
431 static int t0 = -1;
432 static int frames = 0;
433 int t = current_time();
434
435 if (t0 < 0)
436 t0 = t;
437
438 frames++;
439
440 if (t - t0 >= 5.0) {
441 GLfloat seconds = t - t0;
442 GLfloat fps = frames / seconds;
443 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
444 fps);
445 t0 = t;
446 frames = 0;
447 }
448 }
449 }
450 }
451
452
453 int
454 main(int argc, char *argv[])
455 {
456 Display *dpy;
457 Window win;
458 GLXContext ctx;
459 char *dpyName = ":0";
460 GLboolean printInfo = GL_FALSE;
461 int i;
462
463 for (i = 1; i < argc; i++) {
464 if (strcmp(argv[i], "-display") == 0) {
465 dpyName = argv[i+1];
466 i++;
467 }
468 else if (strcmp(argv[i], "-info") == 0) {
469 printInfo = GL_TRUE;
470 }
471 }
472
473 dpy = XOpenDisplay(dpyName);
474 if (!dpy) {
475 printf("Error: couldn't open display %s\n", dpyName);
476 return -1;
477 }
478
479 make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win, &ctx);
480 XMapWindow(dpy, win);
481 glXMakeCurrent(dpy, win, ctx);
482
483 if (printInfo) {
484 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
485 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
486 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
487 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
488 }
489
490 init();
491
492 event_loop(dpy, win);
493
494 glXDestroyContext(dpy, ctx);
495 XDestroyWindow(dpy, win);
496 XCloseDisplay(dpy);
497
498 return 0;
499 }