[Mesa-dev] [PATCH] glxinfo: add support for creating/querying core-profile contexts (v2.1)

Dave Airlie airlied at gmail.com
Sat Jan 12 14:15:36 PST 2013


From: Brian Paul <brianp at vmware.com>

[airlied: Based on Brian's patch, I've fixed it up to always report a non-core
and core profile, after each other, and dropped the -c flag as its redunant
now]

The -c flag says to try to create a core profile (no legacy features)
using glXCreateContextAttribsARB().  A core profile may advertise a
different set of extensions than a compatibility profile (though,
the only difference with NVIDIA's driver is the presence of
GL_ARB_compatibility).  Also note that extensions need to be queried
one at a time with glGetStringi().

Be more careful with creating direct vs. indirect contexts.  If
we're trying to get a direct context, don't immediately settle for
indirect.  Try indirect only after failing to get direct.

xsync workaround from Kaelyn Uhrain
v2.1: add xsync to stop wierd xcb bug, drop [-c]

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/xdemos/glxinfo.c | 565 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 457 insertions(+), 108 deletions(-)

diff --git a/src/xdemos/glxinfo.c b/src/xdemos/glxinfo.c
index 38bd384..c1ecdfd 100644
--- a/src/xdemos/glxinfo.c
+++ b/src/xdemos/glxinfo.c
@@ -29,6 +29,7 @@
  *  -b                     only print ID of "best" visual on screen 0
  *  -i                     use indirect rendering connection only
  *  -l                     print interesting OpenGL limits (added 5 Sep 2002)
+ *  -c                     request a core profile rendering context
  *
  * Brian Paul  26 January 2000
  */
@@ -62,6 +63,8 @@
 #define GLX_COLOR_INDEX_BIT		0x00000002
 #endif
 
+#define ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
+
 typedef enum
 {
    Normal,
@@ -108,6 +111,43 @@ struct visual_attribs
 };
 
    
+/** list of known OpenGL versions */
+static struct { int major, minor; } gl_versions[] = {
+   {1, 0},
+   {1, 1},
+   {1, 2},
+   {1, 3},
+   {1, 4},
+   {1, 5},
+   {2, 0},
+   {2, 1},
+   {3, 0},
+   {3, 1},
+   {3, 2},
+   {3, 3},
+   {4, 0},
+   {4, 1},
+   {4, 2},
+   {4, 3},
+   {0, 0} /* end of list */
+};
+
+#define NUM_GL_VERSIONS ELEMENTS(gl_versions)
+
+
+/**
+ * GL Error checking/warning.
+ */
+static void
+CheckError(int line)
+{
+   int n;
+   n = glGetError();
+   if (n)
+      printf("Warning: GL error 0x%x at line %d\n", n, line);
+}
+
+
 /*
  * qsort callback for string comparison.
  */
@@ -219,6 +259,45 @@ print_extension_list(const char *ext, Bool singleLine)
 }
 
 
