glxgears: Support GLX_EXT_swap_control for querying the current swap interval.
[mesa.git] / progs / xdemos / glxgears.c
index 8db717f1aa38a430b4f47f7c26cdb4f9fa5779a7..92c75caa5e63d1de160a6b2f32d2814c89eea48d 100644 (file)
  * 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
- *    -stereo    use stereo enabled GLX visual
- *
+ * See usage() below for command line options.
  */
 
 
 #include <X11/keysym.h>
 #include <GL/gl.h>
 #include <GL/glx.h>
+#include <GL/glxext.h>
+
+#ifndef GLX_MESA_swap_control
+#define GLX_MESA_swap_control 1
+typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
+#endif
 
 
 #define BENCHMARK
@@ -560,6 +563,70 @@ make_window( Display *dpy, const char *name,
 }
 
 
+/**
+ * Determine whether or not a GLX extension is supported.
+ */
+static int
+is_glx_extension_supported(Display *dpy, const char *query)
+{
+   const int scrnum = DefaultScreen(dpy);
+   const char *glx_extensions = NULL;
+   const size_t len = strlen(query);
+   const char *ptr;
+
+   if (glx_extensions == NULL) {
+      glx_extensions = glXQueryExtensionsString(dpy, scrnum);
+   }
+
+   ptr = strstr(glx_extensions, query);
+   return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
+}
+
+
+/**
+ * Attempt to determine whether or not the display is synched to vblank.
+ */
+static void
+query_vsync(Display *dpy, GLXDrawable drawable)
+{
+   int interval = 0;
+
+#if defined(GLX_EXT_swap_control)
+   if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) {
+       unsigned int tmp = -1;
+       glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp);
+       interval = tmp;
+   } else
+#endif
+   if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
+      PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA =
+          (PFNGLXGETSWAPINTERVALMESAPROC)
+          glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
+
+      interval = (*pglXGetSwapIntervalMESA)();
+   } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) {
+      /* The default swap interval with this extension is 1.  Assume that it
+       * is set to the default.
+       *
+       * Many Mesa-based drivers default to 0, but all of these drivers also
+       * export GLX_MESA_swap_control.  In that case, this branch will never
+       * be taken, and the correct result should be reported.
+       */
+      interval = 1;
+   }
+
+
+   if (interval > 0) {
+      printf("Running synchronized to the vertical refresh.  The framerate should be\n");
+      if (interval == 1) {
+         printf("approximately the same as the monitor refresh rate.\n");
+      } else if (interval > 1) {
+         printf("approximately 1/%d the monitor refresh rate.\n",
+                interval);
+      }
+   }
+}
+
 /**
  * Handle one X event.
  * \return NOP, EXIT or DRAW
@@ -567,6 +634,9 @@ make_window( Display *dpy, const char *name,
 static int
 handle_event(Display *dpy, Window win, XEvent *event)
 {
+   (void) dpy;
+   (void) win;
+
    switch (event->type) {
    case Expose:
       return DRAW;
@@ -686,6 +756,7 @@ main(int argc, char *argv[])
    make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx);
    XMapWindow(dpy, win);
    glXMakeCurrent(dpy, win, ctx);
+   query_vsync(dpy, win);
 
    if (printInfo) {
       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
@@ -707,6 +778,7 @@ main(int argc, char *argv[])
    glDeleteLists(gear1, 1);
    glDeleteLists(gear2, 1);
    glDeleteLists(gear3, 1);
+   glXMakeCurrent(dpy, None, NULL);
    glXDestroyContext(dpy, ctx);
    XDestroyWindow(dpy, win);
    XCloseDisplay(dpy);