2 /* Copyright (c) Mark J. Kilgard, 1997. */
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. */
14 /* glxcaps matches the criteria macros listed in glutint.h, but
15 only list the first set (those that correspond to GLX visual
17 static int glxcap
[NUM_GLXCAPS
] =
40 char *__glutProgramName
= "dstr";
41 Display
*__glutDisplay
;
43 XVisualInfo
*(*__glutDetermineVisualFromString
) (char *string
, Bool
* treatAsSingle
,
44 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
, void **fbc
) = NULL
;
45 char *__glutDisplayString
= NULL
;
47 static int verbose
= 0;
49 static char *compstr
[] =
51 "none", "=", "!=", "<=", ">=", ">", "<", "~"
53 static char *capstr
[] =
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"
62 printCriteria(Criterion
* criteria
, int ncriteria
)
65 printf("Criteria: %d\n", ncriteria
);
66 for (i
= 0; i
< ncriteria
; i
++) {
68 capstr
[criteria
[i
].capability
],
69 compstr
[criteria
[i
].comparison
],
76 static int isMesaGLX
= -1;
79 determineMesaGLX(void)
81 #ifdef GLX_VERSION_1_1
82 const char *vendor
, *version
, *ch
;
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
++);
90 #define MESA_NAME "Mesa " /* Trailing space is intentional. */
92 if (!strncmp(MESA_NAME
, ch
, sizeof(MESA_NAME
) - 1)) {
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
106 static XVisualInfo
**
107 getMesaVisualList(int *n
)
109 XVisualInfo
**vlist
, *vinfo
;
113 vlist
= (XVisualInfo
**) malloc((32 + 16) * sizeof(XVisualInfo
*));
115 __glutFatalError("out of memory.");
118 for (i
= 0; i
< 32; i
++) {
120 attribs
[x
] = GLX_RGBA
;
122 attribs
[x
] = GLX_RED_SIZE
;
126 attribs
[x
] = GLX_GREEN_SIZE
;
130 attribs
[x
] = GLX_BLUE_SIZE
;
135 attribs
[x
] = GLX_DEPTH_SIZE
;
141 attribs
[x
] = GLX_STENCIL_SIZE
;
147 attribs
[x
] = GLX_ACCUM_RED_SIZE
;
151 attribs
[x
] = GLX_ACCUM_GREEN_SIZE
;
155 attribs
[x
] = GLX_ACCUM_BLUE_SIZE
;
161 attribs
[x
] = GLX_ALPHA_SIZE
;
166 attribs
[x
] = GLX_ACCUM_ALPHA_SIZE
;
173 attribs
[x
] = GLX_DOUBLEBUFFER
;
178 assert(x
<= sizeof(attribs
) / sizeof(attribs
[0]));
179 vinfo
= glXChooseVisual(__glutDisplay
, __glutScreen
, attribs
);
185 for (i
= 0; i
< 16; i
++) {
188 attribs
[x
] = GLX_DEPTH_SIZE
;
194 attribs
[x
] = GLX_STENCIL_SIZE
;
200 attribs
[x
] = GLX_DOUBLEBUFFER
;
204 attribs
[x
] = GLX_LEVEL
;
208 #if defined(GLX_TRANSPARENT_TYPE_EXT) && defined(GLX_TRANSPARENT_INDEX_EXT)
209 attribs
[x
] = GLX_TRANSPARENT_TYPE_EXT
;
211 attribs
[x
] = GLX_TRANSPARENT_INDEX_EXT
;
217 assert(x
<= sizeof(attribs
) / sizeof(attribs
[0]));
218 vinfo
= glXChooseVisual(__glutDisplay
, __glutScreen
, attribs
);
229 static FrameBufferMode
*
230 loadVisuals(int *nitems_return
)
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)
238 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
241 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
244 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
248 isMesaGLX
= determineMesaGLX();
250 vlist
= getMesaVisualList(&n
);
253 template.screen
= __glutScreen
;
254 vinfo
= XGetVisualInfo(__glutDisplay
, VisualScreenMask
, &template, &n
);
256 vinfo
= XGetVisualInfo(__glutDisplay
, 0, &template, &n
);
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
*));
272 __glutFatalError("out of memory.");
273 for (i
= 0; i
< n
; i
++) {
274 vlist
[i
] = &vinfo
[i
];
278 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
279 multisample
= __glutIsSupportedByGLX("GLX_SGIS_multisample");
281 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
282 visual_info
= __glutIsSupportedByGLX("GLX_EXT_visual_info");
284 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
285 visual_rating
= __glutIsSupportedByGLX("GLX_EXT_visual_rating");
287 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
288 fbconfig
= __glutIsSupportedByGLX("GLX_SGIX_fbconfig");
291 fbmodes
= (FrameBufferMode
*) malloc(n
* sizeof(FrameBufferMode
));
292 if (fbmodes
== NULL
) {
296 for (i
= 0; i
< n
; i
++) {
299 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
302 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], GLX_USE_GL
, &glcapable
);
303 if (rc
== 0 && glcapable
) {
304 mode
->valid
= 1; /* Assume the best until proven
306 for (j
= 0; j
< NUM_GLXCAPS
; j
++) {
307 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], glxcap
[j
], &mode
->cap
[j
]);
313 mode
->cap
[XVISUAL
] = ChoosePixelFormat(XHDC
, vlist
[i
]);
315 mode
->cap
[XVISUAL
] = (int) vlist
[i
]->visualid
;
317 mode
->cap
[XSTATICGRAY
] = 0;
318 mode
->cap
[XGRAYSCALE
] = 0;
319 mode
->cap
[XSTATICCOLOR
] = 0;
320 mode
->cap
[XPSEUDOCOLOR
] = 0;
321 mode
->cap
[XTRUECOLOR
] = 0;
322 mode
->cap
[XDIRECTCOLOR
] = 0;
324 #if defined(__cplusplus) || defined(c_plusplus)
325 switch (vlist
[i
]->c_class
) {
327 switch (vlist
[i
]->class) {
330 mode
->cap
[XSTATICGRAY
] = 1;
333 mode
->cap
[XGRAYSCALE
] = 1;
336 mode
->cap
[XSTATICCOLOR
] = 1;
339 mode
->cap
[XPSEUDOCOLOR
] = 1;
342 mode
->cap
[XTRUECOLOR
] = 1;
345 mode
->cap
[XDIRECTCOLOR
] = 1;
349 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
353 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
354 564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
355 in <GL/glx.h> despite claiming to support
356 GLX_EXT_visual_rating. */
357 #ifndef GLX_VISUAL_CAVEAT_EXT
358 #define GLX_VISUAL_CAVEAT_EXT 0x20
361 rc
= glXGetConfig(__glutDisplay
,
362 vlist
[i
], GLX_VISUAL_CAVEAT_EXT
, &rating
);
365 mode
->cap
[CONFORMANT
] = 1;
368 case GLX_SLOW_VISUAL_EXT
:
370 mode
->cap
[CONFORMANT
] = 1;
373 /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
374 properly defined in /usr/include/GL/glxtokens.h */
375 #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
376 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
379 case GLX_NON_CONFORMANT_VISUAL_EXT
:
381 mode
->cap
[CONFORMANT
] = 0;
384 default: /* XXX Hopefully this is a good default
387 mode
->cap
[CONFORMANT
] = 1;
392 mode
->cap
[TRANSPARENT
] = 0;
396 mode
->cap
[CONFORMANT
] = 1;
398 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
402 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
403 564 for Alpha did not properly define
404 GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
405 support GLX_EXT_visual_info. */
406 #ifndef GLX_TRANSPARENT_TYPE_EXT
407 #define GLX_TRANSPARENT_TYPE_EXT 0x23
410 rc
= glXGetConfig(__glutDisplay
,
411 vlist
[i
], GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
413 mode
->cap
[TRANSPARENT
] = 0;
415 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
418 mode
->cap
[TRANSPARENT
] = 0;
421 mode
->cap
[TRANSPARENT
] = 0;
423 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
425 rc
= glXGetConfig(__glutDisplay
,
426 vlist
[i
], GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
428 mode
->cap
[SAMPLES
] = 0;
431 mode
->cap
[SAMPLES
] = 0;
434 mode
->cap
[SAMPLES
] = 0;
437 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
440 int fbconfigID
, drawType
, renderType
;
442 fbc
= __glut_glXGetFBConfigFromVisualSGIX(__glutDisplay
, vlist
[i
]);
444 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
445 GLX_FBCONFIG_ID_SGIX
, &fbconfigID
);
446 if ((rc
== 0) && (fbconfigID
!= None
)) {
447 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
448 GLX_DRAWABLE_TYPE_SGIX
, &drawType
);
449 if ((rc
== 0) && (drawType
& GLX_WINDOW_BIT_SGIX
)) {
450 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
451 GLX_RENDER_TYPE_SGIX
, &renderType
);
452 if ((rc
== 0) && (renderType
& GLX_RGBA_BIT_SGIX
)) {
454 mode
->valid
= 1; /* Assume the best until
457 assert(glxcap
[0] == GLX_RGBA
);
460 /* Start with "j = 1" to skip the GLX_RGBA attribute. */
461 for (j
= 1; j
< NUM_GLXCAPS
; j
++) {
462 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
463 fbc
, glxcap
[j
], &mode
->cap
[j
]);
469 mode
->cap
[XVISUAL
] = (int) vlist
[i
]->visualid
;
470 mode
->cap
[XSTATICGRAY
] = 0;
471 mode
->cap
[XGRAYSCALE
] = 0;
472 mode
->cap
[XSTATICCOLOR
] = 0;
473 mode
->cap
[XPSEUDOCOLOR
] = 0;
474 mode
->cap
[XTRUECOLOR
] = 0;
475 mode
->cap
[XDIRECTCOLOR
] = 0;
476 #if defined(__cplusplus) || defined(c_plusplus)
477 switch (vlist
[i
]->c_class
) {
479 switch (vlist
[i
]->class) {
482 mode
->cap
[XSTATICGRAY
] = 1;
485 mode
->cap
[XGRAYSCALE
] = 1;
488 mode
->cap
[XSTATICCOLOR
] = 1;
491 mode
->cap
[XPSEUDOCOLOR
] = 1;
494 mode
->cap
[XTRUECOLOR
] = 1;
497 mode
->cap
[XDIRECTCOLOR
] = 1;
500 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
504 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
505 564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
506 in <GL/glx.h> despite claiming to support
507 GLX_EXT_visual_rating. */
508 #ifndef GLX_VISUAL_CAVEAT_EXT
509 #define GLX_VISUAL_CAVEAT_EXT 0x20
512 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
513 fbc
, GLX_VISUAL_CAVEAT_EXT
, &rating
);
516 mode
->cap
[CONFORMANT
] = 1;
519 case GLX_SLOW_VISUAL_EXT
:
521 mode
->cap
[CONFORMANT
] = 1;
524 /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
525 properly defined in /usr/include/GL/glxtokens.h */
526 #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
527 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
530 case GLX_NON_CONFORMANT_VISUAL_EXT
:
532 mode
->cap
[CONFORMANT
] = 0;
535 default: /* XXX Hopefully this is a good
536 default assumption. */
538 mode
->cap
[CONFORMANT
] = 1;
543 mode
->cap
[TRANSPARENT
] = 0;
547 mode
->cap
[CONFORMANT
] = 1;
549 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
553 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
554 564 for Alpha did not properly define
555 GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
556 support GLX_EXT_visual_info. */
557 #ifndef GLX_TRANSPARENT_TYPE_EXT
558 #define GLX_TRANSPARENT_TYPE_EXT 0x23
561 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
562 fbc
, GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
564 mode
->cap
[TRANSPARENT
] = 0;
566 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
569 mode
->cap
[TRANSPARENT
] = 0;
572 mode
->cap
[TRANSPARENT
] = 0;
574 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
576 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
577 fbc
, GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
579 mode
->cap
[SAMPLES
] = 0;
582 mode
->cap
[SAMPLES
] = 0;
585 mode
->cap
[SAMPLES
] = 0;
589 /* Fbconfig is not RGBA; GLUT only uses RGBA
591 /* XXX Code could be exteneded to handle color
592 index FBconfigs, but seems a color index
593 window-renderable FBconfig would also be
594 advertised as an X visual. */
598 /* Fbconfig does not support window rendering;
599 not a valid FBconfig for GLUT windows. */
603 /* FBconfig ID is None (zero); not a valid
608 /* FBconfig ID is None (zero); not a valid FBconfig. */
612 /* No SGIX_fbconfig GLX sever implementation support. */
616 /* No SGIX_fbconfig GLX extension API support. */
628 findMatch(FrameBufferMode
* fbmodes
, int nfbmodes
,
629 Criterion
* criteria
, int ncriteria
, void **fbc
)
631 FrameBufferMode
*found
;
632 int *bestScore
, *thisScore
;
633 int i
, j
, numok
, result
= 0, worse
, better
;
636 numok
= 1; /* "num" capability is indexed from 1,
639 /* XXX alloca canidate. */
640 bestScore
= (int *) malloc(ncriteria
* sizeof(int));
642 __glutFatalError("out of memory.");
643 for (j
= 0; j
< ncriteria
; j
++) {
644 /* Very negative number. */
645 bestScore
[j
] = -32768;
648 /* XXX alloca canidate. */
649 thisScore
= (int *) malloc(ncriteria
* sizeof(int));
651 __glutFatalError("out of memory.");
653 for (i
= 0; i
< nfbmodes
; i
++) {
654 if (fbmodes
[i
].valid
) {
658 printf("Visual 0x%x\n", fbmodes
[i
].vi
->visualid
);
665 for (j
= 0; j
< ncriteria
; j
++) {
666 int cap
, cvalue
, fbvalue
;
668 cap
= criteria
[j
].capability
;
669 cvalue
= criteria
[j
].value
;
673 fbvalue
= fbmodes
[i
].cap
[cap
];
677 printf(" %s %s %d to %d\n",
678 capstr
[cap
], compstr
[criteria
[j
].comparison
], cvalue
, fbvalue
);
680 switch (criteria
[j
].comparison
) {
682 result
= cvalue
== fbvalue
;
686 result
= cvalue
!= fbvalue
;
690 result
= fbvalue
< cvalue
;
691 thisScore
[j
] = fbvalue
- cvalue
;
694 result
= fbvalue
> cvalue
;
695 thisScore
[j
] = fbvalue
- cvalue
;
698 result
= fbvalue
<= cvalue
;
699 thisScore
[j
] = fbvalue
- cvalue
;
702 result
= (fbvalue
>= cvalue
);
703 thisScore
[j
] = fbvalue
- cvalue
;
706 result
= fbvalue
>= cvalue
;
707 thisScore
[j
] = cvalue
- fbvalue
;
713 printf(" result=%d score=%d bestScore=%d\n", result
, thisScore
[j
], bestScore
[j
]);
717 if (better
|| thisScore
[j
] > bestScore
[j
]) {
719 } else if (thisScore
[j
] == bestScore
[j
]) {
734 if (better
&& !worse
) {
736 for (j
= 0; j
< ncriteria
; j
++) {
737 bestScore
[j
] = thisScore
[j
];
749 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
759 parseCriteria(char *word
, Criterion
* criterion
, int *mask
,
760 Bool
* allowDoubleAsSingle
)
762 char *cstr
, *vstr
, *response
;
763 int comparator
, value
= 0;
764 int rgb
, rgba
, acc
, acca
, count
, i
;
766 cstr
= strpbrk(word
, "=><!~");
778 if (cstr
[1] == '=') {
787 if (cstr
[1] == '=') {
796 if (cstr
[1] == '=') {
806 value
= (int) strtol(vstr
, &response
, 0);
807 if (response
== vstr
) {
808 /* Not a valid number. */
817 if (!strcmp(word
, "alpha")) {
818 criterion
[0].capability
= ALPHA_SIZE
;
819 if (comparator
== NONE
) {
820 criterion
[0].comparison
= GTE
;
821 criterion
[0].value
= 1;
823 criterion
[0].comparison
= comparator
;
824 criterion
[0].value
= value
;
826 *mask
|= (1 << RGBA
);
827 *mask
|= (1 << ALPHA_SIZE
);
828 *mask
|= (1 << RGBA_MODE
);
831 acca
= !strcmp(word
, "acca");
832 acc
= !strcmp(word
, "acc");
834 criterion
[0].capability
= ACCUM_RED_SIZE
;
835 criterion
[1].capability
= ACCUM_GREEN_SIZE
;
836 criterion
[2].capability
= ACCUM_BLUE_SIZE
;
837 criterion
[3].capability
= ACCUM_ALPHA_SIZE
;
842 criterion
[3].comparison
= MIN
;
843 criterion
[3].value
= 0;
845 if (comparator
== NONE
) {
849 for (i
= 0; i
< count
; i
++) {
850 criterion
[i
].comparison
= comparator
;
851 criterion
[i
].value
= value
;
853 *mask
|= (1 << ACCUM_RED_SIZE
);
856 if (!strcmp(word
, "auxbufs")) {
857 criterion
[0].capability
= AUX_BUFFERS
;
858 if (comparator
== NONE
) {
859 criterion
[0].comparison
= MIN
;
860 criterion
[0].value
= 1;
862 criterion
[0].comparison
= comparator
;
863 criterion
[0].value
= value
;
865 *mask
|= (1 << AUX_BUFFERS
);
870 if (!strcmp(word
, "blue")) {
871 criterion
[0].capability
= BLUE_SIZE
;
872 if (comparator
== NONE
) {
873 criterion
[0].comparison
= GTE
;
874 criterion
[0].value
= 1;
876 criterion
[0].comparison
= comparator
;
877 criterion
[0].value
= value
;
879 *mask
|= (1 << RGBA
);
880 *mask
|= (1 << RGBA_MODE
);
883 if (!strcmp(word
, "buffer")) {
884 criterion
[0].capability
= BUFFER_SIZE
;
885 if (comparator
== NONE
) {
886 criterion
[0].comparison
= GTE
;
887 criterion
[0].value
= 1;
889 criterion
[0].comparison
= comparator
;
890 criterion
[0].value
= value
;
896 if (!strcmp(word
, "conformant")) {
897 criterion
[0].capability
= CONFORMANT
;
898 if (comparator
== NONE
) {
899 criterion
[0].comparison
= EQ
;
900 criterion
[0].value
= 1;
902 criterion
[0].comparison
= comparator
;
903 criterion
[0].value
= value
;
905 *mask
|= (1 << CONFORMANT
);
910 if (!strcmp(word
, "depth")) {
911 criterion
[0].capability
= DEPTH_SIZE
;
912 if (comparator
== NONE
) {
913 criterion
[0].comparison
= GTE
;
914 criterion
[0].value
= 12;
916 criterion
[0].comparison
= comparator
;
917 criterion
[0].value
= value
;
919 *mask
|= (1 << DEPTH_SIZE
);
922 if (!strcmp(word
, "double")) {
923 criterion
[0].capability
= DOUBLEBUFFER
;
924 if (comparator
== NONE
) {
925 criterion
[0].comparison
= EQ
;
926 criterion
[0].value
= 1;
928 criterion
[0].comparison
= comparator
;
929 criterion
[0].value
= value
;
931 *mask
|= (1 << DOUBLEBUFFER
);
936 if (!strcmp(word
, "green")) {
937 criterion
[0].capability
= GREEN_SIZE
;
938 if (comparator
== NONE
) {
939 criterion
[0].comparison
= GTE
;
940 criterion
[0].value
= 1;
942 criterion
[0].comparison
= comparator
;
943 criterion
[0].value
= value
;
945 *mask
|= (1 << RGBA
);
946 *mask
|= (1 << RGBA_MODE
);
951 if (!strcmp(word
, "index")) {
952 criterion
[0].capability
= RGBA
;
953 criterion
[0].comparison
= EQ
;
954 criterion
[0].value
= 0;
955 *mask
|= (1 << RGBA
);
956 *mask
|= (1 << CI_MODE
);
957 criterion
[1].capability
= BUFFER_SIZE
;
958 if (comparator
== NONE
) {
959 criterion
[1].comparison
= GTE
;
960 criterion
[1].value
= 1;
962 criterion
[1].comparison
= comparator
;
963 criterion
[1].value
= value
;
969 if (!strcmp(word
, "luminance")) {
970 criterion
[0].capability
= RGBA
;
971 criterion
[0].comparison
= EQ
;
972 criterion
[0].value
= 1;
974 criterion
[1].capability
= RED_SIZE
;
975 if (comparator
== NONE
) {
976 criterion
[1].comparison
= GTE
;
977 criterion
[1].value
= 1;
979 criterion
[1].comparison
= comparator
;
980 criterion
[1].value
= value
;
983 criterion
[2].capability
= GREEN_SIZE
;
984 criterion
[2].comparison
= EQ
;
985 criterion
[2].value
= 0;
987 criterion
[3].capability
= BLUE_SIZE
;
988 criterion
[3].comparison
= EQ
;
989 criterion
[3].value
= 0;
991 *mask
|= (1 << RGBA
);
992 *mask
|= (1 << RGBA_MODE
);
993 *mask
|= (1 << LUMINANCE_MODE
);
998 if (!strcmp(word
, "num")) {
999 criterion
[0].capability
= NUM
;
1000 if (comparator
== NONE
) {
1003 criterion
[0].comparison
= comparator
;
1004 criterion
[0].value
= value
;
1010 if (!strcmp(word
, "red")) {
1011 criterion
[0].capability
= RED_SIZE
;
1012 if (comparator
== NONE
) {
1013 criterion
[0].comparison
= GTE
;
1014 criterion
[0].value
= 1;
1016 criterion
[0].comparison
= comparator
;
1017 criterion
[0].value
= value
;
1019 *mask
|= (1 << RGBA
);
1020 *mask
|= (1 << RGBA_MODE
);
1023 rgba
= !strcmp(word
, "rgba");
1024 rgb
= !strcmp(word
, "rgb");
1026 criterion
[0].capability
= RGBA
;
1027 criterion
[0].comparison
= EQ
;
1028 criterion
[0].value
= 1;
1030 criterion
[1].capability
= RED_SIZE
;
1031 criterion
[2].capability
= GREEN_SIZE
;
1032 criterion
[3].capability
= BLUE_SIZE
;
1033 criterion
[4].capability
= ALPHA_SIZE
;
1038 criterion
[4].comparison
= MIN
;
1039 criterion
[4].value
= 0;
1041 if (comparator
== NONE
) {
1045 for (i
= 1; i
< count
; i
++) {
1046 criterion
[i
].comparison
= comparator
;
1047 criterion
[i
].value
= value
;
1049 *mask
|= (1 << RGBA
);
1050 *mask
|= (1 << RGBA_MODE
);
1055 if (!strcmp(word
, "stencil")) {
1056 criterion
[0].capability
= STENCIL_SIZE
;
1057 if (comparator
== NONE
) {
1058 criterion
[0].comparison
= MIN
;
1059 criterion
[0].value
= 1;
1061 criterion
[0].comparison
= comparator
;
1062 criterion
[0].value
= value
;
1064 *mask
|= (1 << STENCIL_SIZE
);
1067 if (!strcmp(word
, "single")) {
1068 criterion
[0].capability
= DOUBLEBUFFER
;
1069 if (comparator
== NONE
) {
1070 criterion
[0].comparison
= EQ
;
1071 criterion
[0].value
= 0;
1072 *allowDoubleAsSingle
= True
;
1073 *mask
|= (1 << DOUBLEBUFFER
);
1079 if (!strcmp(word
, "stereo")) {
1080 criterion
[0].capability
= STEREO
;
1081 if (comparator
== NONE
) {
1082 criterion
[0].comparison
= EQ
;
1083 criterion
[0].value
= 1;
1085 criterion
[0].comparison
= comparator
;
1086 criterion
[0].value
= value
;
1088 *mask
|= (1 << STEREO
);
1091 if (!strcmp(word
, "samples")) {
1092 criterion
[0].capability
= SAMPLES
;
1093 if (comparator
== NONE
) {
1094 criterion
[0].comparison
= LTE
;
1095 criterion
[0].value
= 4;
1097 criterion
[0].comparison
= comparator
;
1098 criterion
[0].value
= value
;
1100 *mask
|= (1 << SAMPLES
);
1103 if (!strcmp(word
, "slow")) {
1104 criterion
[0].capability
= SLOW
;
1105 if (comparator
== NONE
) {
1106 /* Just "slow" means permit fast visuals, but accept
1107 slow ones in preference. Presumably the slow ones
1108 must be higher quality or something else desirable. */
1109 criterion
[0].comparison
= GTE
;
1110 criterion
[0].value
= 0;
1112 criterion
[0].comparison
= comparator
;
1113 criterion
[0].value
= value
;
1115 *mask
|= (1 << SLOW
);
1121 if (!strcmp(word
, "win32pfd")) {
1122 criterion
[0].capability
= XVISUAL
;
1123 if (comparator
== NONE
) {
1126 criterion
[0].comparison
= comparator
;
1127 criterion
[0].value
= value
;
1133 #if !defined(_WIN32)
1135 if (!strcmp(word
, "xvisual")) {
1136 if (comparator
== NONE
) {
1139 criterion
[0].capability
= XVISUAL
;
1140 criterion
[0].comparison
= comparator
;
1141 criterion
[0].value
= value
;
1142 /* Set everything in "mask" so that no default criteria
1143 get used. Assume the program really wants the
1144 xvisual specified. */
1149 /* Be a little over-eager to fill in the comparison and
1150 value so we won't have to replicate the code after each
1152 if (comparator
== NONE
) {
1153 criterion
[0].comparison
= EQ
;
1154 criterion
[0].value
= 1;
1156 criterion
[0].comparison
= comparator
;
1157 criterion
[0].value
= value
;
1160 if (!strcmp(word
, "xstaticgray")) {
1161 criterion
[0].capability
= XSTATICGRAY
;
1162 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1166 if (!strcmp(word
, "xgrayscale")) {
1167 criterion
[0].capability
= XGRAYSCALE
;
1168 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1172 if (!strcmp(word
, "xstaticcolor")) {
1173 criterion
[0].capability
= XSTATICCOLOR
;
1174 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1178 if (!strcmp(word
, "xpseudocolor")) {
1179 criterion
[0].capability
= XPSEUDOCOLOR
;
1180 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1184 if (!strcmp(word
, "xtruecolor")) {
1185 criterion
[0].capability
= XTRUECOLOR
;
1186 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1190 if (!strcmp(word
, "xdirectcolor")) {
1191 criterion
[0].capability
= XDIRECTCOLOR
;
1192 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1204 parseModeString(char *mode
, int *ncriteria
, Bool
* allowDoubleAsSingle
,
1205 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
)
1207 Criterion
*criteria
= NULL
;
1208 int n
, mask
, parsed
, i
;
1211 *allowDoubleAsSingle
= False
;
1212 copy
= __glutStrdup(mode
);
1213 /* Attempt to estimate how many criteria entries should be
1216 word
= strtok(copy
, " \t");
1219 word
= strtok(NULL
, " \t");
1221 /* Overestimate by 4 times ("rgba" might add four criteria
1222 entries) plus add in possible defaults plus space for
1223 required criteria. */
1224 criteria
= (Criterion
*) malloc((4 * n
+ 30 + nRequired
) * sizeof(Criterion
));
1226 __glutFatalError("out of memory.");
1229 /* Re-copy the copy of the mode string. */
1232 /* First add the required criteria (these match at the
1233 highest priority). Typically these will be used to force a
1234 specific level (layer), transparency, and/or visual type. */
1235 mask
= requiredMask
;
1236 for (i
= 0; i
< nRequired
; i
++) {
1237 criteria
[i
] = requiredCriteria
[i
];
1241 word
= strtok(copy
, " \t");
1243 parsed
= parseCriteria(word
, &criteria
[n
], &mask
, allowDoubleAsSingle
);
1247 __glutWarning("Unrecognized display string word: %s (ignoring)\n", word
);
1249 word
= strtok(NULL
, " \t");
1252 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
1253 if (__glutIsSupportedByGLX("GLX_SGIS_multisample")) {
1254 if (!(mask
& (1 << SAMPLES
))) {
1255 criteria
[n
].capability
= SAMPLES
;
1256 criteria
[n
].comparison
= EQ
;
1257 criteria
[n
].value
= 0;
1260 /* Multisample visuals are marked nonconformant. If
1261 multisampling was requeste and no conformant
1262 preference was set, assume that we will settle for a
1263 non-conformant visual to get multisampling. */
1264 if (!(mask
& (1 << CONFORMANT
))) {
1265 criteria
[n
].capability
= CONFORMANT
;
1266 criteria
[n
].comparison
= MIN
;
1267 criteria
[n
].value
= 0;
1269 mask
|= (1 << CONFORMANT
);
1274 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
1275 if (__glutIsSupportedByGLX("GLX_EXT_visual_info")) {
1276 if (!(mask
& (1 << TRANSPARENT
))) {
1277 criteria
[n
].capability
= TRANSPARENT
;
1278 criteria
[n
].comparison
= EQ
;
1279 criteria
[n
].value
= 0;
1284 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
1285 if (__glutIsSupportedByGLX("GLX_EXT_visual_rating")) {
1286 if (!(mask
& (1 << SLOW
))) {
1287 criteria
[n
].capability
= SLOW
;
1288 criteria
[n
].comparison
= EQ
;
1289 criteria
[n
].value
= 0;
1292 if (!(mask
& (1 << CONFORMANT
))) {
1293 criteria
[n
].capability
= CONFORMANT
;
1294 criteria
[n
].comparison
= EQ
;
1295 criteria
[n
].value
= 1;
1300 if (!(mask
& (1 << ACCUM_RED_SIZE
))) {
1301 criteria
[n
].capability
= ACCUM_RED_SIZE
;
1302 criteria
[n
].comparison
= MIN
;
1303 criteria
[n
].value
= 0;
1304 criteria
[n
+ 1].capability
= ACCUM_GREEN_SIZE
;
1305 criteria
[n
+ 1].comparison
= MIN
;
1306 criteria
[n
+ 1].value
= 0;
1307 criteria
[n
+ 2].capability
= ACCUM_BLUE_SIZE
;
1308 criteria
[n
+ 2].comparison
= MIN
;
1309 criteria
[n
+ 2].value
= 0;
1310 criteria
[n
+ 3].capability
= ACCUM_ALPHA_SIZE
;
1311 criteria
[n
+ 3].comparison
= MIN
;
1312 criteria
[n
+ 3].value
= 0;
1315 if (!(mask
& (1 << AUX_BUFFERS
))) {
1316 criteria
[n
].capability
= AUX_BUFFERS
;
1317 criteria
[n
].comparison
= MIN
;
1318 criteria
[n
].value
= 0;
1321 if (!(mask
& (1 << RGBA
))) {
1322 criteria
[n
].capability
= RGBA
;
1323 criteria
[n
].comparison
= EQ
;
1324 criteria
[n
].value
= 1;
1325 criteria
[n
+ 1].capability
= RED_SIZE
;
1326 criteria
[n
+ 1].comparison
= GTE
;
1327 criteria
[n
+ 1].value
= 1;
1328 criteria
[n
+ 2].capability
= GREEN_SIZE
;
1329 criteria
[n
+ 2].comparison
= GTE
;
1330 criteria
[n
+ 2].value
= 1;
1331 criteria
[n
+ 3].capability
= BLUE_SIZE
;
1332 criteria
[n
+ 3].comparison
= GTE
;
1333 criteria
[n
+ 3].value
= 1;
1334 criteria
[n
+ 4].capability
= ALPHA_SIZE
;
1335 criteria
[n
+ 4].comparison
= MIN
;
1336 criteria
[n
+ 4].value
= 0;
1338 mask
|= (1 << RGBA_MODE
);
1340 #if !defined(_WIN32)
1341 if (!(mask
& (1 << XSTATICGRAY
))) {
1342 assert(isMesaGLX
!= -1);
1343 if ((mask
& (1 << RGBA_MODE
)) && !isMesaGLX
) {
1344 /* Normally, request an RGBA mode visual be TrueColor,
1345 except in the case of Mesa where we trust Mesa (and
1346 other code in GLUT) to handle any type of RGBA visual
1348 if (mask
& (1 << LUMINANCE_MODE
)) {
1349 /* If RGBA luminance was requested, actually go for
1350 a StaticGray visual. */
1351 criteria
[n
].capability
= XSTATICGRAY
;
1353 criteria
[n
].capability
= XTRUECOLOR
;
1355 criteria
[n
].value
= 1;
1356 criteria
[n
].comparison
= EQ
;
1360 if (mask
& (1 << CI_MODE
)) {
1361 criteria
[n
].capability
= XPSEUDOCOLOR
;
1362 criteria
[n
].value
= 1;
1363 criteria
[n
].comparison
= EQ
;
1368 if (!(mask
& (1 << STEREO
))) {
1369 criteria
[n
].capability
= STEREO
;
1370 criteria
[n
].comparison
= EQ
;
1371 criteria
[n
].value
= 0;
1374 if (!(mask
& (1 << DOUBLEBUFFER
))) {
1375 criteria
[n
].capability
= DOUBLEBUFFER
;
1376 criteria
[n
].comparison
= EQ
;
1377 criteria
[n
].value
= 0;
1378 *allowDoubleAsSingle
= True
;
1381 if (!(mask
& (1 << DEPTH_SIZE
))) {
1382 criteria
[n
].capability
= DEPTH_SIZE
;
1383 criteria
[n
].comparison
= MIN
;
1384 criteria
[n
].value
= 0;
1387 if (!(mask
& (1 << STENCIL_SIZE
))) {
1388 criteria
[n
].capability
= STENCIL_SIZE
;
1389 criteria
[n
].comparison
= MIN
;
1390 criteria
[n
].value
= 0;
1393 if (!(mask
& (1 << LEVEL
))) {
1394 criteria
[n
].capability
= LEVEL
;
1395 criteria
[n
].comparison
= EQ
;
1396 criteria
[n
].value
= 0;
1400 /* Since over-estimated the size needed; squeeze it down to
1402 criteria
= (Criterion
*) realloc(criteria
, n
* sizeof(Criterion
));
1404 /* Should never happen since should be shrinking down! */
1405 __glutFatalError("out of memory.");
1408 /* For portability, avoid "realloc(ptr,0)" call. */
1418 static FrameBufferMode
*fbmodes
= NULL
;
1419 static int nfbmodes
= 0;
1421 static XVisualInfo
*
1422 getVisualInfoFromString(char *string
, Bool
* treatAsSingle
,
1423 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
, void **fbc
)
1425 Criterion
*criteria
;
1426 XVisualInfo
*visinfo
;
1427 Bool allowDoubleAsSingle
;
1431 fbmodes
= loadVisuals(&nfbmodes
);
1433 criteria
= parseModeString(string
, &ncriteria
,
1434 &allowDoubleAsSingle
, requiredCriteria
, nRequired
, requiredMask
);
1435 if (criteria
== NULL
) {
1436 __glutWarning("failed to parse mode string");
1440 printCriteria(criteria
, ncriteria
);
1442 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
1446 if (allowDoubleAsSingle
) {
1447 /* Rewrite criteria so that we now look for a double
1448 buffered visual which will then get treated as a
1449 single buffered visual. */
1450 for (i
= 0; i
< ncriteria
; i
++) {
1451 if (criteria
[i
].capability
== DOUBLEBUFFER
1452 && criteria
[i
].comparison
== EQ
1453 && criteria
[i
].value
== 0) {
1454 criteria
[i
].value
= 1;
1457 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
1467 /* We could have a valid pixel format for drawing to a
1468 bitmap. However, we don't want to draw into a bitmap, we
1469 need one that can be used with a window, so make sure
1470 that this is true. */
1471 if (!(visinfo
->dwFlags
& PFD_DRAW_TO_WINDOW
))
1482 glutInitDisplayString(const char *string
)
1485 XHDC
= GetDC(GetDesktopWindow());
1488 __glutDetermineVisualFromString
= getVisualInfoFromString
;
1489 if (__glutDisplayString
) {
1490 free(__glutDisplayString
);
1493 __glutDisplayString
= __glutStrdup(string
);
1494 if (!__glutDisplayString
)
1495 __glutFatalError("out of memory.");
1497 __glutDisplayString
= NULL
;
1504 Criterion requiredWindowCriteria
[] =
1507 {TRANSPARENT
, EQ
, 0}
1509 int numRequiredWindowCriteria
= sizeof(requiredWindowCriteria
) / sizeof(Criterion
);
1510 int requiredWindowCriteriaMask
= (1 << LEVEL
) | (1 << TRANSPARENT
);
1512 Criterion requiredOverlayCriteria
[] =
1515 {TRANSPARENT
, EQ
, 1},
1516 {XPSEUDOCOLOR
, EQ
, 1},
1518 {BUFFER_SIZE
, GTE
, 1}
1520 int numRequiredOverlayCriteria
= sizeof(requiredOverlayCriteria
) / sizeof(Criterion
);
1521 int requiredOverlayCriteriaMask
=
1522 (1 << LEVEL
) | (1 << TRANSPARENT
) | (1 << XSTATICGRAY
) | (1 << RGBA
) | (1 << CI_MODE
);
1525 main(int argc
, char **argv
)
1530 char *str
, buffer
[1024];
1531 int tty
= isatty(fileno(stdin
));
1532 int overlay
= 0, showconfig
= 0;
1533 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
1534 GLXFBConfigSGIX fbc
;
1539 #if !defined(_WIN32)
1540 dpy
= XOpenDisplay(NULL
);
1542 printf("Could not connect to X server\n");
1545 __glutDisplay
= dpy
;
1546 __glutScreen
= DefaultScreen(__glutDisplay
);
1548 while (!feof(stdin
)) {
1551 str
= fgets(buffer
, 1023, stdin
);
1554 if (!strcmp("v", str
)) {
1555 verbose
= 1 - verbose
;
1556 printf("verbose = %d\n\n", verbose
);
1557 } else if (!strcmp("s", str
)) {
1558 showconfig
= 1 - showconfig
;
1559 printf("showconfig = %d\n\n", showconfig
);
1560 } else if (!strcmp("o", str
)) {
1561 overlay
= 1 - overlay
;
1562 printf("overlay = %d\n\n", overlay
);
1565 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1566 requiredOverlayCriteria
, numRequiredOverlayCriteria
, requiredOverlayCriteriaMask
, (void**) &fbc
);
1568 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1569 requiredWindowCriteria
, numRequiredWindowCriteria
, requiredWindowCriteriaMask
, (void**) &fbc
);
1574 printf("Display string: %s", str
);
1576 printf("Visual = 0x%x\n", 0);
1578 printf("Visual = 0x%x%s\n", vinfo
->visualid
, fbc
? " (needs FBC)" : "");
1580 if (treatAsSingle
) {
1581 printf("Treat as SINGLE.\n");
1584 int glxCapable
, bufferSize
, level
, renderType
, doubleBuffer
,
1585 stereo
, auxBuffers
, redSize
, greenSize
, blueSize
,
1586 alphaSize
, depthSize
, stencilSize
, acRedSize
, acGreenSize
,
1587 acBlueSize
, acAlphaSize
;
1589 glXGetConfig(dpy
, vinfo
, GLX_BUFFER_SIZE
, &bufferSize
);
1590 glXGetConfig(dpy
, vinfo
, GLX_LEVEL
, &level
);
1591 glXGetConfig(dpy
, vinfo
, GLX_RGBA
, &renderType
);
1592 glXGetConfig(dpy
, vinfo
, GLX_DOUBLEBUFFER
, &doubleBuffer
);
1593 glXGetConfig(dpy
, vinfo
, GLX_STEREO
, &stereo
);
1594 glXGetConfig(dpy
, vinfo
, GLX_AUX_BUFFERS
, &auxBuffers
);
1595 glXGetConfig(dpy
, vinfo
, GLX_RED_SIZE
, &redSize
);
1596 glXGetConfig(dpy
, vinfo
, GLX_GREEN_SIZE
, &greenSize
);
1597 glXGetConfig(dpy
, vinfo
, GLX_BLUE_SIZE
, &blueSize
);
1598 glXGetConfig(dpy
, vinfo
, GLX_ALPHA_SIZE
, &alphaSize
);
1599 glXGetConfig(dpy
, vinfo
, GLX_DEPTH_SIZE
, &depthSize
);
1600 glXGetConfig(dpy
, vinfo
, GLX_STENCIL_SIZE
, &stencilSize
);
1601 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_RED_SIZE
, &acRedSize
);
1602 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_GREEN_SIZE
, &acGreenSize
);
1603 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_BLUE_SIZE
, &acBlueSize
);
1604 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_ALPHA_SIZE
, &acAlphaSize
);
1605 printf("RGBA = (%d, %d, %d, %d)\n", redSize
, greenSize
, blueSize
, alphaSize
);
1606 printf("acc = (%d, %d, %d, %d)\n", acRedSize
, acGreenSize
, acBlueSize
, acAlphaSize
);
1607 printf("db = %d\n", doubleBuffer
);
1608 printf("str = %d\n", stereo
);
1609 printf("aux = %d\n", auxBuffers
);
1610 printf("lvl = %d\n", level
);
1611 printf("buf = %d\n", bufferSize
);
1612 printf("rgba = %d\n", renderType
);
1613 printf("z = %d\n", depthSize
);
1614 printf("s = %d\n", stencilSize
);
1618 printf("No match.\n");