+/**
+ * Get list of OpenGL extensions using core profile's glGetStringi().
+ */
+static char *
+build_core_profile_extension_list(void)
+{
+   GLint i, n, totalLen;
+   char *buffer;
+   static PFNGLGETSTRINGIPROC glGetStringi_func = NULL;
+
+   if (!glGetStringi_func) {
+      glGetStringi_func = (PFNGLGETSTRINGIPROC)
+         glXGetProcAddressARB((GLubyte *) "glGetStringi");
+   }
+
+   glGetIntegerv(GL_NUM_EXTENSIONS, &n);
+
+   /* compute totalLen */
+   totalLen = 0;
+   for (i = 0; i < n; i++) {
+      const char *ext = (const char *) glGetStringi_func(GL_EXTENSIONS, i);
+      totalLen += strlen(ext) + 1; /* plus a space */
+   }
+
+   buffer = malloc(totalLen);
+   if (buffer) {
+      int pos = 0;
+      for (i = 0; i < n; i++) {
+         const char *ext = (const char *) glGetStringi_func(GL_EXTENSIONS, i);
+         strcpy(buffer + pos, ext);
+         pos += strlen(ext);
+         buffer[pos++] = ' ';
+      }
+   }
+   return buffer;
+}
+
+
+
 static void
 print_display_info(Display *dpy)
 {
@@ -373,7 +452,7 @@ extension_supported(const char *ext, const char *extensionsList)
  * Print interesting OpenGL implementation limits.
  */
 static void
-print_limits(const char *extensions)
+print_limits(const char *extensions, const char *oglstring)
 {
    struct token_name {
       GLuint count;
@@ -436,7 +515,7 @@ print_limits(const char *extensions)
    };
    GLint i, max[2];
 
-   printf("OpenGL limits:\n");
+   printf("%s limits:\n", oglstring);
    for (i = 0; limits[i].count; i++) {
       if (!limits[i].extension ||
           extension_supported(limits[i].extension, extensions)) {
@@ -480,10 +559,249 @@ print_limits(const char *extensions)
 }
 
 
-static void
-print_screen_info(Display *dpy, int scrnum, Bool allowDirect, Bool limits, Bool singleLine)
+struct bit_info
+{
+   int bit;
+   const char *name;
+};
+
+
+/**
+ * Return string representation for bits in a bitmask.
+ */
+static const char *
+bitmask_to_string(const struct bit_info bits[], int numBits, int mask)
+{
+   static char buffer[256], *p;
+   int i;
+
+   strcpy(buffer, "(none)");
+   p = buffer;
+   for (i = 0; i < numBits; i++) {
+      if (mask & bits[i].bit) {
+         if (p > buffer)
+            *p++ = ',';
+         strcpy(p, bits[i].name);
+         p += strlen(bits[i].name);
+      }
+   }
+
+   return buffer;
+}
+
+/**
+ * Return string representation for the bitmask returned by
+ * GL_CONTEXT_PROFILE_MASK (OpenGL 3.2 or later).
+ */
+static const char *
+profile_mask_string(int mask)
+{
+   const static struct bit_info bits[] = {
+#ifdef GL_CONTEXT_CORE_PROFILE_BIT
+      { GL_CONTEXT_CORE_PROFILE_BIT, "core profile"},
+#endif
+#ifdef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
+      { GL_CONTEXT_COMPATIBILITY_PROFILE_BIT, "compatibility profile" }
+#endif
+   };
+
+   return bitmask_to_string(bits, ELEMENTS(bits), mask);
+}
+
+
+/**
+ * Return string representation for the bitmask returned by
+ * GL_CONTEXT_FLAGS (OpenGL 3.0 or later).
+ */
+static const char *
+context_flags_string(int mask)
+{
+   const static struct bit_info bits[] = {
+#ifdef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
+      { GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT, "forward-compatible" },
+#endif
+#ifdef GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB
+      { GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB, "robust-access" },
+#endif
+   };
+
+   return bitmask_to_string(bits, ELEMENTS(bits), mask);
+}
+
+
+/**
+ * Choose a simple FB Config.
+ */
+static GLXFBConfig *
+choose_fb_config(Display *dpy, int scrnum)
+{
+   int fbAttribSingle[] = {
+      GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+      GLX_RED_SIZE,      1,
+      GLX_GREEN_SIZE,    1,
+      GLX_BLUE_SIZE,     1,
+      GLX_DOUBLEBUFFER,  False,
+      None };
+   int fbAttribDouble[] = {
+      GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+      GLX_RED_SIZE,      1,
+      GLX_GREEN_SIZE,    1,
+      GLX_BLUE_SIZE,     1,
+      GLX_DOUBLEBUFFER,  True,
+      None };
+   GLXFBConfig *configs;
+   int nConfigs;
+
+   configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
+   if (!configs)
+      configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
+
+   return configs;
+}
+
+
+static Bool CreateContextErrorFlag;
+
+static int
+create_context_error_handler(Display *dpy, XErrorEvent *error)
+{
+   (void) dpy;
+   (void) error->error_code;
+   CreateContextErrorFlag = True;
+   return 0;
+}
+
+
+/**
+ * Try to create a GLX context of the given version with flags/options.
+ * Note: A version number is required in order to get a core profile
+ * (at least w/ NVIDIA).
+ */
+static GLXContext
+create_context_flags(Display *dpy, GLXFBConfig fbconfig, int major, int minor,
+                     int contextFlags, int profileMask, Bool direct)
+{
+#ifdef GLX_ARB_create_context
+   static PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_func = 0;
+   static Bool firstCall = True;
+   int (*old_handler)(Display *, XErrorEvent *);
+   GLXContext context;
+   int attribs[20];
+   int n = 0;
+
+   if (firstCall) {
+      /* See if we have GLX_ARB_create_context_profile and get pointer to
+       * glXCreateContextAttribsARB() function.
+       */
+      const char *glxExt = glXQueryExtensionsString(dpy, 0);
+      if (extension_supported("GLX_ARB_create_context_profile", glxExt)) {
+         glXCreateContextAttribsARB_func = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+            glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB");
+      }
+      firstCall = False;
+   }
+
+   if (!glXCreateContextAttribsARB_func)
+      return 0;
+
+   /* setup attribute array */
+   if (major) {
+      attribs[n++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+      attribs[n++] = major;
+      attribs[n++] = GLX_CONTEXT_MINOR_VERSION_ARB;
+      attribs[n++] = minor;
+   }
+   if (contextFlags) {
+      attribs[n++] = GLX_CONTEXT_FLAGS_ARB;
+      attribs[n++] = contextFlags;
+   }
+#ifdef GLX_ARB_create_context_profile
+   if (profileMask) {
+      attribs[n++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+      attribs[n++] = profileMask;
+   }
+#endif
+   attribs[n++] = 0;
+
+   /* install X error handler */
+   old_handler = XSetErrorHandler(create_context_error_handler);
+   CreateContextErrorFlag = False;
+
+   /* try creating context */
+   context = glXCreateContextAttribsARB_func(dpy,
+                                             fbconfig,
+                                             0, /* share_context */
+                                             direct,
+                                             attribs);
+
+   /* restore error handler */
+   XSetErrorHandler(old_handler);
+
+   if (CreateContextErrorFlag)
+      context = 0;
+
+   if (direct) {
+      if (!glXIsDirect(dpy, context)) {
+         glXDestroyContext(dpy, context);
+         return 0;
+      }
+   }
+
+   return context;
+#else
+   return 0;
+#endif
+}
+
+
+/**
+ * Try to create a GLX context of the newest version.
+ */
+static GLXContext
+create_context_with_config(Display *dpy, GLXFBConfig config,
+                           Bool coreProfile, Bool direct)
+{
+   GLXContext ctx = 0;
+
+   if (coreProfile) {
+      /* Try to create a core profile, starting with the newest version of
+       * GL that we're aware of.  If we don't specify the version
+       */
+      int i;
+      for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) {
+         ctx = create_context_flags(dpy, config,
+                                    gl_versions[i].major,
+                                    gl_versions[i].minor,
+                                    0x0,
+                                    GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+                                    direct);
+         if (ctx)
+            return ctx;
+      }
+      /* couldn't get core profile context */
+      return 0;
+   }
+
+   /* GLX should return a context of the latest GL version that supports
+    * the full profile.
+    */
+   ctx = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, direct);
+
+   /* make sure the context is direct, if direct was requested */
+   if (ctx && direct) {
+      if (!glXIsDirect(dpy, ctx)) {
+         glXDestroyContext(dpy, ctx);
+         return 0;
+      }
+   }
+
+   return ctx;
+}
+
+
+static XVisualInfo *
+choose_xvisinfo(Display *dpy, int scrnum)
 {
-   Window win;
    int attribSingle[] = {
       GLX_RGBA,
       GLX_RED_SIZE, 1,
@@ -497,60 +815,53 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, Bool limits, Bool
       GLX_BLUE_SIZE, 1,
       GLX_DOUBLEBUFFER,
       None };
+   XVisualInfo *visinfo;
+
+   visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+   if (!visinfo)
+      visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+
+   return visinfo;
+}
+
 
+static void
+print_screen_info(Display *dpy, int scrnum, Bool allowDirect,
+                  Bool coreProfile, Bool limits, Bool singleLine)
+{
+   Window win;
    XSetWindowAttributes attr;
    unsigned long mask;
    Window root;
    GLXContext ctx = NULL;
    XVisualInfo *visinfo;
    int width = 100, height = 100;
+   GLXFBConfig *fbconfigs;
+   const char *oglstring = coreProfile ? "OpenGL core profile" : "OpenGL";
 
    root = RootWindow(dpy, scrnum);
 
    /*
-    * Find a basic GLX visual.  We'll then create a rendering context and
-    * query various info strings.
-    */
-   visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
-   if (!visinfo)
-      visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
-
-   if (visinfo)
-      ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
-
-#ifdef GLX_VERSION_1_3
-   /* Try glXChooseFBConfig() if glXChooseVisual didn't work.
-    * XXX when would that happen?
+    * Choose FBConfig or XVisualInfo and create a context.
     */
-   if (!visinfo) {
-      int fbAttribSingle[] = {
-	 GLX_RENDER_TYPE,   GLX_RGBA_BIT,
-	 GLX_RED_SIZE,      1,
-	 GLX_GREEN_SIZE,    1,
-	 GLX_BLUE_SIZE,     1,
-	 GLX_DOUBLEBUFFER,  False,
-	 None };
-      int fbAttribDouble[] = {
-	 GLX_RENDER_TYPE,   GLX_RGBA_BIT,
-	 GLX_RED_SIZE,      1,
-	 GLX_GREEN_SIZE,    1,
-	 GLX_BLUE_SIZE,     1,
-	 GLX_DOUBLEBUFFER,  True,
-	 None };
-      GLXFBConfig *configs = NULL;
-      int nConfigs;
-
-      configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
-      if (!configs)
-	 configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
-
-      if (configs) {
-	 visinfo = glXGetVisualFromFBConfig(dpy, configs[0]);
-	 ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect);
-	 XFree(configs);
+   fbconfigs = choose_fb_config(dpy, scrnum);
+   if (fbconfigs) {
+      ctx = create_context_with_config(dpy, fbconfigs[0],
+                                       coreProfile, allowDirect);
+      if (!ctx && allowDirect) {
+         /* try indirect */
+         ctx = create_context_with_config(dpy, fbconfigs[0],
+                                          coreProfile, False);
       }
+
+      visinfo = glXGetVisualFromFBConfig(dpy, fbconfigs[0]);
+      XFree(fbconfigs);
+   }
+   else {
+      visinfo = choose_xvisinfo(dpy, scrnum);
+      if (visinfo)
+	 ctx = glXCreateContext(dpy, visinfo, NULL, allowDirect);
    }
-#endif
 
    if (!visinfo) {
       fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
@@ -563,6 +874,9 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, Bool limits, Bool
       return;
    }
 
+   /*
+    * Create a window so that we can just bind the context.
+    */
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
@@ -583,72 +897,118 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, Bool limits, Bool
       const char *glVendor = (const char *) glGetString(GL_VENDOR);
       const char *glRenderer = (const char *) glGetString(GL_RENDERER);
       const char *glVersion = (const char *) glGetString(GL_VERSION);
-      const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
+      char *glExtensions;
       int glxVersionMajor;
       int glxVersionMinor;
       char *displayName = NULL;
       char *colon = NULL, *period = NULL;
-      
+      int version; /* 20, 21, 30, 31, 32, etc */
+
+      CheckError(__LINE__);
+      /* Get list of GL extensions */
+      if (coreProfile) {
+         glExtensions = build_core_profile_extension_list();
+      }
+      else {
+         glExtensions = (char *) glGetString(GL_EXTENSIONS);
+      }
+
+      CheckError(__LINE__);
+
       if (! glXQueryVersion( dpy, & glxVersionMajor, & glxVersionMinor )) {
          fprintf(stderr, "Error: glXQueryVersion failed\n");
          exit(1);
       }
 
-      /* Strip the screen number from the display name, if present. */
-      if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
-         fprintf(stderr, "Error: malloc() failed\n");
-         exit(1);
-      }
-      strcpy(displayName, DisplayString(dpy));
-      colon = strrchr(displayName, ':');
-      if (colon) {
-         period = strchr(colon, '.');
-         if (period)
-            *period = '\0';
-      }
-      printf("display: %s  screen: %d\n", displayName, scrnum);
-      free(displayName);
-      printf("direct rendering: ");
-      if (glXIsDirect(dpy, ctx)) {
-         printf("Yes\n");
-      }
-      else {
-         if (!allowDirect) {
-            printf("No (-i specified)\n");
+      if (!coreProfile) {
+         /* Strip the screen number from the display name, if present. */
+         if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
+            fprintf(stderr, "Error: malloc() failed\n");
+            exit(1);
          }
-         else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
-            printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
+         strcpy(displayName, DisplayString(dpy));
+         colon = strrchr(displayName, ':');
+         if (colon) {
+            period = strchr(colon, '.');
+            if (period)
+               *period = '\0';
+         }
+
+         printf("display: %s  screen: %d\n", displayName, scrnum);
+         free(displayName);
+         printf("direct rendering: ");
+         if (glXIsDirect(dpy, ctx)) {
+            printf("Yes\n");
          }
          else {
-            printf("No (If you want to find out why, try setting "
-                   "LIBGL_DEBUG=verbose)\n");
+            if (!allowDirect) {
+               printf("No (-i specified)\n");
+            }
+            else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
+               printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
+            }
+            else {
+               printf("No (If you want to find out why, try setting "
+                      "LIBGL_DEBUG=verbose)\n");
+            }
          }
-      }
-      printf("server glx vendor string: %s\n", serverVendor);
-      printf("server glx version string: %s\n", serverVersion);
-      printf("server glx extensions:\n");
-      print_extension_list(serverExtensions, singleLine);
-      printf("client glx vendor string: %s\n", clientVendor);
-      printf("client glx version string: %s\n", clientVersion);
-      printf("client glx extensions:\n");
-      print_extension_list(clientExtensions, singleLine);
-      printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor);
-      printf("GLX extensions:\n");
-      print_extension_list(glxExtensions, singleLine);
-      printf("OpenGL vendor string: %s\n", glVendor);
-      printf("OpenGL renderer string: %s\n", glRenderer);
-      printf("OpenGL version string: %s\n", glVersion);
+         printf("server glx vendor string: %s\n", serverVendor);
+         printf("server glx version string: %s\n", serverVersion);
+         printf("server glx extensions:\n");
+         print_extension_list(serverExtensions, singleLine);
+         printf("client glx vendor string: %s\n", clientVendor);
+         printf("client glx version string: %s\n", clientVersion);
+         printf("client glx extensions:\n");
+         print_extension_list(clientExtensions, singleLine);
+         printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor);
+         printf("GLX extensions:\n");
+         print_extension_list(glxExtensions, singleLine);
+         printf("OpenGL vendor string: %s\n", glVendor);
+         printf("OpenGL renderer string: %s\n", glRenderer);
+      } else
+         printf("\n");
+
+      printf("%s version string: %s\n", oglstring, glVersion);
+
+      version = (glVersion[0] - '0') * 10 + (glVersion[2] - '0');
+
+      CheckError(__LINE__);
+
 #ifdef GL_VERSION_2_0
-      if (glVersion[0] >= '2' && glVersion[1] == '.') {
+      if (version >= 20) {
          char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
-         printf("OpenGL shading language version string: %s\n", v);
+         printf("%s shading language version string: %s\n", oglstring, v);
+      }
+#endif
+      CheckError(__LINE__);
+#ifdef GL_VERSION_3_0
+      if (version >= 30) {
+         GLint flags;
+         glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
+         printf("%s context flags: %s\n", oglstring, context_flags_string(flags));
       }
 #endif
+      CheckError(__LINE__);
+#ifdef GL_VERSION_3_2
+      if (version >= 32) {
+         GLint mask;
+         glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
+         printf("%s profile mask: %s\n", oglstring, profile_mask_string(mask));
+      }
+#endif
+
+      CheckError(__LINE__);
 
-      printf("OpenGL extensions:\n");
+      printf("%s extensions:\n", oglstring);
       print_extension_list(glExtensions, singleLine);
+
+      CheckError(__LINE__);
+
       if (limits)
-         print_limits(glExtensions);
+         print_limits(glExtensions, oglstring);
+
+      if (coreProfile)
+         free(glExtensions);
    }
    else {
       fprintf(stderr, "Error: glXMakeCurrent failed\n");
@@ -657,6 +1017,7 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, Bool limits, Bool
    glXDestroyContext(dpy, ctx);
    XFree(visinfo);
    XDestroyWindow(dpy, win);
+   XSync(dpy, 1);
 }
 
 
@@ -684,26 +1045,13 @@ visual_class_name(int cls)
 static const char *
 visual_drawable_type(int type)
 {
-   static char buffer[256], *p;
-   const static struct { int bit; const char *name; } bits[] = {
+   const static struct bit_info bits[] = {
       { GLX_WINDOW_BIT, "window" },
       { GLX_PIXMAP_BIT, "pixmap" },
       { GLX_PBUFFER_BIT, "pbuffer" }
    };
-   int i;
-
-   strcpy(buffer, "(none)");
-   p = buffer;
-   for (i = 0; i < 3; i++) {
-      if (type & bits[i].bit) {
-         if (p > buffer)
-            *p++ = ',';
-         strcpy(p, bits[i].name);
-         p += strlen(bits[i].name);
-      }
-   }
 
-   return buffer;
+   return bitmask_to_string(bits, ELEMENTS(bits), type);
 }
 
 static const char *
@@ -1296,7 +1644,7 @@ find_best_visual(Display *dpy, int scrnum)
 static void
 usage(void)
 {
-   printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-s] ][-display <dname>]\n");
+   printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-s] [-display <dname>]\n");
    printf("\t-v: Print visuals info in verbose form.\n");
    printf("\t-t: Print verbose table.\n");
    printf("\t-display <dname>: Print GLX visuals on specified server.\n");
@@ -1372,7 +1720,8 @@ main(int argc, char *argv[])
       print_display_info(dpy);
       for (scrnum = 0; scrnum < numScreens; scrnum++) {
          mesa_hack(dpy, scrnum);
-         print_screen_info(dpy, scrnum, allowDirect, limits, singleLine);
+         print_screen_info(dpy, scrnum, allowDirect, 0, limits, singleLine);
+         print_screen_info(dpy, scrnum, allowDirect, 1, limits, singleLine);
          printf("\n");
          print_visual_info(dpy, scrnum, mode);
 #ifdef GLX_VERSION_1_3
-- 
1.8.0.2



More information about the mesa-dev mailing list