source: trunk/src/opengl/glut/glut_dstr.c

Last change on this file was 2689, checked in by jeroen, 26 years ago

* empty log message *

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