~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/glut/glx/glut_dstr.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

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