home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / OpenGL 1.0 SDK / Source / Libraries / glut / glut_dstr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  12.6 KB  |  672 lines  |  [TEXT/CWIE]

  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 "glut.h"
  13. #include "glutint.h"
  14.  
  15. char *__glutDisplayString = NULL;
  16.  
  17. static AGLPixelFormat findMatch(Criterion *criteria, int ncriteria)
  18. {
  19.     AGLPixelFormat format;
  20.     GLint i, attrib[50], nattrib;
  21.     
  22.     nattrib = 0;
  23.     for(i = 0; i < ncriteria; i++)
  24.     {
  25.         switch(criteria[i].capability)
  26.         {
  27.             case BUFFER_SIZE:
  28.                 attrib[nattrib++] = AGL_BUFFER_SIZE;
  29.                 attrib[nattrib++] = criteria[i].value;
  30.             break;
  31.             case RGBA:
  32.                 attrib[nattrib++] = AGL_RGBA;
  33.             break;
  34.             case DOUBLEBUFFER:
  35.                 attrib[nattrib++] = AGL_DOUBLEBUFFER;
  36.             break;
  37.             case STEREO:
  38.                 attrib[nattrib++] = AGL_STEREO;
  39.             break;
  40.             case AUX_BUFFERS:
  41.                 attrib[nattrib++] = AGL_AUX_BUFFERS;
  42.                 attrib[nattrib++] = criteria[i].value;
  43.             break;
  44.             case RED_SIZE:
  45.                 attrib[nattrib++] = AGL_RED_SIZE;
  46.                 attrib[nattrib++] = criteria[i].value;
  47.             break;
  48.             case GREEN_SIZE:
  49.                 attrib[nattrib++] = AGL_GREEN_SIZE;
  50.                 attrib[nattrib++] = criteria[i].value;
  51.             break;
  52.             case BLUE_SIZE:
  53.                 attrib[nattrib++] = AGL_BLUE_SIZE;
  54.                 attrib[nattrib++] = criteria[i].value;
  55.             break;
  56.             case ALPHA_SIZE:
  57.                 attrib[nattrib++] = AGL_ALPHA_SIZE;
  58.                 attrib[nattrib++] = criteria[i].value;
  59.             break;
  60.             case DEPTH_SIZE:
  61.                 attrib[nattrib++] = AGL_DEPTH_SIZE;
  62.                 attrib[nattrib++] = criteria[i].value;
  63.             break;
  64.             case STENCIL_SIZE:
  65.                 attrib[nattrib++] = AGL_STENCIL_SIZE;
  66.                 attrib[nattrib++] = criteria[i].value;
  67.             break;
  68.             case ACCUM_RED_SIZE:
  69.                 attrib[nattrib++] = AGL_ACCUM_RED_SIZE;
  70.                 attrib[nattrib++] = criteria[i].value;
  71.             break;
  72.             case ACCUM_GREEN_SIZE:
  73.                 attrib[nattrib++] = AGL_ACCUM_GREEN_SIZE;
  74.                 attrib[nattrib++] = criteria[i].value;
  75.             break;
  76.             case ACCUM_BLUE_SIZE:
  77.                 attrib[nattrib++] = AGL_ACCUM_BLUE_SIZE;
  78.                 attrib[nattrib++] = criteria[i].value;
  79.             break;
  80.             case ACCUM_ALPHA_SIZE:
  81.                 attrib[nattrib++] = AGL_ACCUM_ALPHA_SIZE;
  82.                 attrib[nattrib++] = criteria[i].value;
  83.             break;
  84.             case LEVEL:
  85.                 attrib[nattrib++] = AGL_BUFFER_SIZE;
  86.                 attrib[nattrib++] = criteria[i].value;
  87.             break;
  88.             case CONFORMANT:
  89.             break;
  90.             case SAMPLES:
  91.             break;
  92.             case SLOW:
  93.             break;
  94.         }
  95.     }
  96.     
  97.     //attrib[nattrib++] = AGL_FAILURE_REVERT;
  98.     attrib[nattrib++] = AGL_NONE;
  99.     
  100.     format = aglChoosePixelFormat(NULL, 0, attrib);
  101.     
  102.     return format;
  103. }
  104.  
  105.  
  106. static int parseCriteria(char *word, Criterion * criterion, int *mask)
  107. {
  108.     char *cstr, *vstr, *response;
  109.     int comparator, value;
  110.     int rgb, rgba, acc, acca, count, i;
  111.  
  112.     cstr = strpbrk(word, "=><!~");
  113.     if (cstr)
  114.     {
  115.         switch (cstr[0])
  116.         {
  117.             case '=':
  118.                 comparator = EQ;
  119.                 vstr = &cstr[1];
  120.             break;
  121.             case '~':
  122.                 comparator = MIN;
  123.                 vstr = &cstr[1];
  124.             break;
  125.             case '>':
  126.                 if(cstr[1] == '=')
  127.                 {
  128.                     comparator = GTE;
  129.                     vstr = &cstr[2];
  130.                 }
  131.                 else
  132.                 {
  133.                     comparator = GT;
  134.                     vstr = &cstr[1];
  135.                 }
  136.             break;
  137.             case '<':
  138.                 if(cstr[1] == '=')
  139.                 {
  140.                     comparator = LTE;
  141.                     vstr = &cstr[2];
  142.                 }
  143.                 else
  144.                 {
  145.                     comparator = LT;
  146.                     vstr = &cstr[1];
  147.                 }
  148.             break;
  149.             case '!':
  150.                 if(cstr[1] == '=')
  151.                 {
  152.                     comparator = NEQ;
  153.                     vstr = &cstr[2];
  154.                 }
  155.                 else
  156.                 {
  157.                     return -1;
  158.                 }
  159.             break;
  160.             default:
  161.                 return -1;
  162.         }
  163.         
  164.         value = (int) strtol(vstr, &response, 0);
  165.         
  166.         if(response == vstr)
  167.         {
  168.             /* Not a valid number. */
  169.             return -1;
  170.         }
  171.         
  172.         *cstr = '\0';
  173.         
  174.     }
  175.     else
  176.     {
  177.         comparator = NONE;
  178.     }
  179.     
  180.     switch(word[0])
  181.     {
  182.         case 'a':
  183.             if(!strcmp(word, "alpha"))
  184.             {
  185.                 criterion[0].capability = ALPHA_SIZE;
  186.                 
  187.                 if(comparator == NONE)
  188.                 {
  189.                     criterion[0].comparison = GTE;
  190.                     criterion[0].value = 1;
  191.                 }
  192.                 else
  193.                 {
  194.                     criterion[0].comparison = comparator;
  195.                     criterion[0].value = value;
  196.                 }
  197.                 
  198.                 *mask |= (1 << RGBA);
  199.                 *mask |= (1 << ALPHA_SIZE);
  200.                 *mask |= (1 << RGBA_MODE);
  201.                 
  202.                 return 1;
  203.             }
  204.             
  205.             acca = !strcmp(word, "acca");
  206.             acc = !strcmp(word, "acc");
  207.             
  208.             if(acc || acca)
  209.             {
  210.                 criterion[0].capability = ACCUM_RED_SIZE;
  211.                 criterion[1].capability = ACCUM_GREEN_SIZE;
  212.                 criterion[2].capability = ACCUM_BLUE_SIZE;
  213.                 criterion[3].capability = ACCUM_ALPHA_SIZE;
  214.                 
  215.                 if(acca)
  216.                 {
  217.                     count = 4;
  218.                 }
  219.                 else
  220.                 {
  221.                     count = 3;
  222.                     criterion[3].comparison = MIN;
  223.                     criterion[3].value = 0;
  224.                 }
  225.                 
  226.                 if(comparator == NONE)
  227.                 {
  228.                     comparator = GTE;
  229.                     value = 8;
  230.                 }
  231.                 
  232.                 for(i = 0; i < count; i++)
  233.                 {
  234.                     criterion[i].comparison = comparator;
  235.                     criterion[i].value = value;
  236.                 }
  237.                 
  238.                 *mask |= (1 << ACCUM_RED_SIZE);
  239.                 
  240.                 return 4;
  241.             }
  242.         
  243.             if(!strcmp(word, "auxbufs"))
  244.             {
  245.                 criterion[0].capability = AUX_BUFFERS;
  246.                 
  247.                 if(comparator == NONE)
  248.                 {
  249.                     criterion[0].comparison = MIN;
  250.                     criterion[0].value = 1;
  251.                 }
  252.                 else
  253.                 {
  254.                     criterion[0].comparison = comparator;
  255.                     criterion[0].value = value;
  256.                 }
  257.                 
  258.                 *mask |= (1 << AUX_BUFFERS);
  259.                 
  260.                 return 1;
  261.             }
  262.                 
  263.             return -1;
  264.         case 'b':
  265.             if(!strcmp(word, "blue"))
  266.             {
  267.                 criterion[0].capability = BLUE_SIZE;
  268.                 
  269.                 if (comparator == NONE)
  270.                 {
  271.                     criterion[0].comparison = GTE;
  272.                     criterion[0].value = 1;
  273.                 }
  274.                 else
  275.                 {
  276.                     criterion[0].comparison = comparator;
  277.                     criterion[0].value = value;
  278.                 }
  279.             
  280.                 *mask |= (1 << RGBA);
  281.                 *mask |= (1 << RGBA_MODE);
  282.             
  283.                 return 1;
  284.             }
  285.             
  286.             if(!strcmp(word, "buffer"))
  287.             {
  288.                 criterion[0].capability = BUFFER_SIZE;
  289.                 
  290.                 if(comparator == NONE)
  291.                 {
  292.                     criterion[0].comparison = GTE;
  293.                     criterion[0].value = 1;
  294.                 }
  295.                 else
  296.                 {
  297.                     criterion[0].comparison = comparator;
  298.                     criterion[0].value = value;
  299.                 }
  300.             
  301.                 return 1;
  302.             }
  303.             
  304.             return -1;
  305.         case 'c':
  306.             if (!strcmp(word, "conformant"))
  307.             {
  308.             criterion[0].capability = CONFORMANT;
  309.             if (comparator == NONE)
  310.             {
  311.             criterion[0].comparison = EQ;
  312.             criterion[0].value = 1;
  313.             }
  314.             else
  315.             {
  316.             criterion[0].comparison = comparator;
  317.             criterion[0].value = value;
  318.             }
  319.             *mask |= (1 << CONFORMANT);
  320.             return 1;
  321.             }
  322.             return -1;
  323.         case 'd':
  324.             if (!strcmp(word, "depth"))
  325.             {
  326.             criterion[0].capability = DEPTH_SIZE;
  327.             if (comparator == NONE)
  328.             {
  329.             criterion[0].comparison = GTE;
  330.             criterion[0].value = 12;
  331.             }
  332.             else
  333.             {
  334.             criterion[0].comparison = comparator;
  335.             criterion[0].value = value;
  336.             }
  337.             *mask |= (1 << DEPTH_SIZE);
  338.             return 1;
  339.             }
  340.             if (!strcmp(word, "double"))
  341.             {
  342.             criterion[0].capability = DOUBLEBUFFER;
  343.             if (comparator == NONE) {
  344.             criterion[0].comparison = EQ;
  345.             criterion[0].value = 1;
  346.             }
  347.             else
  348.             {
  349.             criterion[0].comparison = comparator;
  350.             criterion[0].value = value;
  351.             }
  352.             *mask |= (1 << DOUBLEBUFFER);
  353.             return 1;
  354.             }
  355.             return -1;
  356.         case 'f':
  357.             if (!strcmp(word, "fullscreen"))
  358.             {
  359.             criterion[0].capability = FULLSCREEN;
  360.             if (comparator == NONE)
  361.             {
  362.             criterion[0].comparison = GTE;
  363.             criterion[0].value = 12;
  364.             }
  365.             else
  366.             {
  367.             criterion[0].comparison = comparator;
  368.             criterion[0].value = value;
  369.             }
  370.             *mask |= (1 << FULLSCREEN);
  371.             return 1;
  372.             }
  373.             return -1;
  374.         case 'g':
  375.             if (!strcmp(word, "green"))
  376.             {
  377.             criterion[0].capability = GREEN_SIZE;
  378.             if (comparator == NONE)
  379.             {
  380.             criterion[0].comparison = GTE;
  381.             criterion[0].value = 1;
  382.             }
  383.             else
  384.             {
  385.             criterion[0].comparison = comparator;
  386.             criterion[0].value = value;
  387.             }
  388.             *mask |= (1 << RGBA);
  389.             *mask |= (1 << RGBA_MODE);
  390.             return 1;
  391.             }
  392.             return -1;
  393.         case 'i':
  394.             if (!strcmp(word, "index"))
  395.             {
  396.             criterion[0].capability = RGBA;
  397.             criterion[0].comparison = EQ;
  398.             criterion[0].value = 0;
  399.             *mask |= (1 << RGBA);
  400.             *mask |= (1 << CI_MODE);
  401.             if (comparator == NONE)
  402.             {
  403.             criterion[1].capability = BUFFER_SIZE;
  404.             criterion[1].comparison = GTE;
  405.             criterion[1].value = 1;
  406.             }
  407.             else
  408.             {
  409.             criterion[1].capability = BUFFER_SIZE;
  410.             criterion[1].comparison = comparator;
  411.             criterion[1].value = value;
  412.             }
  413.             return 2;
  414.             }
  415.             return -1;
  416.             case 'n':
  417.             if (!strcmp(word, "num"))
  418.             {
  419.             criterion[0].capability = NUM;
  420.             if (comparator == NONE)
  421.             {
  422.             return -1;
  423.             }
  424.             else
  425.             {
  426.             criterion[0].comparison = comparator;
  427.             criterion[0].value = value;
  428.             return 1;
  429.             }
  430.             }
  431.             return -1;
  432.         case 'r':
  433.             if (!strcmp(word, "red"))
  434.             {
  435.             criterion[0].capability = RED_SIZE;
  436.             if (comparator == NONE)
  437.             {
  438.             criterion[0].comparison = GTE;
  439.             criterion[0].value = 1;
  440.             }
  441.             else
  442.             {
  443.             criterion[0].comparison = comparator;
  444.             criterion[0].value = value;
  445.             }
  446.             *mask |= (1 << RGBA);
  447.             *mask |= (1 << RGBA_MODE);
  448.             return 1;
  449.             }
  450.             rgba = !strcmp(word, "rgba");
  451.             rgb = !strcmp(word, "rgb");
  452.             if (rgb || rgba)
  453.             {
  454.             criterion[0].capability = RGBA;
  455.             criterion[0].comparison = EQ;
  456.             criterion[0].value = 1;
  457.  
  458.             criterion[1].capability = RED_SIZE;
  459.             criterion[2].capability = GREEN_SIZE;
  460.             criterion[3].capability = BLUE_SIZE;
  461.             criterion[4].capability = ALPHA_SIZE;
  462.             if (rgba)
  463.             {
  464.             count = 5;
  465.             }
  466.             else
  467.             {
  468.             count = 4;
  469.             criterion[4].comparison = MIN;
  470.             criterion[4].value = 0;
  471.             }
  472.             if (comparator == NONE)
  473.             {
  474.             comparator = GTE;
  475.             value = 1;
  476.             }
  477.             for (i = 1; i < count; i++)
  478.             {
  479.             criterion[i].comparison = comparator;
  480.             criterion[i].value = value;
  481.             }
  482.             *mask |= (1 << RGBA);
  483.             *mask |= (1 << RGBA_MODE);
  484.             return 5;
  485.             }
  486.             return -1;
  487.         case 's':
  488.             if (!strcmp(word, "stencil"))
  489.             {
  490.             criterion[0].capability = STENCIL_SIZE;
  491.             if (comparator == NONE) {
  492.             criterion[0].comparison = MIN;
  493.             criterion[0].value = 1;
  494.             }
  495.             else
  496.             {
  497.             criterion[0].comparison = comparator;
  498.             criterion[0].value = value;
  499.             }
  500.             *mask |= (1 << STENCIL_SIZE);
  501.             return 1;
  502.             }
  503.             if (!strcmp(word, "single"))
  504.             {
  505.             criterion[0].capability = DOUBLEBUFFER;
  506.             if (comparator == NONE) {
  507.             criterion[0].comparison = EQ;
  508.             criterion[0].value = 0;
  509.             *mask |= (1 << DOUBLEBUFFER);
  510.             return 1;
  511.             }
  512.             else
  513.             {
  514.             return -1;
  515.             }
  516.             }
  517.             if (!strcmp(word, "stereo"))
  518.             {
  519.             criterion[0].capability = STEREO;
  520.             if (comparator == NONE)
  521.             {
  522.             criterion[0].comparison = EQ;
  523.             criterion[0].value = 1;
  524.             }
  525.             else
  526.             {
  527.             criterion[0].comparison = comparator;
  528.             criterion[0].value = value;
  529.             }
  530.             *mask |= (1 << STEREO);
  531.             return 1;
  532.             }
  533.             if (!strcmp(word, "samples"))
  534.             {
  535.             criterion[0].capability = SAMPLES;
  536.             if (comparator == NONE) {
  537.             criterion[0].comparison = LTE;
  538.             criterion[0].value = 4;
  539.             }
  540.             else
  541.             {
  542.             criterion[0].comparison = comparator;
  543.             criterion[0].value = value;
  544.             }
  545.             *mask |= (1 << SAMPLES);
  546.             return 1;
  547.             }
  548.             if (!strcmp(word, "slow"))
  549.             {
  550.             criterion[0].capability = SLOW;
  551.             if (comparator == NONE) {
  552.             /* Just "slow" means permit fast visuals, but accept
  553.             slow ones in preference. Presumably the slow ones
  554.             must be higher quality or something else desirable. */
  555.             criterion[0].comparison = GTE;
  556.             criterion[0].value = 0;
  557.             } else {
  558.             criterion[0].comparison = comparator;
  559.             criterion[0].value = value;
  560.             }
  561.             *mask |= (1 << SLOW);
  562.             return 1;
  563.             }
  564.             return -1;
  565.         default:
  566.             return -1;
  567.     }
  568. }
  569.  
  570. static Criterion *parseModeString(char *mode, int *ncriteria)
  571. {
  572.     Criterion *criteria = NULL;
  573.     int n, mask, parsed;
  574.     char *copy, *word;
  575.  
  576.     copy = __glutStrdup(mode);
  577.     
  578.     /* Attempt to estimate how many criteria entries should be needed. */
  579.     n = 0;
  580.     word = strtok(copy, " \t");
  581.     while(word)
  582.     {
  583.         n++;
  584.         word = strtok(NULL, " \t");
  585.     }
  586.     
  587.     /* Overestimate by 4 times ("rgba" might add four criteria
  588.     entries) plus add in possible defaults plus space for
  589.     required criteria. */
  590.     criteria = (Criterion *) malloc((4 * n + 30) * sizeof(Criterion));
  591.     if (!criteria) __glutFatalError("out of memory.");
  592.  
  593.     /* Re-copy the copy of the mode string. */
  594.     strcpy(copy, mode);
  595.  
  596.     mask = 0;
  597.     n = 0;
  598.  
  599.     word = strtok(copy, " \t");
  600.     while(word)
  601.     {
  602.         parsed = parseCriteria(word, &criteria[n], &mask);
  603.         
  604.         if(parsed >= 0)
  605.         {
  606.             n += parsed;
  607.         }
  608.         else 
  609.         {
  610.             __glutWarning("Unrecognized display string word: %s (ignoring)\n", word);
  611.         }
  612.         
  613.         word = strtok(NULL, " \t");
  614.     }
  615.  
  616.     if(n)
  617.     {
  618.         criteria = (Criterion *) realloc(criteria, n * sizeof(Criterion));
  619.         
  620.         if(!criteria) __glutFatalError("out of memory.");
  621.     }
  622.     else
  623.     {
  624.         free(criteria);
  625.         criteria = NULL;
  626.     }
  627.  
  628.     free(copy);
  629.     *ncriteria = n;
  630.     
  631.     return criteria;
  632. }
  633.  
  634. AGLPixelFormat __glutVisualInfoFromString(char *string)
  635. {
  636.     Criterion *criteria;
  637.     AGLPixelFormat visinfo;
  638.     int ncriteria;
  639.  
  640.     criteria = parseModeString(string, &ncriteria);
  641.     if(criteria == NULL)
  642.     {
  643.         __glutWarning("failed to parse mode string");
  644.         return NULL;
  645.     }
  646.     
  647.     visinfo = findMatch(criteria, ncriteria);
  648.     
  649.     free(criteria);
  650.  
  651.     return visinfo;
  652. }
  653.  
  654. void glutInitDisplayString(const char *string)
  655. {
  656.     if(__glutDisplayString)
  657.     {
  658.         free(__glutDisplayString);
  659.     }
  660.     
  661.     if(string)
  662.     {
  663.         __glutDisplayString = __glutStrdup(string);
  664.         
  665.         if(!__glutDisplayString) __glutFatalError("out of memory.");
  666.     }
  667.     else
  668.     {
  669.         __glutDisplayString = NULL;
  670.     }
  671. }
  672.