blob: 40d2f2fc3d92f74eb2cb34ce6374a2eef75557f5 [file] [log] [blame]
Brian Paul355da232001-03-23 22:46:26 +00001/*
2 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/*
23 * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
24 * Port by Brian Paul 23 March 2001
25 *
Brian Paulad802332003-04-09 21:47:19 +000026 * Modified by Ian Romanick <idr@us.ibm.com> 09 April 2003 to support
27 * GLX_{MESA,SGI}_swap_control and GLX_OML_sync_control.
Brian Paul355da232001-03-23 22:46:26 +000028 *
Brian Paulad802332003-04-09 21:47:19 +000029 * Command line options:
30 * -display Name of the display to use.
31 * -info print GL implementation information
32 * -swap N Attempt to set the swap interval to 1/N second
33 * -forcegetrate Get the display refresh rate even if the required GLX
34 * extension is not supported.
Brian Paul355da232001-03-23 22:46:26 +000035 */
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>
Brian Paulad802332003-04-09 21:47:19 +000044#include <stdint.h>
45#define GLX_GLXEXT_PROTOTYPES
Brian Paul355da232001-03-23 22:46:26 +000046#include <GL/gl.h>
47#include <GL/glx.h>
48
Brian Paulad802332003-04-09 21:47:19 +000049#ifndef GLX_MESA_swap_control
50typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval);
51typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void );
52#endif
53
54#if !defined( GLX_OML_sync_control ) && defined( _STDINT_H )
55#define GLX_OML_sync_control 1
56typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
57#endif
Brian Paul355da232001-03-23 22:46:26 +000058
59#define BENCHMARK
60
61#ifdef BENCHMARK
62
63/* XXX this probably isn't very portable */
64
65#include <sys/time.h>
66#include <unistd.h>
67
Brian Paulad802332003-04-09 21:47:19 +000068#define NUL '\0'
69
Brian Paul355da232001-03-23 22:46:26 +000070/* return current time (in seconds) */
71static int
72current_time(void)
73{
74 struct timeval tv;
Jouk Jansenf72a3da2002-10-08 08:38:26 +000075#ifdef __VMS
76 (void) gettimeofday(&tv, NULL );
77#else
Brian Paul355da232001-03-23 22:46:26 +000078 struct timezone tz;
79 (void) gettimeofday(&tv, &tz);
Jouk Jansenf72a3da2002-10-08 08:38:26 +000080#endif
Brian Paul355da232001-03-23 22:46:26 +000081 return (int) tv.tv_sec;
82}
83
84#else /*BENCHMARK*/
85
86/* dummy */
87static int
88current_time(void)
89{
90 return 0;
91}
92
93#endif /*BENCHMARK*/
94
95
96
97#ifndef M_PI
98#define M_PI 3.14159265
99#endif
100
101
102static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
103static GLint gear1, gear2, gear3;
104static GLfloat angle = 0.0;
105
Brian Paulad802332003-04-09 21:47:19 +0000106static GLboolean has_OML_sync_control = GL_FALSE;
107static GLboolean has_SGI_swap_control = GL_FALSE;
108static GLboolean has_MESA_swap_control = GL_FALSE;
109
110static char ** extension_table = NULL;
111static unsigned num_extensions;
Brian Paul355da232001-03-23 22:46:26 +0000112
113/*
114 *
115 * Draw a gear wheel. You'll probably want to call this function when
116 * building a display list since we do a lot of trig here.
117 *
118 * Input: inner_radius - radius of hole at center
119 * outer_radius - radius at center of teeth
120 * width - width of gear
121 * teeth - number of teeth
122 * tooth_depth - depth of tooth
123 */
124static void
125gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
126 GLint teeth, GLfloat tooth_depth)
127{
128 GLint i;
129 GLfloat r0, r1, r2;
130 GLfloat angle, da;
131 GLfloat u, v, len;
132
133 r0 = inner_radius;
134 r1 = outer_radius - tooth_depth / 2.0;
135 r2 = outer_radius + tooth_depth / 2.0;
136
137 da = 2.0 * M_PI / teeth / 4.0;
138
139 glShadeModel(GL_FLAT);
140
141 glNormal3f(0.0, 0.0, 1.0);
142
143 /* draw front face */
144 glBegin(GL_QUAD_STRIP);
145 for (i = 0; i <= teeth; i++) {
146 angle = i * 2.0 * M_PI / teeth;
147 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
148 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
149 if (i < teeth) {
150 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
151 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
152 width * 0.5);
153 }
154 }
155 glEnd();
156
157 /* draw front sides of teeth */
158 glBegin(GL_QUADS);
159 da = 2.0 * M_PI / teeth / 4.0;
160 for (i = 0; i < teeth; i++) {
161 angle = i * 2.0 * M_PI / teeth;
162
163 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
164 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
165 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
166 width * 0.5);
167 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
168 width * 0.5);
169 }
170 glEnd();
171
172 glNormal3f(0.0, 0.0, -1.0);
173
174 /* draw back face */
175 glBegin(GL_QUAD_STRIP);
176 for (i = 0; i <= teeth; i++) {
177 angle = i * 2.0 * M_PI / teeth;
178 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
179 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
180 if (i < teeth) {
181 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
182 -width * 0.5);
183 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
184 }
185 }
186 glEnd();
187
188 /* draw back sides of teeth */
189 glBegin(GL_QUADS);
190 da = 2.0 * M_PI / teeth / 4.0;
191 for (i = 0; i < teeth; i++) {
192 angle = i * 2.0 * M_PI / teeth;
193
194 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
195 -width * 0.5);
196 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
197 -width * 0.5);
198 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
199 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
200 }
201 glEnd();
202
203 /* draw outward faces of teeth */
204 glBegin(GL_QUAD_STRIP);
205 for (i = 0; i < teeth; i++) {
206 angle = i * 2.0 * M_PI / teeth;
207
208 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
209 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
210 u = r2 * cos(angle + da) - r1 * cos(angle);
211 v = r2 * sin(angle + da) - r1 * sin(angle);
212 len = sqrt(u * u + v * v);
213 u /= len;
214 v /= len;
215 glNormal3f(v, -u, 0.0);
216 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
217 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
218 glNormal3f(cos(angle), sin(angle), 0.0);
219 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
220 width * 0.5);
221 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
222 -width * 0.5);
223 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
224 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
225 glNormal3f(v, -u, 0.0);
226 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
227 width * 0.5);
228 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
229 -width * 0.5);
230 glNormal3f(cos(angle), sin(angle), 0.0);
231 }
232
233 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
234 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
235
236 glEnd();
237
238 glShadeModel(GL_SMOOTH);
239
240 /* draw inside radius cylinder */
241 glBegin(GL_QUAD_STRIP);
242 for (i = 0; i <= teeth; i++) {
243 angle = i * 2.0 * M_PI / teeth;
244 glNormal3f(-cos(angle), -sin(angle), 0.0);
245 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
246 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
247 }
248 glEnd();
249}
250
251
252static void
253draw(void)
254{
255 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
256
257 glPushMatrix();
258 glRotatef(view_rotx, 1.0, 0.0, 0.0);
259 glRotatef(view_roty, 0.0, 1.0, 0.0);
260 glRotatef(view_rotz, 0.0, 0.0, 1.0);
261
262 glPushMatrix();
263 glTranslatef(-3.0, -2.0, 0.0);
264 glRotatef(angle, 0.0, 0.0, 1.0);
265 glCallList(gear1);
266 glPopMatrix();
267
268 glPushMatrix();
269 glTranslatef(3.1, -2.0, 0.0);
270 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
271 glCallList(gear2);
272 glPopMatrix();
273
274 glPushMatrix();
275 glTranslatef(-3.1, 4.2, 0.0);
276 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
277 glCallList(gear3);
278 glPopMatrix();
279
280 glPopMatrix();
281}
282
283
284/* new window size or exposure */
285static void
286reshape(int width, int height)
287{
288 GLfloat h = (GLfloat) height / (GLfloat) width;
289
290 glViewport(0, 0, (GLint) width, (GLint) height);
291 glMatrixMode(GL_PROJECTION);
292 glLoadIdentity();
293 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
294 glMatrixMode(GL_MODELVIEW);
295 glLoadIdentity();
296 glTranslatef(0.0, 0.0, -40.0);
297}
298
299
300static void
301init(void)
302{
303 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
304 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
305 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
306 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
307
308 glLightfv(GL_LIGHT0, GL_POSITION, pos);
309 glEnable(GL_CULL_FACE);
310 glEnable(GL_LIGHTING);
311 glEnable(GL_LIGHT0);
312 glEnable(GL_DEPTH_TEST);
313
314 /* make the gears */
315 gear1 = glGenLists(1);
316 glNewList(gear1, GL_COMPILE);
317 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
318 gear(1.0, 4.0, 1.0, 20, 0.7);
319 glEndList();
320
321 gear2 = glGenLists(1);
322 glNewList(gear2, GL_COMPILE);
323 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
324 gear(0.5, 2.0, 2.0, 10, 0.7);
325 glEndList();
326
327 gear3 = glGenLists(1);
328 glNewList(gear3, GL_COMPILE);
329 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
330 gear(1.3, 2.0, 0.5, 10, 0.7);
331 glEndList();
332
333 glEnable(GL_NORMALIZE);
334}
335
336
337/*
338 * Create an RGB, double-buffered window.
339 * Return the window and context handles.
340 */
341static void
342make_window( Display *dpy, const char *name,
343 int x, int y, int width, int height,
344 Window *winRet, GLXContext *ctxRet)
345{
346 int attrib[] = { GLX_RGBA,
347 GLX_RED_SIZE, 1,
348 GLX_GREEN_SIZE, 1,
349 GLX_BLUE_SIZE, 1,
350 GLX_DOUBLEBUFFER,
351 GLX_DEPTH_SIZE, 1,
352 None };
353 int scrnum;
354 XSetWindowAttributes attr;
355 unsigned long mask;
356 Window root;
357 Window win;
358 GLXContext ctx;
359 XVisualInfo *visinfo;
360
361 scrnum = DefaultScreen( dpy );
362 root = RootWindow( dpy, scrnum );
363
364 visinfo = glXChooseVisual( dpy, scrnum, attrib );
365 if (!visinfo) {
366 printf("Error: couldn't get an RGB, Double-buffered visual\n");
367 exit(1);
368 }
369
370 /* window attributes */
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 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, win, &sizehints);
390 XSetStandardProperties(dpy, win, name, name,
391 None, (char **)NULL, 0, &sizehints);
392 }
393
394 ctx = glXCreateContext( dpy, visinfo, NULL, True );
395 if (!ctx) {
396 printf("Error: glXCreateContext failed\n");
397 exit(1);
398 }
399
400 XFree(visinfo);
401
402 *winRet = win;
403 *ctxRet = ctx;
404}
405
406
407static void
408event_loop(Display *dpy, Window win)
409{
410 while (1) {
411 while (XPending(dpy) > 0) {
412 XEvent event;
413 XNextEvent(dpy, &event);
414 switch (event.type) {
415 case Expose:
416 /* we'll redraw below */
417 break;
418 case ConfigureNotify:
419 reshape(event.xconfigure.width, event.xconfigure.height);
420 break;
421 case KeyPress:
422 {
423 char buffer[10];
424 int r, code;
425 code = XLookupKeysym(&event.xkey, 0);
426 if (code == XK_Left) {
427 view_roty += 5.0;
428 }
429 else if (code == XK_Right) {
430 view_roty -= 5.0;
431 }
432 else if (code == XK_Up) {
433 view_rotx += 5.0;
434 }
435 else if (code == XK_Down) {
436 view_rotx -= 5.0;
437 }
438 else {
439 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
440 NULL, NULL);
441 if (buffer[0] == 27) {
442 /* escape */
443 return;
444 }
445 }
446 }
447 }
448 }
449
450 /* next frame */
451 angle += 2.0;
452
453 draw();
454 glXSwapBuffers(dpy, win);
455
456 /* calc framerate */
457 {
458 static int t0 = -1;
459 static int frames = 0;
460 int t = current_time();
461
462 if (t0 < 0)
463 t0 = t;
464
465 frames++;
466
467 if (t - t0 >= 5.0) {
468 GLfloat seconds = t - t0;
469 GLfloat fps = frames / seconds;
470 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
471 fps);
472 t0 = t;
473 frames = 0;
474 }
475 }
476 }
477}
478
479
Brian Paulad802332003-04-09 21:47:19 +0000480/**
481 * Display the refresh rate of the display using the GLX_OML_sync_control
482 * extension.
483 */
484
485static void
486show_refresh_rate( Display * dpy )
487{
488#ifdef GLX_OML_sync_control
489 PFNGLXGETMSCRATEOMLPROC get_msc_rate;
490 int32_t n;
491 int32_t d;
492
493 get_msc_rate = (PFNGLXGETMSCRATEOMLPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetMscRateOML" );
494 if ( get_msc_rate != NULL ) {
495 (*get_msc_rate)( dpy, glXGetCurrentDrawable(), &n, &d );
496 printf( "refresh rate: %.1fHz\n", (float) n / d );
497 return;
498 }
499#endif
500 printf( "glXGetMscRateOML not supported.\n" );
501}
502
503
504/**
505 * Fill in the table of extension strings from a supplied extensions string
506 * (as returned by glXQueryExtensionsString).
507 *
508 * \param string String of GLX extensions.
509 * \sa is_extension_supported
510 */
511
512static void
513make_extension_table( const char * string )
514{
515 char ** string_tab;
516 unsigned num_strings;
517 unsigned base;
518 unsigned idx;
519 unsigned i;
520
521 /* Count the number of spaces in the string. That gives a base-line
522 * figure for the number of extension in the string.
523 */
524
525 num_strings = 1;
526 for ( i = 0 ; string[i] != NUL ; i++ ) {
527 if ( string[i] == ' ' ) {
528 num_strings++;
529 }
530 }
531
532 string_tab = (char **) malloc( sizeof( char * ) * num_strings );
533 if ( string_tab == NULL ) {
534 return;
535 }
536
537 base = 0;
538 idx = 0;
539
540 while ( string[ base ] != NUL ) {
541 /* Determine the length of the next extension string.
542 */
543
544 for ( i = 0
545 ; (string[ base + i ] != NUL) && (string[ base + i ] != ' ')
546 ; i++ ) {
547 /* empty */ ;
548 }
549
550 if ( i > 0 ) {
551 /* If the string was non-zero length, add it to the table. We
552 * can get zero length strings if there is a space at the end of
553 * the string or if there are two (or more) spaces next to each
554 * other in the string.
555 */
556
557 string_tab[ idx ] = malloc( sizeof( char ) * (i + 1) );
558 if ( string_tab[ idx ] == NULL ) {
559 return;
560 }
561
562 (void) memcpy( string_tab[ idx ], & string[ base ], i );
563 string_tab[ idx ][i] = NUL;
564 idx++;
565 }
566
567
568 /* Skip to the start of the next extension string.
569 */
570
571 for ( base += i
572 ; (string[ base ] == ' ') && (string[ base ] != NUL)
573 ; base++ ) {
574 /* empty */ ;
575 }
576 }
577
578 extension_table = string_tab;
579 num_extensions = idx;
580}
581
582
583/**
584 * Determine of an extension is supported. The extension string table
585 * must have already be initialized by calling \c make_extension_table.
586 *
587 * \praram ext Extension to be tested.
588 * \return GL_TRUE of the extension is supported, GL_FALSE otherwise.
589 * \sa make_extension_table
590 */
591
592static GLboolean
593is_extension_supported( const char * ext )
594{
595 unsigned i;
596
597 for ( i = 0 ; i < num_extensions ; i++ ) {
598 if ( strcmp( ext, extension_table[i] ) == 0 ) {
599 return GL_TRUE;
600 }
601 }
602
603 return GL_FALSE;
604}
605
606
Brian Paul355da232001-03-23 22:46:26 +0000607int
608main(int argc, char *argv[])
609{
610 Display *dpy;
611 Window win;
612 GLXContext ctx;
613 char *dpyName = ":0";
Brian Paulad802332003-04-09 21:47:19 +0000614 int swap_interval = 1;
615 GLboolean do_swap_interval = GL_FALSE;
616 GLboolean force_get_rate = GL_FALSE;
Brian Paul355da232001-03-23 22:46:26 +0000617 GLboolean printInfo = GL_FALSE;
618 int i;
Brian Paulad802332003-04-09 21:47:19 +0000619 PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL;
620 PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL;
621
Brian Paul355da232001-03-23 22:46:26 +0000622
623 for (i = 1; i < argc; i++) {
Brian Paulad802332003-04-09 21:47:19 +0000624 if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
Brian Paul355da232001-03-23 22:46:26 +0000625 dpyName = argv[i+1];
626 i++;
627 }
628 else if (strcmp(argv[i], "-info") == 0) {
629 printInfo = GL_TRUE;
630 }
Brian Paulad802332003-04-09 21:47:19 +0000631 else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) {
632 swap_interval = atoi( argv[i+1] );
633 do_swap_interval = GL_TRUE;
634 i++;
635 }
636 else if (strcmp(argv[i], "-forcegetrate") == 0) {
637 /* This option was put in because some DRI drivers don't support the
638 * full GLX_OML_sync_control extension, but they do support
639 * glXGetMscRateOML.
640 */
641 force_get_rate = GL_TRUE;
642 }
643 else if (strcmp(argv[i], "-help") == 0) {
644 printf("Usage:\n");
645 printf(" gears [options]\n");
646 printf("Options:\n");
647 printf(" -help Print this information\n");
648 printf(" -display displayName Specify X display\n");
649 printf(" -info Display GL information\n");
650 printf(" -swap N Swap no more than once per N vertical refreshes\n");
651 printf(" -forcgetrate Try to use glXGetMscRateOML function\n");
652 return 0;
653 }
Brian Paul355da232001-03-23 22:46:26 +0000654 }
655
656 dpy = XOpenDisplay(dpyName);
657 if (!dpy) {
658 printf("Error: couldn't open display %s\n", dpyName);
659 return -1;
660 }
661
662 make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &ctx);
663 XMapWindow(dpy, win);
664 glXMakeCurrent(dpy, win, ctx);
665
Brian Paulad802332003-04-09 21:47:19 +0000666 make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) );
667 has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" );
668 has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" );
669 has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" );
670
671 if ( has_MESA_swap_control ) {
672 set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalMESA" );
673 get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetSwapIntervalMESA" );
674 }
675 else if ( has_SGI_swap_control ) {
676 set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" );
677 }
678
679
Brian Paul355da232001-03-23 22:46:26 +0000680 if (printInfo) {
681 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
682 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
683 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
684 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
Brian Paulad802332003-04-09 21:47:19 +0000685 if ( has_OML_sync_control || force_get_rate ) {
686 show_refresh_rate( dpy );
687 }
688
689 if ( get_swap_interval != NULL ) {
690 printf("Default swap interval = %d\n", (*get_swap_interval)() );
691 }
692 }
693
694 if ( do_swap_interval ) {
695 if ( set_swap_interval != NULL ) {
696 if ( ((swap_interval == 0) && !has_MESA_swap_control)
697 || (swap_interval < 0) ) {
698 printf( "Swap interval must be non-negative or greater than zero "
699 "if GLX_MESA_swap_control is not supported.\n" );
700 }
701 else {
702 (*set_swap_interval)( swap_interval );
703 }
704
705 if ( printInfo && (get_swap_interval != NULL) ) {
706 printf("Current swap interval = %d\n", (*get_swap_interval)() );
707 }
708 }
709 else {
710 printf("Unable to set swap-interval. Neither GLX_SGI_swap_control "
711 "nor GLX_MESA_swap_control are supported.\n" );
712 }
Brian Paul355da232001-03-23 22:46:26 +0000713 }
714
715 init();
716
717 event_loop(dpy, win);
718
719 glXDestroyContext(dpy, ctx);
720 XDestroyWindow(dpy, win);
721 XCloseDisplay(dpy);
722
723 return 0;
724}