home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src-glut / glut_dstr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  36.3 KB  |  1,359 lines

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