From ad80233d5de6f1e4527ffe3f1ed552c0da095d7e Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 9 Apr 2003 21:47:19 +0000 Subject: [PATCH] add support for swap and sync extensions (Ian Romanick) --- progs/xdemos/glxgears.c | 229 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 226 insertions(+), 3 deletions(-) diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c index 59691513e2c..40d2f2fc3d9 100644 --- a/progs/xdemos/glxgears.c +++ b/progs/xdemos/glxgears.c @@ -23,9 +23,15 @@ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) * Port by Brian Paul 23 March 2001 * - * Command line options: - * -info print GL implementation information + * Modified by Ian Romanick 09 April 2003 to support + * GLX_{MESA,SGI}_swap_control and GLX_OML_sync_control. * + * Command line options: + * -display Name of the display to use. + * -info print GL implementation information + * -swap N Attempt to set the swap interval to 1/N second + * -forcegetrate Get the display refresh rate even if the required GLX + * extension is not supported. */ @@ -35,9 +41,20 @@ #include #include #include +#include +#define GLX_GLXEXT_PROTOTYPES #include #include +#ifndef GLX_MESA_swap_control +typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval); +typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void ); +#endif + +#if !defined( GLX_OML_sync_control ) && defined( _STDINT_H ) +#define GLX_OML_sync_control 1 +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); +#endif #define BENCHMARK @@ -48,6 +65,8 @@ #include #include +#define NUL '\0' + /* return current time (in seconds) */ static int current_time(void) @@ -84,6 +103,12 @@ static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; static GLint gear1, gear2, gear3; static GLfloat angle = 0.0; +static GLboolean has_OML_sync_control = GL_FALSE; +static GLboolean has_SGI_swap_control = GL_FALSE; +static GLboolean has_MESA_swap_control = GL_FALSE; + +static char ** extension_table = NULL; +static unsigned num_extensions; /* * @@ -452,6 +477,133 @@ event_loop(Display *dpy, Window win) } +/** + * Display the refresh rate of the display using the GLX_OML_sync_control + * extension. + */ + +static void +show_refresh_rate( Display * dpy ) +{ +#ifdef GLX_OML_sync_control + PFNGLXGETMSCRATEOMLPROC get_msc_rate; + int32_t n; + int32_t d; + + get_msc_rate = (PFNGLXGETMSCRATEOMLPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetMscRateOML" ); + if ( get_msc_rate != NULL ) { + (*get_msc_rate)( dpy, glXGetCurrentDrawable(), &n, &d ); + printf( "refresh rate: %.1fHz\n", (float) n / d ); + return; + } +#endif + printf( "glXGetMscRateOML not supported.\n" ); +} + + +/** + * Fill in the table of extension strings from a supplied extensions string + * (as returned by glXQueryExtensionsString). + * + * \param string String of GLX extensions. + * \sa is_extension_supported + */ + +static void +make_extension_table( const char * string ) +{ + char ** string_tab; + unsigned num_strings; + unsigned base; + unsigned idx; + unsigned i; + + /* Count the number of spaces in the string. That gives a base-line + * figure for the number of extension in the string. + */ + + num_strings = 1; + for ( i = 0 ; string[i] != NUL ; i++ ) { + if ( string[i] == ' ' ) { + num_strings++; + } + } + + string_tab = (char **) malloc( sizeof( char * ) * num_strings ); + if ( string_tab == NULL ) { + return; + } + + base = 0; + idx = 0; + + while ( string[ base ] != NUL ) { + /* Determine the length of the next extension string. + */ + + for ( i = 0 + ; (string[ base + i ] != NUL) && (string[ base + i ] != ' ') + ; i++ ) { + /* empty */ ; + } + + if ( i > 0 ) { + /* If the string was non-zero length, add it to the table. We + * can get zero length strings if there is a space at the end of + * the string or if there are two (or more) spaces next to each + * other in the string. + */ + + string_tab[ idx ] = malloc( sizeof( char ) * (i + 1) ); + if ( string_tab[ idx ] == NULL ) { + return; + } + + (void) memcpy( string_tab[ idx ], & string[ base ], i ); + string_tab[ idx ][i] = NUL; + idx++; + } + + + /* Skip to the start of the next extension string. + */ + + for ( base += i + ; (string[ base ] == ' ') && (string[ base ] != NUL) + ; base++ ) { + /* empty */ ; + } + } + + extension_table = string_tab; + num_extensions = idx; +} + + +/** + * Determine of an extension is supported. The extension string table + * must have already be initialized by calling \c make_extension_table. + * + * \praram ext Extension to be tested. + * \return GL_TRUE of the extension is supported, GL_FALSE otherwise. + * \sa make_extension_table + */ + +static GLboolean +is_extension_supported( const char * ext ) +{ + unsigned i; + + for ( i = 0 ; i < num_extensions ; i++ ) { + if ( strcmp( ext, extension_table[i] ) == 0 ) { + return GL_TRUE; + } + } + + return GL_FALSE; +} + + int main(int argc, char *argv[]) { @@ -459,17 +611,46 @@ main(int argc, char *argv[]) Window win; GLXContext ctx; char *dpyName = ":0"; + int swap_interval = 1; + GLboolean do_swap_interval = GL_FALSE; + GLboolean force_get_rate = GL_FALSE; GLboolean printInfo = GL_FALSE; int i; + PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL; + PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL; + for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-display") == 0) { + if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { dpyName = argv[i+1]; i++; } else if (strcmp(argv[i], "-info") == 0) { printInfo = GL_TRUE; } + else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) { + swap_interval = atoi( argv[i+1] ); + do_swap_interval = GL_TRUE; + i++; + } + else if (strcmp(argv[i], "-forcegetrate") == 0) { + /* This option was put in because some DRI drivers don't support the + * full GLX_OML_sync_control extension, but they do support + * glXGetMscRateOML. + */ + force_get_rate = GL_TRUE; + } + else if (strcmp(argv[i], "-help") == 0) { + printf("Usage:\n"); + printf(" gears [options]\n"); + printf("Options:\n"); + printf(" -help Print this information\n"); + printf(" -display displayName Specify X display\n"); + printf(" -info Display GL information\n"); + printf(" -swap N Swap no more than once per N vertical refreshes\n"); + printf(" -forcgetrate Try to use glXGetMscRateOML function\n"); + return 0; + } } dpy = XOpenDisplay(dpyName); @@ -482,11 +663,53 @@ main(int argc, char *argv[]) XMapWindow(dpy, win); glXMakeCurrent(dpy, win, ctx); + make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) ); + has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" ); + has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" ); + has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" ); + + if ( has_MESA_swap_control ) { + set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalMESA" ); + get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetSwapIntervalMESA" ); + } + else if ( has_SGI_swap_control ) { + set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" ); + } + + if (printInfo) { printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); + if ( has_OML_sync_control || force_get_rate ) { + show_refresh_rate( dpy ); + } + + if ( get_swap_interval != NULL ) { + printf("Default swap interval = %d\n", (*get_swap_interval)() ); + } + } + + if ( do_swap_interval ) { + if ( set_swap_interval != NULL ) { + if ( ((swap_interval == 0) && !has_MESA_swap_control) + || (swap_interval < 0) ) { + printf( "Swap interval must be non-negative or greater than zero " + "if GLX_MESA_swap_control is not supported.\n" ); + } + else { + (*set_swap_interval)( swap_interval ); + } + + if ( printInfo && (get_swap_interval != NULL) ) { + printf("Current swap interval = %d\n", (*get_swap_interval)() ); + } + } + else { + printf("Unable to set swap-interval. Neither GLX_SGI_swap_control " + "nor GLX_MESA_swap_control are supported.\n" ); + } } init(); -- 2.30.2