added silly mesa_hack() function and -b option
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 23 Mar 2001 21:41:44 +0000 (21:41 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 23 Mar 2001 21:41:44 +0000 (21:41 +0000)
progs/xdemos/glxinfo.c

index cfc3bc4a1aab1d380014d98edf67e1cd0ffc69eb..21a9a60331f2dca8cbdb3a585f584c4cb25d656f 100644 (file)
@@ -1,7 +1,7 @@
-/* $Id: glxinfo.c,v 1.11 2001/03/19 13:58:45 alanh Exp $ */
+/* $Id: glxinfo.c,v 1.12 2001/03/23 21:41:44 brianp Exp $ */
 
 /*
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  *  -t                     print wide table
  *  -v                     print verbose information
  *  -display DisplayName   specify the X display to interogate
+ *  -b                     only print ID of "best" visual on screen 0
  *
  * Brian Paul  26 January 2000
  */
 
+#define DO_GLU  /* may want to remove this for easier XFree86 building? */
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <GL/gl.h>
+#ifdef DO_GLU
 #include <GL/glu.h>
+#endif
 #include <GL/glx.h>
 #include <stdio.h>
 #include <string.h>
 
 
+#ifndef GLX_NONE_EXT
+#define GLX_NONE_EXT  0x8000
+#endif
+
+
 typedef enum
 {
    Normal,
@@ -194,8 +203,10 @@ print_screen_info(Display *dpy, int scrnum)
       const char *glRenderer = (const char *) glGetString(GL_RENDERER);
       const char *glVersion = (const char *) glGetString(GL_VERSION);
       const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
+#ifdef DO_GLU
       const char *gluVersion = (const char *) gluGetString(GLU_VERSION);
       const char *gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS);
+#endif
       printf("display: %s  screen:%d\n", DisplayString(dpy), scrnum);
       printf("direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
       printf("server glx vendor string: %s\n", serverVendor);
@@ -213,9 +224,11 @@ print_screen_info(Display *dpy, int scrnum)
       printf("OpenGL version string: %s\n", glVersion);
       printf("OpenGL extensions:\n");
       print_extension_list(glExtensions);
+#ifdef DO_GLU
       printf("glu version: %s\n", gluVersion);
       printf("glu extensions:\n");
       print_extension_list(gluExtensions);
+#endif
    }
    else {
       fprintf(stderr, "Error: glXMakeCurrent failed\n");
@@ -489,6 +502,98 @@ print_visual_info(Display *dpy, int scrnum, InfoMode mode)
 }
 
 
+/*
+ * Stand-alone Mesa doesn't really implement the GLX protocol so it
+ * doesn't really know the GLX attributes associated with an X visual.
+ * The first time a visual is presented to Mesa's pseudo-GLX it
+ * attaches ancilliary buffers to it (like depth and stencil).
+ * But that usually only works if glXChooseVisual is used.
+ * This function calls glXChooseVisual() to sort of "prime the pump"
+ * for Mesa's GLX so that the visuals that get reported actually
+ * reflect what applications will see.
+ * This has no effect when using true GLX.
+ */
+static void
+mesa_hack(Display *dpy, int scrnum)
+{
+   static int attribs[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DEPTH_SIZE, 1,
+      GLX_STENCIL_SIZE, 1,
+      GLX_ACCUM_RED_SIZE, 1,
+      GLX_ACCUM_GREEN_SIZE, 1,
+      GLX_ACCUM_BLUE_SIZE, 1,
+      GLX_ACCUM_ALPHA_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None
+   };
+   XVisualInfo *visinfo;
+
+   visinfo = glXChooseVisual(dpy, scrnum, attribs);
+   if (visinfo)
+      XFree(visinfo);
+}
+
+
+/*
+ * Examine all visuals to find the so-called best one.
+ * We prefer deepest RGBA buffer with depth, stencil and accum
+ * that has no caveats.
+ */
+static int
+find_best_visual(Display *dpy, int scrnum)
+{
+   XVisualInfo template;
+   XVisualInfo *visuals;
+   int numVisuals;
+   long mask;
+   int i;
+   struct visual_attribs bestVis;
+
+   /* get list of all visuals on this screen */
+   template.screen = scrnum;
+   mask = VisualScreenMask;
+   visuals = XGetVisualInfo(dpy, mask, &template, &numVisuals);
+
+   /* init bestVis with first visual info */
+   get_visual_attribs(dpy, &visuals[0], &bestVis);
+
+   /* try to find a "better" visual */
+   for (i = 1; i < numVisuals; i++) {
+      struct visual_attribs vis;
+
+      get_visual_attribs(dpy, &visuals[i], &vis);
+
+      /* always skip visuals with caveats */
+      if (vis.visualCaveat != GLX_NONE_EXT)
+         continue;
+
+      /* see if this vis is better than bestVis */
+      if ((!bestVis.supportsGL && vis.supportsGL) ||
+          (bestVis.visualCaveat != GLX_NONE_EXT) ||
+          (!bestVis.rgba && vis.rgba) ||
+          (!bestVis.doubleBuffer && vis.doubleBuffer) ||
+          (bestVis.redSize < vis.redSize) ||
+          (bestVis.greenSize < vis.greenSize) ||
+          (bestVis.blueSize < vis.blueSize) ||
+          (bestVis.alphaSize < vis.alphaSize) ||
+          (bestVis.depthSize < vis.depthSize) ||
+          (bestVis.stencilSize < vis.stencilSize) ||
+          (bestVis.accumRedSize < vis.accumRedSize)) {
+         /* found a better visual */
+         bestVis = vis;
+      }
+   }
+
+   XFree(visuals);
+
+   return bestVis.id;
+}
+
+
 int
 main(int argc, char *argv[])
 {
@@ -496,6 +601,7 @@ main(int argc, char *argv[])
    Display *dpy;
    int numScreens, scrnum;
    InfoMode mode = Normal;
+   GLboolean findBest = GL_FALSE;
    int i;
 
    for (i = 1; i < argc; i++) {
@@ -509,6 +615,9 @@ main(int argc, char *argv[])
       else if (strcmp(argv[i], "-v") == 0) {
          mode = Verbose;
       }
+      else if (strcmp(argv[i], "-b") == 0) {
+         findBest = GL_TRUE;
+      }
    }
 
    dpy = XOpenDisplay(displayName);
@@ -517,13 +626,22 @@ main(int argc, char *argv[])
       return -1;
    }
 
-   numScreens = ScreenCount(dpy);
-   for (scrnum = 0; scrnum < numScreens; scrnum++) {
-      print_screen_info(dpy, scrnum);
-      printf("\n");
-      print_visual_info(dpy, scrnum, mode);
-      if (scrnum + 1 < numScreens)
-         printf("\n\n");
+   if (findBest) {
+      int b;
+      mesa_hack(dpy, 0);
+      b = find_best_visual(dpy, 0);
+      printf("%d\n", b);
+   }
+   else {
+      numScreens = ScreenCount(dpy);
+      for (scrnum = 0; scrnum < numScreens; scrnum++) {
+         mesa_hack(dpy, scrnum);
+         print_screen_info(dpy, scrnum);
+         printf("\n");
+         print_visual_info(dpy, scrnum, mode);
+         if (scrnum + 1 < numScreens)
+            printf("\n\n");
+      }
    }
 
    XCloseDisplay(dpy);