glut_dstr.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:47k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* Copyright (c) Mark J. Kilgard, 1997. */
  2. /* This program is freely distributable without licensing fees
  3.    and is provided without guarantee or warrantee expressed or
  4.    implied. This program is -not- in the public domain. */
  5. #include <assert.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "glutint.h"
  10. /* glxcaps matches the criteria macros listed in glutint.h, but
  11.    only list the first set (those that correspond to GLX visual
  12.    attributes). */
  13. static int glxcap[NUM_GLXCAPS] =
  14. {
  15.   GLX_RGBA,
  16.   GLX_BUFFER_SIZE,
  17.   GLX_DOUBLEBUFFER,
  18.   GLX_STEREO,
  19.   GLX_AUX_BUFFERS,
  20.   GLX_RED_SIZE,
  21.   GLX_GREEN_SIZE,
  22.   GLX_BLUE_SIZE,
  23.   GLX_ALPHA_SIZE,
  24.   GLX_DEPTH_SIZE,
  25.   GLX_STENCIL_SIZE,
  26.   GLX_ACCUM_RED_SIZE,
  27.   GLX_ACCUM_GREEN_SIZE,
  28.   GLX_ACCUM_BLUE_SIZE,
  29.   GLX_ACCUM_ALPHA_SIZE,
  30.   GLX_LEVEL,
  31. };
  32. #ifdef TEST
  33. #if !defined(_WIN32)
  34. char *__glutProgramName = "dstr";
  35. Display *__glutDisplay;
  36. int __glutScreen;
  37. XVisualInfo *(*__glutDetermineVisualFromString) (char *string, Bool * treatAsSingle,
  38.   Criterion * requiredCriteria, int nRequired, int requiredMask, void **fbc) = NULL;
  39. char *__glutDisplayString = NULL;
  40. #endif
  41. static int verbose = 0;
  42. static char *compstr[] =
  43. {
  44.   "none", "=", "!=", "<=", ">=", ">", "<", "~"
  45. };
  46. static char *capstr[] =
  47. {
  48.   "rgba", "bufsize", "double", "stereo", "auxbufs", "red", "green", "blue", "alpha",
  49.   "depth", "stencil", "acred", "acgreen", "acblue", "acalpha", "level", "xvisual",
  50.   "transparent", "samples", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
  51.   "xtruecolor", "xdirectcolor", "slow", "conformant", "num"
  52. };
  53. static void
  54. printCriteria(Criterion * criteria, int ncriteria)
  55. {
  56.   int i;
  57.   printf("Criteria: %dn", ncriteria);
  58.   for (i = 0; i < ncriteria; i++) {
  59.     printf("  %s %s %dn",
  60.       capstr[criteria[i].capability],
  61.       compstr[criteria[i].comparison],
  62.       criteria[i].value);
  63.   }
  64. }
  65. #endif /* TEST */
  66. static int isMesaGLX = -1;
  67. static int
  68. determineMesaGLX(void)
  69. {
  70. #ifdef GLX_VERSION_1_1
  71.   const char *vendor, *version, *ch;
  72.   vendor = glXGetClientString(__glutDisplay, GLX_VENDOR);
  73.   if (!strcmp(vendor, "Brian Paul")) {
  74.     version = glXGetClientString(__glutDisplay, GLX_VERSION);
  75.     for (ch = version; *ch != ' ' && *ch != ''; ch++);
  76.     for (; *ch == ' ' && *ch != ''; ch++);
  77. #define MESA_NAME "Mesa "  /* Trailing space is intentional. */
  78.     if (!strncmp(MESA_NAME, ch, sizeof(MESA_NAME) - 1)) {
  79.       return 1;
  80.     }
  81.   }
  82. #else
  83.   /* Recent versions for Mesa should support GLX 1.1 and
  84.      therefore glXGetClientString.  If we get into this case,
  85.      we would be compiling against a true OpenGL not supporting
  86.      GLX 1.1, and the resulting compiled library won't work well
  87.      with Mesa then. */
  88. #endif
  89.   return 0;
  90. }
  91. static XVisualInfo **
  92. getMesaVisualList(int *n)
  93. {
  94.   XVisualInfo **vlist, *vinfo;
  95.   int attribs[23];
  96.   int i, x, cnt;
  97.   vlist = (XVisualInfo **) malloc((32 + 16) * sizeof(XVisualInfo *));
  98.   if (!vlist)
  99.     __glutFatalError("out of memory.");
  100.   cnt = 0;
  101.   for (i = 0; i < 32; i++) {
  102.     x = 0;
  103.     attribs[x] = GLX_RGBA;
  104.     x++;
  105.     attribs[x] = GLX_RED_SIZE;
  106.     x++;
  107.     attribs[x] = 1;
  108.     x++;
  109.     attribs[x] = GLX_GREEN_SIZE;
  110.     x++;
  111.     attribs[x] = 1;
  112.     x++;
  113.     attribs[x] = GLX_BLUE_SIZE;
  114.     x++;
  115.     attribs[x] = 1;
  116.     x++;
  117.     if (i & 1) {
  118.       attribs[x] = GLX_DEPTH_SIZE;
  119.       x++;
  120.       attribs[x] = 1;
  121.       x++;
  122.     }
  123.     if (i & 2) {
  124.       attribs[x] = GLX_STENCIL_SIZE;
  125.       x++;
  126.       attribs[x] = 1;
  127.       x++;
  128.     }
  129.     if (i & 4) {
  130.       attribs[x] = GLX_ACCUM_RED_SIZE;
  131.       x++;
  132.       attribs[x] = 1;
  133.       x++;
  134.       attribs[x] = GLX_ACCUM_GREEN_SIZE;
  135.       x++;
  136.       attribs[x] = 1;
  137.       x++;
  138.       attribs[x] = GLX_ACCUM_BLUE_SIZE;
  139.       x++;
  140.       attribs[x] = 1;
  141.       x++;
  142.     }
  143.     if (i & 8) {
  144.       attribs[x] = GLX_ALPHA_SIZE;
  145.       x++;
  146.       attribs[x] = 1;
  147.       x++;
  148.       if (i & 4) {
  149.         attribs[x] = GLX_ACCUM_ALPHA_SIZE;
  150.         x++;
  151.         attribs[x] = 1;
  152.         x++;
  153.       }
  154.     }
  155.     if (i & 16) {
  156.       attribs[x] = GLX_DOUBLEBUFFER;
  157.       x++;
  158.     }
  159.     attribs[x] = None;
  160.     x++;
  161.     assert(x <= sizeof(attribs) / sizeof(attribs[0]));
  162.     vinfo = glXChooseVisual(__glutDisplay, __glutScreen, attribs);
  163.     if (vinfo) {
  164.       vlist[cnt] = vinfo;
  165.       cnt++;
  166.     }
  167.   }
  168.   for (i = 0; i < 16; i++) {
  169.     x = 0;
  170.     if (i & 1) {
  171.       attribs[x] = GLX_DEPTH_SIZE;
  172.       x++;
  173.       attribs[x] = 1;
  174.       x++;
  175.     }
  176.     if (i & 2) {
  177.       attribs[x] = GLX_STENCIL_SIZE;
  178.       x++;
  179.       attribs[x] = 1;
  180.       x++;
  181.     }
  182.     if (i & 4) {
  183.       attribs[x] = GLX_DOUBLEBUFFER;
  184.       x++;
  185.     }
  186.     if (i & 8) {
  187.       attribs[x] = GLX_LEVEL;
  188.       x++;
  189.       attribs[x] = 1;
  190.       x++;
  191. #if defined(GLX_TRANSPARENT_TYPE_EXT) && defined(GLX_TRANSPARENT_INDEX_EXT)
  192.       attribs[x] = GLX_TRANSPARENT_TYPE_EXT;
  193.       x++;
  194.       attribs[x] = GLX_TRANSPARENT_INDEX_EXT;
  195.       x++;
  196. #endif
  197.     }
  198.     attribs[x] = None;
  199.     x++;
  200.     assert(x <= sizeof(attribs) / sizeof(attribs[0]));
  201.     vinfo = glXChooseVisual(__glutDisplay, __glutScreen, attribs);
  202.     if (vinfo) {
  203.       vlist[cnt] = vinfo;
  204.       cnt++;
  205.     }
  206.   }
  207.   *n = cnt;
  208.   return vlist;
  209. }
  210. static FrameBufferMode *
  211. loadVisuals(int *nitems_return)
  212. {
  213.   XVisualInfo *vinfo, **vlist, template;
  214.   FrameBufferMode *fbmodes, *mode;
  215.   int n, i, j, rc, glcapable;
  216. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
  217.   int multisample;
  218. #endif
  219. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
  220.   int visual_info;
  221. #endif
  222. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
  223.   int visual_rating;
  224. #endif
  225. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  226.   int fbconfig;
  227. #endif
  228.   isMesaGLX = determineMesaGLX();
  229.   if (isMesaGLX) {
  230.     vlist = getMesaVisualList(&n);
  231.   } else {
  232. #if !defined(_WIN32)
  233.     template.screen = __glutScreen;
  234.     vinfo = XGetVisualInfo(__glutDisplay, VisualScreenMask, &template, &n);
  235. #else
  236.     vinfo = XGetVisualInfo(__glutDisplay, 0, &template, &n);
  237. #endif
  238.     if (vinfo == NULL) {
  239.       *nitems_return = 0;
  240.       return NULL;
  241.     }
  242.     assert(n > 0);
  243.     /* Make an array of XVisualInfo* pointers to help the Mesa
  244.        case because each glXChooseVisual call returns a
  245.        distinct XVisualInfo*, not a handy array like
  246.        XGetVisualInfo.  (Mesa expects us to return the _exact_
  247.        pointer returned by glXChooseVisual so we could not just
  248.        copy the returned structure.) */
  249.     vlist = (XVisualInfo **) malloc(n * sizeof(XVisualInfo *));
  250.     if (!vlist)
  251.       __glutFatalError("out of memory.");
  252.     for (i = 0; i < n; i++) {
  253.       vlist[i] = &vinfo[i];
  254.     }
  255.   }
  256. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
  257.   multisample = __glutIsSupportedByGLX("GLX_SGIS_multisample");
  258. #endif
  259. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
  260.   visual_info = __glutIsSupportedByGLX("GLX_EXT_visual_info");
  261. #endif
  262. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
  263.   visual_rating = __glutIsSupportedByGLX("GLX_EXT_visual_rating");
  264. #endif
  265. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  266.   fbconfig = __glutIsSupportedByGLX("GLX_SGIX_fbconfig");
  267. #endif
  268.   fbmodes = (FrameBufferMode *) malloc(n * sizeof(FrameBufferMode));
  269.   if (fbmodes == NULL) {
  270.     *nitems_return = -1;
  271.     return NULL;
  272.   }
  273.   for (i = 0; i < n; i++) {
  274.     mode = &fbmodes[i];
  275.     mode->vi = vlist[i];
  276. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  277.     mode->fbc = NULL;
  278. #endif
  279.     rc = glXGetConfig(__glutDisplay, vlist[i], GLX_USE_GL, &glcapable);
  280.     if (rc == 0 && glcapable) {
  281.       mode->valid = 1;  /* Assume the best until proven
  282.                            otherwise. */
  283.       for (j = 0; j < NUM_GLXCAPS; j++) {
  284.         rc = glXGetConfig(__glutDisplay, vlist[i], glxcap[j], &mode->cap[j]);
  285.         if (rc != 0) {
  286.           mode->valid = 0;
  287.         }
  288.       }
  289. #if defined(_WIN32)
  290.       mode->cap[XVISUAL] = ChoosePixelFormat(XHDC, vlist[i]);
  291. #else
  292.       mode->cap[XVISUAL] = (int) vlist[i]->visualid;
  293. #endif
  294.       mode->cap[XSTATICGRAY] = 0;
  295.       mode->cap[XGRAYSCALE] = 0;
  296.       mode->cap[XSTATICCOLOR] = 0;
  297.       mode->cap[XPSEUDOCOLOR] = 0;
  298.       mode->cap[XTRUECOLOR] = 0;
  299.       mode->cap[XDIRECTCOLOR] = 0;
  300. #if !defined(_WIN32)
  301. #if defined(__cplusplus) || defined(c_plusplus)
  302.       switch (vlist[i]->c_class) {
  303. #else
  304.       switch (vlist[i]->class) {
  305. #endif
  306.       case StaticGray:
  307.         mode->cap[XSTATICGRAY] = 1;
  308.         break;
  309.       case GrayScale:
  310.         mode->cap[XGRAYSCALE] = 1;
  311.         break;
  312.       case StaticColor:
  313.         mode->cap[XSTATICCOLOR] = 1;
  314.         break;
  315.       case PseudoColor:
  316.         mode->cap[XPSEUDOCOLOR] = 1;
  317.         break;
  318.       case TrueColor:
  319.         mode->cap[XTRUECOLOR] = 1;
  320.         break;
  321.       case DirectColor:
  322.         mode->cap[XDIRECTCOLOR] = 1;
  323.         break;
  324.       }
  325. #endif
  326. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
  327.       if (visual_rating) {
  328.         int rating;
  329. /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
  330.    564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
  331.    in <GL/glx.h> despite claiming to support
  332.    GLX_EXT_visual_rating. */
  333. #ifndef GLX_VISUAL_CAVEAT_EXT
  334. #define GLX_VISUAL_CAVEAT_EXT 0x20
  335. #endif
  336.         rc = glXGetConfig(__glutDisplay,
  337.   vlist[i], GLX_VISUAL_CAVEAT_EXT, &rating);
  338.         if (rc != 0) {
  339.           mode->cap[SLOW] = 0;
  340.           mode->cap[CONFORMANT] = 1;
  341.         } else {
  342.           switch (rating) {
  343.           case GLX_SLOW_VISUAL_EXT:
  344.             mode->cap[SLOW] = 1;
  345.             mode->cap[CONFORMANT] = 1;
  346.             break;
  347. /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
  348.    properly defined in /usr/include/GL/glxtokens.h */
  349. #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
  350. #define GLX_NON_CONFORMANT_VISUAL_EXT   0x800D
  351. #endif
  352.           case GLX_NON_CONFORMANT_VISUAL_EXT:
  353.             mode->cap[SLOW] = 0;
  354.             mode->cap[CONFORMANT] = 0;
  355.             break;
  356.           case GLX_NONE_EXT:
  357.           default:     /* XXX Hopefully this is a good default
  358.                            assumption. */
  359.             mode->cap[SLOW] = 0;
  360.             mode->cap[CONFORMANT] = 1;
  361.             break;
  362.           }
  363.         }
  364.       } else {
  365.         mode->cap[TRANSPARENT] = 0;
  366.       }
  367. #else
  368.       mode->cap[SLOW] = 0;
  369.       mode->cap[CONFORMANT] = 1;
  370. #endif
  371. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
  372.       if (visual_info) {
  373.         int transparent;
  374. /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
  375.    564 for Alpha did not properly define
  376.    GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
  377.    support GLX_EXT_visual_info. */
  378. #ifndef GLX_TRANSPARENT_TYPE_EXT
  379. #define GLX_TRANSPARENT_TYPE_EXT 0x23
  380. #endif
  381.         rc = glXGetConfig(__glutDisplay,
  382.           vlist[i], GLX_TRANSPARENT_TYPE_EXT, &transparent);
  383.         if (rc != 0) {
  384.           mode->cap[TRANSPARENT] = 0;
  385.         } else {
  386.           mode->cap[TRANSPARENT] = (transparent != GLX_NONE_EXT);
  387.         }
  388.       } else {
  389.         mode->cap[TRANSPARENT] = 0;
  390.       }
  391. #else
  392.       mode->cap[TRANSPARENT] = 0;
  393. #endif
  394. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
  395.       if (multisample) {
  396.         rc = glXGetConfig(__glutDisplay,
  397.   vlist[i], GLX_SAMPLES_SGIS, &mode->cap[SAMPLES]);
  398.         if (rc != 0) {
  399.           mode->cap[SAMPLES] = 0;
  400.         }
  401.       } else {
  402.         mode->cap[SAMPLES] = 0;
  403.       }
  404. #else
  405.       mode->cap[SAMPLES] = 0;
  406. #endif
  407.     } else {
  408. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  409.       if (fbconfig) {
  410.         GLXFBConfigSGIX fbc;
  411.         int fbconfigID, drawType, renderType;
  412.         fbc = glXGetFBConfigFromVisualSGIX(__glutDisplay, vlist[i]);
  413.         if (fbc) {
  414.           rc = glXGetFBConfigAttribSGIX(__glutDisplay, fbc,
  415.     GLX_FBCONFIG_ID_SGIX, &fbconfigID);
  416.           if ((rc == 0) && (fbconfigID != None)) {
  417.             rc = glXGetFBConfigAttribSGIX(__glutDisplay, fbc,
  418.       GLX_DRAWABLE_TYPE_SGIX, &drawType);
  419.             if ((rc == 0) && (drawType & GLX_WINDOW_BIT_SGIX)) {
  420.               rc = glXGetFBConfigAttribSGIX(__glutDisplay, fbc,
  421.         GLX_RENDER_TYPE_SGIX, &renderType);
  422.               if ((rc == 0) && (renderType & GLX_RGBA_BIT_SGIX)) {
  423.                 mode->fbc = fbc;
  424.                 mode->valid = 1;  /* Assume the best until
  425.                                      proven otherwise. */
  426. assert(glxcap[0] == GLX_RGBA);
  427.                 mode->cap[0] = 1;
  428.                 /* Start with "j = 1" to skip the GLX_RGBA attribute. */
  429.                 for (j = 1; j < NUM_GLXCAPS; j++) {
  430.                   rc = glXGetFBConfigAttribSGIX(__glutDisplay,
  431.     fbc, glxcap[j], &mode->cap[j]);
  432.                   if (rc != 0) {
  433.                     mode->valid = 0;
  434.                   }
  435.                 }
  436.                 mode->cap[XVISUAL] = (int) vlist[i]->visualid;
  437.                 mode->cap[XSTATICGRAY] = 0;
  438.                 mode->cap[XGRAYSCALE] = 0;
  439.                 mode->cap[XSTATICCOLOR] = 0;
  440.                 mode->cap[XPSEUDOCOLOR] = 0;
  441.                 mode->cap[XTRUECOLOR] = 0;
  442.                 mode->cap[XDIRECTCOLOR] = 0;
  443. #if defined(__cplusplus) || defined(c_plusplus)
  444.                 switch (vlist[i]->c_class) {
  445. #else
  446.                 switch (vlist[i]->class) {
  447. #endif
  448.                 case StaticGray:
  449.                   mode->cap[XSTATICGRAY] = 1;
  450.                   break;
  451.                 case GrayScale:
  452.                   mode->cap[XGRAYSCALE] = 1;
  453.                   break;
  454.                 case StaticColor:
  455.                   mode->cap[XSTATICCOLOR] = 1;
  456.                   break;
  457.                 case PseudoColor:
  458.                   mode->cap[XPSEUDOCOLOR] = 1;
  459.                   break;
  460.                 case TrueColor:
  461.                   mode->cap[XTRUECOLOR] = 1;
  462.                   break;
  463.                 case DirectColor:
  464.                   mode->cap[XDIRECTCOLOR] = 1;
  465.                   break;
  466.                 }
  467. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
  468.                 if (visual_rating) {
  469.                   int rating;
  470. /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
  471.    564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
  472.    in <GL/glx.h> despite claiming to support
  473.    GLX_EXT_visual_rating. */
  474. #ifndef GLX_VISUAL_CAVEAT_EXT
  475. #define GLX_VISUAL_CAVEAT_EXT 0x20
  476. #endif
  477.                   rc = glXGetFBConfigAttribSGIX(__glutDisplay,
  478.     fbc, GLX_VISUAL_CAVEAT_EXT, &rating);
  479.                   if (rc != 0) {
  480.                     mode->cap[SLOW] = 0;
  481.                     mode->cap[CONFORMANT] = 1;
  482.                   } else {
  483.                     switch (rating) {
  484.                     case GLX_SLOW_VISUAL_EXT:
  485.                       mode->cap[SLOW] = 1;
  486.                       mode->cap[CONFORMANT] = 1;
  487.                       break;
  488. /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
  489.    properly defined in /usr/include/GL/glxtokens.h */
  490. #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
  491. #define GLX_NON_CONFORMANT_VISUAL_EXT   0x800D
  492. #endif
  493.                     case GLX_NON_CONFORMANT_VISUAL_EXT:
  494.                       mode->cap[SLOW] = 0;
  495.                       mode->cap[CONFORMANT] = 0;
  496.                       break;
  497.                     case GLX_NONE_EXT:
  498.                     default:  /* XXX Hopefully this is a good
  499.                                   default assumption. */
  500.                       mode->cap[SLOW] = 0;
  501.                       mode->cap[CONFORMANT] = 1;
  502.                       break;
  503.                     }
  504.                   }
  505.                 } else {
  506.                   mode->cap[TRANSPARENT] = 0;
  507.                 }
  508. #else
  509.                 mode->cap[SLOW] = 0;
  510.                 mode->cap[CONFORMANT] = 1;
  511. #endif
  512. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
  513.                 if (visual_info) {
  514.                   int transparent;
  515. /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
  516.    564 for Alpha did not properly define
  517.    GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
  518.    support GLX_EXT_visual_info. */
  519. #ifndef GLX_TRANSPARENT_TYPE_EXT
  520. #define GLX_TRANSPARENT_TYPE_EXT 0x23
  521. #endif
  522.                   rc = glXGetFBConfigAttribSGIX(__glutDisplay,
  523.     fbc, GLX_TRANSPARENT_TYPE_EXT, &transparent);
  524.                   if (rc != 0) {
  525.                     mode->cap[TRANSPARENT] = 0;
  526.                   } else {
  527.                     mode->cap[TRANSPARENT] = (transparent != GLX_NONE_EXT);
  528.                   }
  529.                 } else {
  530.                   mode->cap[TRANSPARENT] = 0;
  531.                 }
  532. #else
  533.                 mode->cap[TRANSPARENT] = 0;
  534. #endif
  535. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
  536.                 if (multisample) {
  537.                   rc = glXGetFBConfigAttribSGIX(__glutDisplay,
  538.     fbc, GLX_SAMPLES_SGIS, &mode->cap[SAMPLES]);
  539.                   if (rc != 0) {
  540.                     mode->cap[SAMPLES] = 0;
  541.                   }
  542.                 } else {
  543.                   mode->cap[SAMPLES] = 0;
  544.                 }
  545. #else
  546.                 mode->cap[SAMPLES] = 0;
  547. #endif
  548.               } else {
  549.                 /* Fbconfig is not RGBA; GLUT only uses RGBA
  550.                    FBconfigs. */
  551.                 /* XXX Code could be exteneded to handle color
  552.                    index FBconfigs, but seems a color index
  553.                    window-renderable FBconfig would also be
  554.                    advertised as an X visual. */
  555.                 mode->valid = 0;
  556.               }
  557.             } else {
  558.               /* Fbconfig does not support window rendering;
  559.                  not a valid FBconfig for GLUT windows. */
  560.               mode->valid = 0;
  561.             }
  562.           } else {
  563.             /* FBconfig ID is None (zero); not a valid
  564.                FBconfig. */
  565.             mode->valid = 0;
  566.           }
  567.         } else {
  568.           /* FBconfig ID is None (zero); not a valid FBconfig. */
  569.           mode->valid = 0;
  570.         }
  571.       } else {
  572.         /* No SGIX_fbconfig GLX sever implementation support. */
  573.         mode->valid = 0;
  574.       }
  575. #else
  576.       /* No SGIX_fbconfig GLX extension API support. */
  577.       mode->valid = 0;
  578. #endif
  579.     }
  580.   }
  581.   free(vlist);
  582.   *nitems_return = n;
  583.   return fbmodes;
  584. }
  585. static XVisualInfo *
  586. findMatch(FrameBufferMode * fbmodes, int nfbmodes,
  587.   Criterion * criteria, int ncriteria, void **fbc)
  588. {
  589.   FrameBufferMode *found;
  590.   int *bestScore, *thisScore;
  591.   int i, j, numok, result, worse, better;
  592.   found = NULL;
  593.   numok = 1;            /* "num" capability is indexed from 1,
  594.                            not 0. */
  595.   /* XXX alloca canidate. */
  596.   bestScore = (int *) malloc(ncriteria * sizeof(int));
  597.   if (!bestScore)
  598.     __glutFatalError("out of memory.");
  599.   for (j = 0; j < ncriteria; j++) {
  600.     /* Very negative number. */
  601.     bestScore[j] = -32768;
  602.   }
  603.   /* XXX alloca canidate. */
  604.   thisScore = (int *) malloc(ncriteria * sizeof(int));
  605.   if (!thisScore)
  606.     __glutFatalError("out of memory.");
  607.   for (i = 0; i < nfbmodes; i++) {
  608.     if (fbmodes[i].valid) {
  609. #ifdef TEST
  610. #if !defined(_WIN32)
  611.       if (verbose)
  612.         printf("Visual 0x%xn", fbmodes[i].vi->visualid);
  613. #endif
  614. #endif
  615.       worse = 0;
  616.       better = 0;
  617.       for (j = 0; j < ncriteria; j++) {
  618.         int cap, cvalue, fbvalue;
  619.         cap = criteria[j].capability;
  620.         cvalue = criteria[j].value;
  621.         if (cap == NUM) {
  622.           fbvalue = numok;
  623.         } else {
  624.           fbvalue = fbmodes[i].cap[cap];
  625.         }
  626. #ifdef TEST
  627.         if (verbose)
  628.           printf("  %s %s %d to %dn",
  629.             capstr[cap], compstr[criteria[j].comparison], cvalue, fbvalue);
  630. #endif
  631.         switch (criteria[j].comparison) {
  632.         case EQ:
  633.           result = cvalue == fbvalue;
  634.           thisScore[j] = 1;
  635.           break;
  636.         case NEQ:
  637.           result = cvalue != fbvalue;
  638.           thisScore[j] = 1;
  639.           break;
  640.         case LT:
  641.           result = fbvalue < cvalue;
  642.           thisScore[j] = fbvalue - cvalue;
  643.           break;
  644.         case GT:
  645.           result = fbvalue > cvalue;
  646.           thisScore[j] = fbvalue - cvalue;
  647.           break;
  648.         case LTE:
  649.           result = fbvalue <= cvalue;
  650.           thisScore[j] = fbvalue - cvalue;
  651.           break;
  652.         case GTE:
  653.           result = (fbvalue >= cvalue);
  654.           thisScore[j] = fbvalue - cvalue;
  655.           break;
  656.         case MIN:
  657.           result = fbvalue >= cvalue;
  658.           thisScore[j] = cvalue - fbvalue;
  659.           break;
  660.         }
  661. #ifdef TEST
  662.         if (verbose)
  663.           printf("                result=%d   score=%d   bestScore=%dn", result, thisScore[j], bestScore[j]);
  664. #endif
  665.         if (result) {
  666.           if (better || thisScore[j] > bestScore[j]) {
  667. better = 1;
  668.           } else if (thisScore[j] == bestScore[j]) {
  669.             /* Keep looking. */
  670.           } else {
  671.             goto nextFBM;
  672.           }
  673.         } else {
  674. if (cap == NUM) {
  675.             worse = 1;
  676.           } else {
  677.             goto nextFBM;
  678.           }
  679.         }
  680.       }
  681.       if (better && !worse) {
  682.         found = &fbmodes[i];
  683.         for (j = 0; j < ncriteria; j++) {
  684.           bestScore[j] = thisScore[j];
  685.         }
  686.       }
  687.       numok++;
  688.     nextFBM:;
  689.     }
  690.   }
  691.   free(bestScore);
  692.   free(thisScore);
  693.   if (found) {
  694. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  695.     *fbc = found->fbc;
  696. #endif
  697. return found->vi;
  698.   } else {
  699.     return NULL;
  700.   }
  701. }
  702. static int
  703. parseCriteria(char *word, Criterion * criterion, int *mask,
  704.   Bool * allowDoubleAsSingle)
  705. {
  706.   char *cstr, *vstr, *response;
  707.   int comparator, value;
  708.   int rgb, rgba, acc, acca, count, i;
  709.   cstr = strpbrk(word, "=><!~");
  710.   if (cstr) {
  711.     switch (cstr[0]) {
  712.     case '=':
  713.       comparator = EQ;
  714.       vstr = &cstr[1];
  715.       break;
  716.     case '~':
  717.       comparator = MIN;
  718.       vstr = &cstr[1];
  719.       break;
  720.     case '>':
  721.       if (cstr[1] == '=') {
  722.         comparator = GTE;
  723.         vstr = &cstr[2];
  724.       } else {
  725.         comparator = GT;
  726.         vstr = &cstr[1];
  727.       }
  728.       break;
  729.     case '<':
  730.       if (cstr[1] == '=') {
  731.         comparator = LTE;
  732.         vstr = &cstr[2];
  733.       } else {
  734.         comparator = LT;
  735.         vstr = &cstr[1];
  736.       }
  737.       break;
  738.     case '!':
  739.       if (cstr[1] == '=') {
  740.         comparator = NEQ;
  741.         vstr = &cstr[2];
  742.       } else {
  743.         return -1;
  744.       }
  745.       break;
  746.     default:
  747.       return -1;
  748.     }
  749.     value = (int) strtol(vstr, &response, 0);
  750.     if (response == vstr) {
  751.       /* Not a valid number. */
  752.       return -1;
  753.     }
  754.     *cstr = '';
  755.   } else {
  756.     comparator = NONE;
  757.   }
  758.   switch (word[0]) {
  759.   case 'a':
  760.     if (!strcmp(word, "alpha")) {
  761.       criterion[0].capability = ALPHA_SIZE;
  762.       if (comparator == NONE) {
  763.         criterion[0].comparison = GTE;
  764.         criterion[0].value = 1;
  765.       } else {
  766.         criterion[0].comparison = comparator;
  767.         criterion[0].value = value;
  768.       }
  769.       *mask |= (1 << RGBA);
  770.       *mask |= (1 << ALPHA_SIZE);
  771.       *mask |= (1 << RGBA_MODE);
  772.       return 1;
  773.     }
  774.     acca = !strcmp(word, "acca");
  775.     acc = !strcmp(word, "acc");
  776.     if (acc || acca) {
  777.       criterion[0].capability = ACCUM_RED_SIZE;
  778.       criterion[1].capability = ACCUM_GREEN_SIZE;
  779.       criterion[2].capability = ACCUM_BLUE_SIZE;
  780.       criterion[3].capability = ACCUM_ALPHA_SIZE;
  781.       if (acca) {
  782.         count = 4;
  783.       } else {
  784.         count = 3;
  785.         criterion[3].comparison = MIN;
  786.         criterion[3].value = 0;
  787.       }
  788.       if (comparator == NONE) {
  789.         comparator = GTE;
  790.         value = 8;
  791.       }
  792.       for (i = 0; i < count; i++) {
  793.         criterion[i].comparison = comparator;
  794.         criterion[i].value = value;
  795.       }
  796.       *mask |= (1 << ACCUM_RED_SIZE);
  797.       return 4;
  798.     }
  799.     if (!strcmp(word, "auxbufs")) {
  800.       criterion[0].capability = AUX_BUFFERS;
  801.       if (comparator == NONE) {
  802.         criterion[0].comparison = MIN;
  803.         criterion[0].value = 1;
  804.       } else {
  805.         criterion[0].comparison = comparator;
  806.         criterion[0].value = value;
  807.       }
  808.       *mask |= (1 << AUX_BUFFERS);
  809.       return 1;
  810.     }
  811.     return -1;
  812.   case 'b':
  813.     if (!strcmp(word, "blue")) {
  814.       criterion[0].capability = BLUE_SIZE;
  815.       if (comparator == NONE) {
  816.         criterion[0].comparison = GTE;
  817.         criterion[0].value = 1;
  818.       } else {
  819.         criterion[0].comparison = comparator;
  820.         criterion[0].value = value;
  821.       }
  822.       *mask |= (1 << RGBA);
  823.       *mask |= (1 << RGBA_MODE);
  824.       return 1;
  825.     }
  826.     if (!strcmp(word, "buffer")) {
  827.       criterion[0].capability = BUFFER_SIZE;
  828.       if (comparator == NONE) {
  829.         criterion[0].comparison = GTE;
  830.         criterion[0].value = 1;
  831.       } else {
  832.         criterion[0].comparison = comparator;
  833.         criterion[0].value = value;
  834.       }
  835.       return 1;
  836.     }
  837.     return -1;
  838.   case 'c':
  839.     if (!strcmp(word, "conformant")) {
  840.       criterion[0].capability = CONFORMANT;
  841.       if (comparator == NONE) {
  842.         criterion[0].comparison = EQ;
  843.         criterion[0].value = 1;
  844.       } else {
  845.         criterion[0].comparison = comparator;
  846.         criterion[0].value = value;
  847.       }
  848.       *mask |= (1 << CONFORMANT);
  849.       return 1;
  850.     }
  851.     return -1;
  852.   case 'd':
  853.     if (!strcmp(word, "depth")) {
  854.       criterion[0].capability = DEPTH_SIZE;
  855.       if (comparator == NONE) {
  856.         criterion[0].comparison = GTE;
  857.         criterion[0].value = 12;
  858.       } else {
  859.         criterion[0].comparison = comparator;
  860.         criterion[0].value = value;
  861.       }
  862.       *mask |= (1 << DEPTH_SIZE);
  863.       return 1;
  864.     }
  865.     if (!strcmp(word, "double")) {
  866.       criterion[0].capability = DOUBLEBUFFER;
  867.       if (comparator == NONE) {
  868.         criterion[0].comparison = EQ;
  869.         criterion[0].value = 1;
  870.       } else {
  871.         criterion[0].comparison = comparator;
  872.         criterion[0].value = value;
  873.       }
  874.       *mask |= (1 << DOUBLEBUFFER);
  875.       return 1;
  876.     }
  877.     return -1;
  878.   case 'g':
  879.     if (!strcmp(word, "green")) {
  880.       criterion[0].capability = GREEN_SIZE;
  881.       if (comparator == NONE) {
  882.         criterion[0].comparison = GTE;
  883.         criterion[0].value = 1;
  884.       } else {
  885.         criterion[0].comparison = comparator;
  886.         criterion[0].value = value;
  887.       }
  888.       *mask |= (1 << RGBA);
  889.       *mask |= (1 << RGBA_MODE);
  890.       return 1;
  891.     }
  892.     return -1;
  893.   case 'i':
  894.     if (!strcmp(word, "index")) {
  895.       criterion[0].capability = RGBA;
  896.       criterion[0].comparison = EQ;
  897.       criterion[0].value = 0;
  898.       *mask |= (1 << RGBA);
  899.       *mask |= (1 << CI_MODE);
  900.       criterion[1].capability = BUFFER_SIZE;
  901.       if (comparator == NONE) {
  902.         criterion[1].comparison = GTE;
  903.         criterion[1].value = 1;
  904.       } else {
  905.         criterion[1].comparison = comparator;
  906.         criterion[1].value = value;
  907.       }
  908.       return 2;
  909.     }
  910.     return -1;
  911.   case 'l':
  912.     if (!strcmp(word, "luminance")) {
  913.       criterion[0].capability = RGBA;
  914.       criterion[0].comparison = EQ;
  915.       criterion[0].value = 1;
  916.       criterion[1].capability = RED_SIZE;
  917.       if (comparator == NONE) {
  918.         criterion[1].comparison = GTE;
  919.         criterion[1].value = 1;
  920.       } else {
  921.         criterion[1].comparison = comparator;
  922.         criterion[1].value = value;
  923.       }
  924.       criterion[2].capability = GREEN_SIZE;
  925.       criterion[2].comparison = EQ;
  926.       criterion[2].value = 0;
  927.       criterion[3].capability = BLUE_SIZE;
  928.       criterion[3].comparison = EQ;
  929.       criterion[3].value = 0;
  930.       *mask |= (1 << RGBA);
  931.       *mask |= (1 << RGBA_MODE);
  932.       *mask |= (1 << LUMINANCE_MODE);
  933.       return 4;
  934.     }
  935.     return -1;
  936.   case 'n':
  937.     if (!strcmp(word, "num")) {
  938.       criterion[0].capability = NUM;
  939.       if (comparator == NONE) {
  940.         return -1;
  941.       } else {
  942.         criterion[0].comparison = comparator;
  943.         criterion[0].value = value;
  944.         return 1;
  945.       }
  946.     }
  947.     return -1;
  948.   case 'r':
  949.     if (!strcmp(word, "red")) {
  950.       criterion[0].capability = RED_SIZE;
  951.       if (comparator == NONE) {
  952.         criterion[0].comparison = GTE;
  953.         criterion[0].value = 1;
  954.       } else {
  955.         criterion[0].comparison = comparator;
  956.         criterion[0].value = value;
  957.       }
  958.       *mask |= (1 << RGBA);
  959.       *mask |= (1 << RGBA_MODE);
  960.       return 1;
  961.     }
  962.     rgba = !strcmp(word, "rgba");
  963.     rgb = !strcmp(word, "rgb");
  964.     if (rgb || rgba) {
  965.       criterion[0].capability = RGBA;
  966.       criterion[0].comparison = EQ;
  967.       criterion[0].value = 1;
  968.       criterion[1].capability = RED_SIZE;
  969.       criterion[2].capability = GREEN_SIZE;
  970.       criterion[3].capability = BLUE_SIZE;
  971.       criterion[4].capability = ALPHA_SIZE;
  972.       if (rgba) {
  973.         count = 5;
  974.       } else {
  975.         count = 4;
  976.         criterion[4].comparison = MIN;
  977.         criterion[4].value = 0;
  978.       }
  979.       if (comparator == NONE) {
  980.         comparator = GTE;
  981.         value = 1;
  982.       }
  983.       for (i = 1; i < count; i++) {
  984.         criterion[i].comparison = comparator;
  985.         criterion[i].value = value;
  986.       }
  987.       *mask |= (1 << RGBA);
  988.       *mask |= (1 << RGBA_MODE);
  989.       return 5;
  990.     }
  991.     return -1;
  992.   case 's':
  993.     if (!strcmp(word, "stencil")) {
  994.       criterion[0].capability = STENCIL_SIZE;
  995.       if (comparator == NONE) {
  996.         criterion[0].comparison = MIN;
  997.         criterion[0].value = 1;
  998.       } else {
  999.         criterion[0].comparison = comparator;
  1000.         criterion[0].value = value;
  1001.       }
  1002.       *mask |= (1 << STENCIL_SIZE);
  1003.       return 1;
  1004.     }
  1005.     if (!strcmp(word, "single")) {
  1006.       criterion[0].capability = DOUBLEBUFFER;
  1007.       if (comparator == NONE) {
  1008.         criterion[0].comparison = EQ;
  1009.         criterion[0].value = 0;
  1010.         *allowDoubleAsSingle = True;
  1011.         *mask |= (1 << DOUBLEBUFFER);
  1012.         return 1;
  1013.       } else {
  1014.         return -1;
  1015.       }
  1016.     }
  1017.     if (!strcmp(word, "stereo")) {
  1018.       criterion[0].capability = STEREO;
  1019.       if (comparator == NONE) {
  1020.         criterion[0].comparison = EQ;
  1021.         criterion[0].value = 1;
  1022.       } else {
  1023.         criterion[0].comparison = comparator;
  1024.         criterion[0].value = value;
  1025.       }
  1026.       *mask |= (1 << STEREO);
  1027.       return 1;
  1028.     }
  1029.     if (!strcmp(word, "samples")) {
  1030.       criterion[0].capability = SAMPLES;
  1031.       if (comparator == NONE) {
  1032.         criterion[0].comparison = LTE;
  1033.         criterion[0].value = 4;
  1034.       } else {
  1035.         criterion[0].comparison = comparator;
  1036.         criterion[0].value = value;
  1037.       }
  1038.       *mask |= (1 << SAMPLES);
  1039.       return 1;
  1040.     }
  1041.     if (!strcmp(word, "slow")) {
  1042.       criterion[0].capability = SLOW;
  1043.       if (comparator == NONE) {
  1044.         /* Just "slow" means permit fast visuals, but accept
  1045.            slow ones in preference. Presumably the slow ones
  1046.            must be higher quality or something else desirable. */
  1047.         criterion[0].comparison = GTE;
  1048.         criterion[0].value = 0;
  1049.       } else {
  1050.         criterion[0].comparison = comparator;
  1051.         criterion[0].value = value;
  1052.       }
  1053.       *mask |= (1 << SLOW);
  1054.       return 1;
  1055.     }
  1056.     return -1;
  1057. #if defined(_WIN32)
  1058.   case 'w':
  1059.     if (!strcmp(word, "win32pfd")) {
  1060.       criterion[0].capability = XVISUAL;
  1061.       if (comparator == NONE) {
  1062.         return -1;
  1063.       } else {
  1064.         criterion[0].comparison = comparator;
  1065.         criterion[0].value = value;
  1066.         return 1;
  1067.       }
  1068.     }
  1069.     return -1;
  1070. #endif
  1071. #if !defined(_WIN32)
  1072.   case 'x':
  1073.     if (!strcmp(word, "xvisual")) {
  1074.       if (comparator == NONE) {
  1075.         return -1;
  1076.       } else {
  1077.         criterion[0].capability = XVISUAL;
  1078.         criterion[0].comparison = comparator;
  1079.         criterion[0].value = value;
  1080.         /* Set everything in "mask" so that no default criteria
  1081.            get used.  Assume the program really wants the
  1082.            xvisual specified. */
  1083.         *mask |= ~0;
  1084.         return 1;
  1085.       }
  1086.     }
  1087.     /* Be a little over-eager to fill in the comparison and
  1088.        value so we won't have to replicate the code after each
  1089.        string match. */
  1090.     if (comparator == NONE) {
  1091.       criterion[0].comparison = EQ;
  1092.       criterion[0].value = 1;
  1093.     } else {
  1094.       criterion[0].comparison = comparator;
  1095.       criterion[0].value = value;
  1096.     }
  1097.     if (!strcmp(word, "xstaticgray")) {
  1098.       criterion[0].capability = XSTATICGRAY;
  1099.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1100.                                        class selected. */
  1101.       return 1;
  1102.     }
  1103.     if (!strcmp(word, "xgrayscale")) {
  1104.       criterion[0].capability = XGRAYSCALE;
  1105.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1106.                                        class selected. */
  1107.       return 1;
  1108.     }
  1109.     if (!strcmp(word, "xstaticcolor")) {
  1110.       criterion[0].capability = XSTATICCOLOR;
  1111.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1112.                                        class selected. */
  1113.       return 1;
  1114.     }
  1115.     if (!strcmp(word, "xpseudocolor")) {
  1116.       criterion[0].capability = XPSEUDOCOLOR;
  1117.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1118.                                        class selected. */
  1119.       return 1;
  1120.     }
  1121.     if (!strcmp(word, "xtruecolor")) {
  1122.       criterion[0].capability = XTRUECOLOR;
  1123.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1124.                                        class selected. */
  1125.       return 1;
  1126.     }
  1127.     if (!strcmp(word, "xdirectcolor")) {
  1128.       criterion[0].capability = XDIRECTCOLOR;
  1129.       *mask |= (1 << XSTATICGRAY);  /* Indicates _any_ visual
  1130.                                        class selected. */
  1131.       return 1;
  1132.     }
  1133.     return -1;
  1134. #endif
  1135.   default:
  1136.     return -1;
  1137.   }
  1138. }
  1139. static Criterion *
  1140. parseModeString(char *mode, int *ncriteria, Bool * allowDoubleAsSingle,
  1141.   Criterion * requiredCriteria, int nRequired, int requiredMask)
  1142. {
  1143.   Criterion *criteria = NULL;
  1144.   int n, mask, parsed, i;
  1145.   char *copy, *word;
  1146.   *allowDoubleAsSingle = False;
  1147.   copy = __glutStrdup(mode);
  1148.   /* Attempt to estimate how many criteria entries should be
  1149.      needed. */
  1150.   n = 0;
  1151.   word = strtok(copy, " t");
  1152.   while (word) {
  1153.     n++;
  1154.     word = strtok(NULL, " t");
  1155.   }
  1156.   /* Overestimate by 4 times ("rgba" might add four criteria
  1157.      entries) plus add in possible defaults plus space for
  1158.      required criteria. */
  1159.   criteria = (Criterion *) malloc((4 * n + 30 + nRequired) * sizeof(Criterion));
  1160.   if (!criteria) {
  1161.     __glutFatalError("out of memory.");
  1162.   }
  1163.   /* Re-copy the copy of the mode string. */
  1164.   strcpy(copy, mode);
  1165.   /* First add the required criteria (these match at the
  1166.      highest priority). Typically these will be used to force a
  1167.      specific level (layer), transparency, and/or visual type. */
  1168.   mask = requiredMask;
  1169.   for (i = 0; i < nRequired; i++) {
  1170.     criteria[i] = requiredCriteria[i];
  1171.   }
  1172.   n = nRequired;
  1173.   word = strtok(copy, " t");
  1174.   while (word) {
  1175.     parsed = parseCriteria(word, &criteria[n], &mask, allowDoubleAsSingle);
  1176.     if (parsed >= 0) {
  1177.       n += parsed;
  1178.     } else {
  1179.       __glutWarning("Unrecognized display string word: %s (ignoring)n", word);
  1180.     }
  1181.     word = strtok(NULL, " t");
  1182.   }
  1183. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
  1184.   if (__glutIsSupportedByGLX("GLX_SGIS_multisample")) {
  1185.     if (!(mask & (1 << SAMPLES))) {
  1186.       criteria[n].capability = SAMPLES;
  1187.       criteria[n].comparison = EQ;
  1188.       criteria[n].value = 0;
  1189.       n++;
  1190.     } else {
  1191.       /* Multisample visuals are marked nonconformant.  If
  1192.          multisampling was requeste and no conformant
  1193.          preference was set, assume that we will settle for a
  1194.          non-conformant visual to get multisampling. */
  1195.       if (!(mask & (1 << CONFORMANT))) {
  1196.         criteria[n].capability = CONFORMANT;
  1197.         criteria[n].comparison = MIN;
  1198.         criteria[n].value = 0;
  1199.         n++;
  1200.         mask |= (1 << CONFORMANT);
  1201.       }
  1202.     }
  1203.   }
  1204. #endif
  1205. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
  1206.   if (__glutIsSupportedByGLX("GLX_EXT_visual_info")) {
  1207.     if (!(mask & (1 << TRANSPARENT))) {
  1208.       criteria[n].capability = TRANSPARENT;
  1209.       criteria[n].comparison = EQ;
  1210.       criteria[n].value = 0;
  1211.       n++;
  1212.     }
  1213.   }
  1214. #endif
  1215. #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
  1216.   if (__glutIsSupportedByGLX("GLX_EXT_visual_rating")) {
  1217.     if (!(mask & (1 << SLOW))) {
  1218.       criteria[n].capability = SLOW;
  1219.       criteria[n].comparison = EQ;
  1220.       criteria[n].value = 0;
  1221.       n++;
  1222.     }
  1223.     if (!(mask & (1 << CONFORMANT))) {
  1224.       criteria[n].capability = CONFORMANT;
  1225.       criteria[n].comparison = EQ;
  1226.       criteria[n].value = 1;
  1227.       n++;
  1228.     }
  1229.   }
  1230. #endif
  1231.   if (!(mask & (1 << ACCUM_RED_SIZE))) {
  1232.     criteria[n].capability = ACCUM_RED_SIZE;
  1233.     criteria[n].comparison = MIN;
  1234.     criteria[n].value = 0;
  1235.     criteria[n + 1].capability = ACCUM_GREEN_SIZE;
  1236.     criteria[n + 1].comparison = MIN;
  1237.     criteria[n + 1].value = 0;
  1238.     criteria[n + 2].capability = ACCUM_BLUE_SIZE;
  1239.     criteria[n + 2].comparison = MIN;
  1240.     criteria[n + 2].value = 0;
  1241.     criteria[n + 3].capability = ACCUM_ALPHA_SIZE;
  1242.     criteria[n + 3].comparison = MIN;
  1243.     criteria[n + 3].value = 0;
  1244.     n += 4;
  1245.   }
  1246.   if (!(mask & (1 << AUX_BUFFERS))) {
  1247.     criteria[n].capability = AUX_BUFFERS;
  1248.     criteria[n].comparison = MIN;
  1249.     criteria[n].value = 0;
  1250.     n++;
  1251.   }
  1252.   if (!(mask & (1 << RGBA))) {
  1253.     criteria[n].capability = RGBA;
  1254.     criteria[n].comparison = EQ;
  1255.     criteria[n].value = 1;
  1256.     criteria[n + 1].capability = RED_SIZE;
  1257.     criteria[n + 1].comparison = GTE;
  1258.     criteria[n + 1].value = 1;
  1259.     criteria[n + 2].capability = GREEN_SIZE;
  1260.     criteria[n + 2].comparison = GTE;
  1261.     criteria[n + 2].value = 1;
  1262.     criteria[n + 3].capability = BLUE_SIZE;
  1263.     criteria[n + 3].comparison = GTE;
  1264.     criteria[n + 3].value = 1;
  1265.     criteria[n + 4].capability = ALPHA_SIZE;
  1266.     criteria[n + 4].comparison = MIN;
  1267.     criteria[n + 4].value = 0;
  1268.     n += 5;
  1269.     mask |= (1 << RGBA_MODE);
  1270.   }
  1271. #if !defined(_WIN32)
  1272.   if (!(mask & (1 << XSTATICGRAY))) {
  1273.     assert(isMesaGLX != -1);
  1274.     if ((mask & (1 << RGBA_MODE)) && !isMesaGLX) {
  1275.       /* Normally, request an RGBA mode visual be TrueColor,
  1276.          except in the case of Mesa where we trust Mesa (and
  1277.          other code in GLUT) to handle any type of RGBA visual
  1278.          reasonably. */
  1279.       if (mask & (1 << LUMINANCE_MODE)) {
  1280. /* If RGBA luminance was requested, actually go for
  1281.    a StaticGray visual. */
  1282.         criteria[n].capability = XSTATICGRAY;
  1283.       } else {
  1284.         criteria[n].capability = XTRUECOLOR;
  1285.       }
  1286.       criteria[n].value = 1;
  1287.       criteria[n].comparison = EQ;
  1288.       n++;
  1289.     }
  1290.     if (mask & (1 << CI_MODE)) {
  1291.       criteria[n].capability = XPSEUDOCOLOR;
  1292.       criteria[n].value = 1;
  1293.       criteria[n].comparison = EQ;
  1294.       n++;
  1295.     }
  1296.   }
  1297. #endif
  1298.   if (!(mask & (1 << STEREO))) {
  1299.     criteria[n].capability = STEREO;
  1300.     criteria[n].comparison = EQ;
  1301.     criteria[n].value = 0;
  1302.     n++;
  1303.   }
  1304.   if (!(mask & (1 << DOUBLEBUFFER))) {
  1305.     criteria[n].capability = DOUBLEBUFFER;
  1306.     criteria[n].comparison = EQ;
  1307.     criteria[n].value = 0;
  1308.     *allowDoubleAsSingle = True;
  1309.     n++;
  1310.   }
  1311.   if (!(mask & (1 << DEPTH_SIZE))) {
  1312.     criteria[n].capability = DEPTH_SIZE;
  1313.     criteria[n].comparison = MIN;
  1314.     criteria[n].value = 0;
  1315.     n++;
  1316.   }
  1317.   if (!(mask & (1 << STENCIL_SIZE))) {
  1318.     criteria[n].capability = STENCIL_SIZE;
  1319.     criteria[n].comparison = MIN;
  1320.     criteria[n].value = 0;
  1321.     n++;
  1322.   }
  1323.   if (!(mask & (1 << LEVEL))) {
  1324.     criteria[n].capability = LEVEL;
  1325.     criteria[n].comparison = EQ;
  1326.     criteria[n].value = 0;
  1327.     n++;
  1328.   }
  1329.   if (n) {
  1330.     /* Since over-estimated the size needed; squeeze it down to
  1331.        reality. */
  1332.     criteria = (Criterion *) realloc(criteria, n * sizeof(Criterion));
  1333.     if (!criteria) {
  1334.       /* Should never happen since should be shrinking down! */
  1335.       __glutFatalError("out of memory.");
  1336.     }
  1337.   } else {
  1338.     /* For portability, avoid "realloc(ptr,0)" call. */
  1339.     free(criteria);
  1340.     criteria = NULL;
  1341.   }
  1342.   free(copy);
  1343.   *ncriteria = n;
  1344.   return criteria;
  1345. }
  1346. static FrameBufferMode *fbmodes = NULL;
  1347. static int nfbmodes = 0;
  1348. static XVisualInfo *
  1349. getVisualInfoFromString(char *string, Bool * treatAsSingle,
  1350.   Criterion * requiredCriteria, int nRequired, int requiredMask, void **fbc)
  1351. {
  1352.   Criterion *criteria;
  1353.   XVisualInfo *visinfo;
  1354.   Bool allowDoubleAsSingle;
  1355.   int ncriteria, i;
  1356.   /* In WIN32, after changing display settings, the visuals might change.
  1357.   (e.g. if entering game mode with a different bitdepth!)
  1358.   Therefore, reload the visuals each time they are queried. */
  1359. #ifdef WIN32
  1360.   if (fbmodes) {
  1361.   free(fbmodes);
  1362.   fbmodes = NULL;
  1363.   nfbmodes = 0;
  1364.   }
  1365. #endif
  1366.   if (!fbmodes) {
  1367.     fbmodes = loadVisuals(&nfbmodes);
  1368.   }
  1369.   criteria = parseModeString(string, &ncriteria,
  1370.     &allowDoubleAsSingle, requiredCriteria, nRequired, requiredMask);
  1371.   if (criteria == NULL) {
  1372.     __glutWarning("failed to parse mode string");
  1373.     return NULL;
  1374.   }
  1375. #ifdef TEST
  1376.   printCriteria(criteria, ncriteria);
  1377. #endif
  1378.   visinfo = findMatch(fbmodes, nfbmodes, criteria, ncriteria, fbc);
  1379.   if (visinfo) {
  1380.     *treatAsSingle = 0;
  1381.   } else {
  1382.     if (allowDoubleAsSingle) {
  1383.       /* Rewrite criteria so that we now look for a double
  1384.          buffered visual which will then get treated as a
  1385.          single buffered visual. */
  1386.       for (i = 0; i < ncriteria; i++) {
  1387.         if (criteria[i].capability == DOUBLEBUFFER
  1388.           && criteria[i].comparison == EQ
  1389.           && criteria[i].value == 0) {
  1390.           criteria[i].value = 1;
  1391.         }
  1392.       }
  1393.       visinfo = findMatch(fbmodes, nfbmodes, criteria, ncriteria, fbc);
  1394.       if (visinfo) {
  1395.         *treatAsSingle = 1;
  1396.       }
  1397.     }
  1398.   }
  1399.   free(criteria);
  1400.   if (visinfo) {
  1401. #if defined(_WIN32)
  1402.     /* We could have a valid pixel format for drawing to a
  1403.        bitmap. However, we don't want to draw into a bitmap, we
  1404.        need one that can be used with a window, so make sure
  1405.        that this is true. */
  1406.     if (!(visinfo->dwFlags & PFD_DRAW_TO_WINDOW))
  1407.       return NULL;
  1408. #endif
  1409.     return visinfo;
  1410.   } else {
  1411.     return NULL;
  1412.   }
  1413. }
  1414. /* CENTRY */
  1415. void APIENTRY
  1416. glutInitDisplayString(const char *string)
  1417. {
  1418. #ifdef _WIN32
  1419.   XHDC = GetDC(GetDesktopWindow());
  1420. #endif
  1421.   __glutDetermineVisualFromString = getVisualInfoFromString;
  1422.   if (__glutDisplayString) {
  1423.     free(__glutDisplayString);
  1424.   }
  1425.   if (string) {
  1426.     __glutDisplayString = __glutStrdup(string);
  1427.     if (!__glutDisplayString)
  1428.       __glutFatalError("out of memory.");
  1429.   } else {
  1430.     __glutDisplayString = NULL;
  1431.   }
  1432. }
  1433. /* ENDCENTRY */
  1434. #ifdef TEST
  1435. Criterion requiredWindowCriteria[] =
  1436. {
  1437.   {LEVEL, EQ, 0},
  1438.   {TRANSPARENT, EQ, 0}
  1439. };
  1440. int numRequiredWindowCriteria = sizeof(requiredWindowCriteria) / sizeof(Criterion);
  1441. int requiredWindowCriteriaMask = (1 << LEVEL) | (1 << TRANSPARENT);
  1442. Criterion requiredOverlayCriteria[] =
  1443. {
  1444.   {LEVEL, EQ, 1},
  1445.   {TRANSPARENT, EQ, 1},
  1446.   {XPSEUDOCOLOR, EQ, 1},
  1447.   {RGBA, EQ, 0},
  1448.   {BUFFER_SIZE, GTE, 1}
  1449. };
  1450. int numRequiredOverlayCriteria = sizeof(requiredOverlayCriteria) / sizeof(Criterion);
  1451. int requiredOverlayCriteriaMask =
  1452. (1 << LEVEL) | (1 << TRANSPARENT) | (1 << XSTATICGRAY) | (1 << RGBA) | (1 << CI_MODE);
  1453. int
  1454. main(int argc, char **argv)
  1455. {
  1456.   Display *dpy;
  1457.   XVisualInfo *vinfo;
  1458.   Bool treatAsSingle;
  1459.   char *str, buffer[1024];
  1460.   int tty = isatty(fileno(stdin));
  1461.   int overlay = 0, showconfig = 0;
  1462. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  1463.   GLXFBConfigSGIX fbc;
  1464. #else
  1465.   void *fbc;
  1466. #endif
  1467. #if !defined(_WIN32)
  1468.   dpy = XOpenDisplay(NULL);
  1469.   if (dpy == NULL) {
  1470.     printf("Could not connect to X servern");
  1471.     exit(1);
  1472.   }
  1473.   __glutDisplay = dpy;
  1474.   __glutScreen = DefaultScreen(__glutDisplay);
  1475. #endif
  1476.   while (!feof(stdin)) {
  1477.     if (tty)
  1478.       printf("dstr> ");
  1479.     str = gets(buffer);
  1480.     if (str) {
  1481.       printf("n");
  1482.       if (!strcmp("v", str)) {
  1483.         verbose = 1 - verbose;
  1484.         printf("verbose = %dnn", verbose);
  1485.       } else if (!strcmp("s", str)) {
  1486.         showconfig = 1 - showconfig;
  1487.         printf("showconfig = %dnn", showconfig);
  1488.       } else if (!strcmp("o", str)) {
  1489.         overlay = 1 - overlay;
  1490.         printf("overlay = %dnn", overlay);
  1491.       } else {
  1492.         if (overlay) {
  1493.           vinfo = getVisualInfoFromString(str, &treatAsSingle,
  1494.             requiredOverlayCriteria, numRequiredOverlayCriteria, requiredOverlayCriteriaMask, (void**) &fbc);
  1495.         } else {
  1496.           vinfo = getVisualInfoFromString(str, &treatAsSingle,
  1497.             requiredWindowCriteria, numRequiredWindowCriteria, requiredWindowCriteriaMask, (void**) &fbc);
  1498.         }
  1499.         if (vinfo) {
  1500.           printf("n");
  1501.           if (!tty)
  1502.             printf("Display string: %s", str);
  1503. #ifdef _WIN32
  1504.           printf("Visual = 0x%xn", 0);
  1505. #else
  1506.           printf("Visual = 0x%x%sn", vinfo->visualid, fbc ? " (needs FBC)" : "");
  1507. #endif
  1508.           if (treatAsSingle) {
  1509.             printf("Treat as SINGLE.n");
  1510.           }
  1511.           if (showconfig) {
  1512.             int glxCapable, bufferSize, level, renderType, doubleBuffer,
  1513.               stereo, auxBuffers, redSize, greenSize, blueSize,
  1514.               alphaSize, depthSize, stencilSize, acRedSize, acGreenSize,
  1515.               acBlueSize, acAlphaSize;
  1516.             glXGetConfig(dpy, vinfo, GLX_BUFFER_SIZE, &bufferSize);
  1517.             glXGetConfig(dpy, vinfo, GLX_LEVEL, &level);
  1518.             glXGetConfig(dpy, vinfo, GLX_RGBA, &renderType);
  1519.             glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &doubleBuffer);
  1520.             glXGetConfig(dpy, vinfo, GLX_STEREO, &stereo);
  1521.             glXGetConfig(dpy, vinfo, GLX_AUX_BUFFERS, &auxBuffers);
  1522.             glXGetConfig(dpy, vinfo, GLX_RED_SIZE, &redSize);
  1523.             glXGetConfig(dpy, vinfo, GLX_GREEN_SIZE, &greenSize);
  1524.             glXGetConfig(dpy, vinfo, GLX_BLUE_SIZE, &blueSize);
  1525.             glXGetConfig(dpy, vinfo, GLX_ALPHA_SIZE, &alphaSize);
  1526.             glXGetConfig(dpy, vinfo, GLX_DEPTH_SIZE, &depthSize);
  1527.             glXGetConfig(dpy, vinfo, GLX_STENCIL_SIZE, &stencilSize);
  1528.             glXGetConfig(dpy, vinfo, GLX_ACCUM_RED_SIZE, &acRedSize);
  1529.             glXGetConfig(dpy, vinfo, GLX_ACCUM_GREEN_SIZE, &acGreenSize);
  1530.             glXGetConfig(dpy, vinfo, GLX_ACCUM_BLUE_SIZE, &acBlueSize);
  1531.             glXGetConfig(dpy, vinfo, GLX_ACCUM_ALPHA_SIZE, &acAlphaSize);
  1532.             printf("RGBA = (%d, %d, %d, %d)n", redSize, greenSize, blueSize, alphaSize);
  1533.             printf("acc  = (%d, %d, %d, %d)n", acRedSize, acGreenSize, acBlueSize, acAlphaSize);
  1534.             printf("db   = %dn", doubleBuffer);
  1535.             printf("str  = %dn", stereo);
  1536.             printf("aux  = %dn", auxBuffers);
  1537.             printf("lvl  = %dn", level);
  1538.             printf("buf  = %dn", bufferSize);
  1539.             printf("rgba = %dn", renderType);
  1540.             printf("z    = %dn", depthSize);
  1541.             printf("s    = %dn", stencilSize);
  1542.           }
  1543.         } else {
  1544.           printf("n");
  1545.           printf("No match.n");
  1546.         }
  1547.         printf("n");
  1548.       }
  1549.     }
  1550.   }
  1551.   printf("n");
  1552.   return 0;
  1553. }
  1554. #endif