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