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) || defined(GLX_ARB_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) || defined(GLX_ARB_multisample))
279 multisample
= __glutIsSupportedByGLX("GLX_SGIS_multisample") ||
280 __glutIsSupportedByGLX("GLX_ARB_multisample");
282 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
283 visual_info
= __glutIsSupportedByGLX("GLX_EXT_visual_info");
285 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
286 visual_rating
= __glutIsSupportedByGLX("GLX_EXT_visual_rating");
288 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
289 fbconfig
= __glutIsSupportedByGLX("GLX_SGIX_fbconfig");
292 fbmodes
= (FrameBufferMode
*) malloc(n
* sizeof(FrameBufferMode
));
293 if (fbmodes
== NULL
) {
298 for (i
= 0; i
< n
; i
++) {
301 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
304 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], GLX_USE_GL
, &glcapable
);
305 if (rc
== 0 && glcapable
) {
306 mode
->valid
= 1; /* Assume the best until proven
308 for (j
= 0; j
< NUM_GLXCAPS
; j
++) {
309 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], glxcap
[j
], &mode
->cap
[j
]);
315 mode
->cap
[XVISUAL
] = ChoosePixelFormat(XHDC
, vlist
[i
]);
317 mode
->cap
[XVISUAL
] = (int) vlist
[i
]->visualid
;
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;
326 #if defined(__cplusplus) || defined(c_plusplus)
327 switch (vlist
[i
]->c_class
) {
329 switch (vlist
[i
]->class) {
332 mode
->cap
[XSTATICGRAY
] = 1;
335 mode
->cap
[XGRAYSCALE
] = 1;
338 mode
->cap
[XSTATICCOLOR
] = 1;
341 mode
->cap
[XPSEUDOCOLOR
] = 1;
344 mode
->cap
[XTRUECOLOR
] = 1;
347 mode
->cap
[XDIRECTCOLOR
] = 1;
351 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
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
363 rc
= glXGetConfig(__glutDisplay
,
364 vlist
[i
], GLX_VISUAL_CAVEAT_EXT
, &rating
);
367 mode
->cap
[CONFORMANT
] = 1;
370 case GLX_SLOW_VISUAL_EXT
:
372 mode
->cap
[CONFORMANT
] = 1;
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
381 case GLX_NON_CONFORMANT_VISUAL_EXT
:
383 mode
->cap
[CONFORMANT
] = 0;
386 default: /* XXX Hopefully this is a good default
389 mode
->cap
[CONFORMANT
] = 1;
394 mode
->cap
[TRANSPARENT
] = 0;
398 mode
->cap
[CONFORMANT
] = 1;
400 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
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
412 rc
= glXGetConfig(__glutDisplay
,
413 vlist
[i
], GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
415 mode
->cap
[TRANSPARENT
] = 0;
417 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
420 mode
->cap
[TRANSPARENT
] = 0;
423 mode
->cap
[TRANSPARENT
] = 0;
425 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
427 rc
= glXGetConfig(__glutDisplay
,
428 vlist
[i
], GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
430 mode
->cap
[SAMPLES
] = 0;
433 mode
->cap
[SAMPLES
] = 0;
436 mode
->cap
[SAMPLES
] = 0;
439 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
442 int fbconfigID
, drawType
, renderType
;
444 fbc
= __glut_glXGetFBConfigFromVisualSGIX(__glutDisplay
, vlist
[i
]);
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
)) {
456 mode
->valid
= 1; /* Assume the best until
459 assert(glxcap
[0] == GLX_RGBA
);
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
]);
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
) {
481 switch (vlist
[i
]->class) {
484 mode
->cap
[XSTATICGRAY
] = 1;
487 mode
->cap
[XGRAYSCALE
] = 1;
490 mode
->cap
[XSTATICCOLOR
] = 1;
493 mode
->cap
[XPSEUDOCOLOR
] = 1;
496 mode
->cap
[XTRUECOLOR
] = 1;
499 mode
->cap
[XDIRECTCOLOR
] = 1;
502 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
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
514 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
515 fbc
, GLX_VISUAL_CAVEAT_EXT
, &rating
);
518 mode
->cap
[CONFORMANT
] = 1;
521 case GLX_SLOW_VISUAL_EXT
:
523 mode
->cap
[CONFORMANT
] = 1;
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
532 case GLX_NON_CONFORMANT_VISUAL_EXT
:
534 mode
->cap
[CONFORMANT
] = 0;
537 default: /* XXX Hopefully this is a good
538 default assumption. */
540 mode
->cap
[CONFORMANT
] = 1;
545 mode
->cap
[TRANSPARENT
] = 0;
549 mode
->cap
[CONFORMANT
] = 1;
551 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
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
563 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
564 fbc
, GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
566 mode
->cap
[TRANSPARENT
] = 0;
568 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
571 mode
->cap
[TRANSPARENT
] = 0;
574 mode
->cap
[TRANSPARENT
] = 0;
576 #if defined(GLX_VERSION_1_1) && (defined(GLX_SGIS_multisample) || defined(GLX_ARB_multisample))
578 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
579 fbc
, GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
581 mode
->cap
[SAMPLES
] = 0;
584 mode
->cap
[SAMPLES
] = 0;
587 mode
->cap
[SAMPLES
] = 0;
591 /* Fbconfig is not RGBA; GLUT only uses RGBA
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. */
600 /* Fbconfig does not support window rendering;
601 not a valid FBconfig for GLUT windows. */
605 /* FBconfig ID is None (zero); not a valid
610 /* FBconfig ID is None (zero); not a valid FBconfig. */
614 /* No SGIX_fbconfig GLX sever implementation support. */
618 /* No SGIX_fbconfig GLX extension API support. */
630 findMatch(FrameBufferMode
* fbmodes
, int nfbmodes
,
631 Criterion
* criteria
, int ncriteria
, void **fbc
)
633 FrameBufferMode
*found
;
634 int *bestScore
, *thisScore
;
635 int i
, j
, numok
, result
= 0, worse
, better
;
638 numok
= 1; /* "num" capability is indexed from 1,
641 /* XXX alloca canidate. */
642 bestScore
= (int *) malloc(ncriteria
* sizeof(int));
644 __glutFatalError("out of memory.");
645 for (j
= 0; j
< ncriteria
; j
++) {
646 /* Very negative number. */
647 bestScore
[j
] = -32768;
650 /* XXX alloca canidate. */
651 thisScore
= (int *) malloc(ncriteria
* sizeof(int));
653 __glutFatalError("out of memory.");
655 for (i
= 0; i
< nfbmodes
; i
++) {
656 if (fbmodes
[i
].valid
) {
660 printf("Visual 0x%x\n", fbmodes
[i
].vi
->visualid
);
667 for (j
= 0; j
< ncriteria
; j
++) {
668 int cap
, cvalue
, fbvalue
;
670 cap
= criteria
[j
].capability
;
671 cvalue
= criteria
[j
].value
;
675 fbvalue
= fbmodes
[i
].cap
[cap
];
679 printf(" %s %s %d to %d\n",
680 capstr
[cap
], compstr
[criteria
[j
].comparison
], cvalue
, fbvalue
);
682 switch (criteria
[j
].comparison
) {
684 result
= cvalue
== fbvalue
;
688 result
= cvalue
!= fbvalue
;
692 result
= fbvalue
< cvalue
;
693 thisScore
[j
] = fbvalue
- cvalue
;
696 result
= fbvalue
> cvalue
;
697 thisScore
[j
] = fbvalue
- cvalue
;
700 result
= fbvalue
<= cvalue
;
701 thisScore
[j
] = fbvalue
- cvalue
;
704 result
= (fbvalue
>= cvalue
);
705 thisScore
[j
] = fbvalue
- cvalue
;
708 result
= fbvalue
>= cvalue
;
709 thisScore
[j
] = cvalue
- fbvalue
;
715 printf(" result=%d score=%d bestScore=%d\n", result
, thisScore
[j
], bestScore
[j
]);
719 if (better
|| thisScore
[j
] > bestScore
[j
]) {
721 } else if (thisScore
[j
] == bestScore
[j
]) {
736 if (better
&& !worse
) {
738 for (j
= 0; j
< ncriteria
; j
++) {
739 bestScore
[j
] = thisScore
[j
];
751 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
761 parseCriteria(char *word
, Criterion
* criterion
, int *mask
,
762 Bool
* allowDoubleAsSingle
)
764 char *cstr
, *vstr
, *response
;
765 int comparator
, value
= 0;
766 int rgb
, rgba
, acc
, acca
, count
, i
;
768 cstr
= strpbrk(word
, "=><!~");
780 if (cstr
[1] == '=') {
789 if (cstr
[1] == '=') {
798 if (cstr
[1] == '=') {
808 value
= (int) strtol(vstr
, &response
, 0);
809 if (response
== vstr
) {
810 /* Not a valid number. */
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;
825 criterion
[0].comparison
= comparator
;
826 criterion
[0].value
= value
;
828 *mask
|= (1 << RGBA
);
829 *mask
|= (1 << ALPHA_SIZE
);
830 *mask
|= (1 << RGBA_MODE
);
833 acca
= !strcmp(word
, "acca");
834 acc
= !strcmp(word
, "acc");
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
;
844 criterion
[3].comparison
= MIN
;
845 criterion
[3].value
= 0;
847 if (comparator
== NONE
) {
851 for (i
= 0; i
< count
; i
++) {
852 criterion
[i
].comparison
= comparator
;
853 criterion
[i
].value
= value
;
855 *mask
|= (1 << ACCUM_RED_SIZE
);
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;
864 criterion
[0].comparison
= comparator
;
865 criterion
[0].value
= value
;
867 *mask
|= (1 << AUX_BUFFERS
);
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;
878 criterion
[0].comparison
= comparator
;
879 criterion
[0].value
= value
;
881 *mask
|= (1 << RGBA
);
882 *mask
|= (1 << RGBA_MODE
);
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;
891 criterion
[0].comparison
= comparator
;
892 criterion
[0].value
= value
;
898 if (!strcmp(word
, "conformant")) {
899 criterion
[0].capability
= CONFORMANT
;
900 if (comparator
== NONE
) {
901 criterion
[0].comparison
= EQ
;
902 criterion
[0].value
= 1;
904 criterion
[0].comparison
= comparator
;
905 criterion
[0].value
= value
;
907 *mask
|= (1 << CONFORMANT
);
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;
918 criterion
[0].comparison
= comparator
;
919 criterion
[0].value
= value
;
921 *mask
|= (1 << DEPTH_SIZE
);
924 if (!strcmp(word
, "double")) {
925 criterion
[0].capability
= DOUBLEBUFFER
;
926 if (comparator
== NONE
) {
927 criterion
[0].comparison
= EQ
;
928 criterion
[0].value
= 1;
930 criterion
[0].comparison
= comparator
;
931 criterion
[0].value
= value
;
933 *mask
|= (1 << DOUBLEBUFFER
);
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;
944 criterion
[0].comparison
= comparator
;
945 criterion
[0].value
= value
;
947 *mask
|= (1 << RGBA
);
948 *mask
|= (1 << RGBA_MODE
);
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;
964 criterion
[1].comparison
= comparator
;
965 criterion
[1].value
= value
;
971 if (!strcmp(word
, "luminance")) {
972 criterion
[0].capability
= RGBA
;
973 criterion
[0].comparison
= EQ
;
974 criterion
[0].value
= 1;
976 criterion
[1].capability
= RED_SIZE
;
977 if (comparator
== NONE
) {
978 criterion
[1].comparison
= GTE
;
979 criterion
[1].value
= 1;
981 criterion
[1].comparison
= comparator
;
982 criterion
[1].value
= value
;
985 criterion
[2].capability
= GREEN_SIZE
;
986 criterion
[2].comparison
= EQ
;
987 criterion
[2].value
= 0;
989 criterion
[3].capability
= BLUE_SIZE
;
990 criterion
[3].comparison
= EQ
;
991 criterion
[3].value
= 0;
993 *mask
|= (1 << RGBA
);
994 *mask
|= (1 << RGBA_MODE
);
995 *mask
|= (1 << LUMINANCE_MODE
);
1000 if (!strcmp(word
, "num")) {
1001 criterion
[0].capability
= NUM
;
1002 if (comparator
== NONE
) {
1005 criterion
[0].comparison
= comparator
;
1006 criterion
[0].value
= value
;
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;
1018 criterion
[0].comparison
= comparator
;
1019 criterion
[0].value
= value
;
1021 *mask
|= (1 << RGBA
);
1022 *mask
|= (1 << RGBA_MODE
);
1025 rgba
= !strcmp(word
, "rgba");
1026 rgb
= !strcmp(word
, "rgb");
1028 criterion
[0].capability
= RGBA
;
1029 criterion
[0].comparison
= EQ
;
1030 criterion
[0].value
= 1;
1032 criterion
[1].capability
= RED_SIZE
;
1033 criterion
[2].capability
= GREEN_SIZE
;
1034 criterion
[3].capability
= BLUE_SIZE
;
1035 criterion
[4].capability
= ALPHA_SIZE
;
1040 criterion
[4].comparison
= MIN
;
1041 criterion
[4].value
= 0;
1043 if (comparator
== NONE
) {
1047 for (i
= 1; i
< count
; i
++) {
1048 criterion
[i
].comparison
= comparator
;
1049 criterion
[i
].value
= value
;
1051 *mask
|= (1 << RGBA
);
1052 *mask
|= (1 << RGBA_MODE
);
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;
1063 criterion
[0].comparison
= comparator
;
1064 criterion
[0].value
= value
;
1066 *mask
|= (1 << STENCIL_SIZE
);
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
);
1081 if (!strcmp(word
, "stereo")) {
1082 criterion
[0].capability
= STEREO
;
1083 if (comparator
== NONE
) {
1084 criterion
[0].comparison
= EQ
;
1085 criterion
[0].value
= 1;
1087 criterion
[0].comparison
= comparator
;
1088 criterion
[0].value
= value
;
1090 *mask
|= (1 << STEREO
);
1093 if (!strcmp(word
, "samples")) {
1094 criterion
[0].capability
= SAMPLES
;
1095 if (comparator
== NONE
) {
1096 criterion
[0].comparison
= LTE
;
1097 criterion
[0].value
= 4;
1099 criterion
[0].comparison
= comparator
;
1100 criterion
[0].value
= value
;
1102 *mask
|= (1 << SAMPLES
);
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;
1114 criterion
[0].comparison
= comparator
;
1115 criterion
[0].value
= value
;
1117 *mask
|= (1 << SLOW
);
1123 if (!strcmp(word
, "win32pfd")) {
1124 criterion
[0].capability
= XVISUAL
;
1125 if (comparator
== NONE
) {
1128 criterion
[0].comparison
= comparator
;
1129 criterion
[0].value
= value
;
1135 #if !defined(_WIN32)
1137 if (!strcmp(word
, "xvisual")) {
1138 if (comparator
== NONE
) {
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. */
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
1154 if (comparator
== NONE
) {
1155 criterion
[0].comparison
= EQ
;
1156 criterion
[0].value
= 1;
1158 criterion
[0].comparison
= comparator
;
1159 criterion
[0].value
= value
;
1162 if (!strcmp(word
, "xstaticgray")) {
1163 criterion
[0].capability
= XSTATICGRAY
;
1164 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1168 if (!strcmp(word
, "xgrayscale")) {
1169 criterion
[0].capability
= XGRAYSCALE
;
1170 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1174 if (!strcmp(word
, "xstaticcolor")) {
1175 criterion
[0].capability
= XSTATICCOLOR
;
1176 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1180 if (!strcmp(word
, "xpseudocolor")) {
1181 criterion
[0].capability
= XPSEUDOCOLOR
;
1182 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1186 if (!strcmp(word
, "xtruecolor")) {
1187 criterion
[0].capability
= XTRUECOLOR
;
1188 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1192 if (!strcmp(word
, "xdirectcolor")) {
1193 criterion
[0].capability
= XDIRECTCOLOR
;
1194 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1206 parseModeString(char *mode
, int *ncriteria
, Bool
* allowDoubleAsSingle
,
1207 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
)
1209 Criterion
*criteria
= NULL
;
1210 int n
, mask
, parsed
, i
;
1213 *allowDoubleAsSingle
= False
;
1214 copy
= __glutStrdup(mode
);
1215 /* Attempt to estimate how many criteria entries should be
1218 word
= strtok(copy
, " \t");
1221 word
= strtok(NULL
, " \t");
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
));
1228 __glutFatalError("out of memory.");
1231 /* Re-copy the copy of the mode string. */
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
];
1243 word
= strtok(copy
, " \t");
1245 parsed
= parseCriteria(word
, &criteria
[n
], &mask
, allowDoubleAsSingle
);
1249 __glutWarning("Unrecognized display string word: %s (ignoring)\n", word
);
1251 word
= strtok(NULL
, " \t");
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;
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;
1272 mask
|= (1 << CONFORMANT
);
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;
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;
1295 if (!(mask
& (1 << CONFORMANT
))) {
1296 criteria
[n
].capability
= CONFORMANT
;
1297 criteria
[n
].comparison
= EQ
;
1298 criteria
[n
].value
= 1;
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;
1318 if (!(mask
& (1 << AUX_BUFFERS
))) {
1319 criteria
[n
].capability
= AUX_BUFFERS
;
1320 criteria
[n
].comparison
= MIN
;
1321 criteria
[n
].value
= 0;
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;
1341 mask
|= (1 << RGBA_MODE
);
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
1351 if (mask
& (1 << LUMINANCE_MODE
)) {
1352 /* If RGBA luminance was requested, actually go for
1353 a StaticGray visual. */
1354 criteria
[n
].capability
= XSTATICGRAY
;
1356 criteria
[n
].capability
= XTRUECOLOR
;
1358 criteria
[n
].value
= 1;
1359 criteria
[n
].comparison
= EQ
;
1363 if (mask
& (1 << CI_MODE
)) {
1364 criteria
[n
].capability
= XPSEUDOCOLOR
;
1365 criteria
[n
].value
= 1;
1366 criteria
[n
].comparison
= EQ
;
1371 if (!(mask
& (1 << STEREO
))) {
1372 criteria
[n
].capability
= STEREO
;
1373 criteria
[n
].comparison
= EQ
;
1374 criteria
[n
].value
= 0;
1377 if (!(mask
& (1 << DOUBLEBUFFER
))) {
1378 criteria
[n
].capability
= DOUBLEBUFFER
;
1379 criteria
[n
].comparison
= EQ
;
1380 criteria
[n
].value
= 0;
1381 *allowDoubleAsSingle
= True
;
1384 if (!(mask
& (1 << DEPTH_SIZE
))) {
1385 criteria
[n
].capability
= DEPTH_SIZE
;
1386 criteria
[n
].comparison
= MIN
;
1387 criteria
[n
].value
= 0;
1390 if (!(mask
& (1 << STENCIL_SIZE
))) {
1391 criteria
[n
].capability
= STENCIL_SIZE
;
1392 criteria
[n
].comparison
= MIN
;
1393 criteria
[n
].value
= 0;
1396 if (!(mask
& (1 << LEVEL
))) {
1397 criteria
[n
].capability
= LEVEL
;
1398 criteria
[n
].comparison
= EQ
;
1399 criteria
[n
].value
= 0;
1403 /* Since over-estimated the size needed; squeeze it down to
1405 criteria
= (Criterion
*) realloc(criteria
, n
* sizeof(Criterion
));
1407 /* Should never happen since should be shrinking down! */
1408 __glutFatalError("out of memory.");
1411 /* For portability, avoid "realloc(ptr,0)" call. */
1421 static FrameBufferMode
*fbmodes
= NULL
;
1422 static int nfbmodes
= 0;
1424 static XVisualInfo
*
1425 getVisualInfoFromString(char *string
, Bool
* treatAsSingle
,
1426 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
, void **fbc
)
1428 Criterion
*criteria
;
1429 XVisualInfo
*visinfo
;
1430 Bool allowDoubleAsSingle
;
1434 fbmodes
= loadVisuals(&nfbmodes
);
1436 criteria
= parseModeString(string
, &ncriteria
,
1437 &allowDoubleAsSingle
, requiredCriteria
, nRequired
, requiredMask
);
1438 if (criteria
== NULL
) {
1439 __glutWarning("failed to parse mode string");
1443 printCriteria(criteria
, ncriteria
);
1445 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
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;
1460 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
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
))
1485 glutInitDisplayString(const char *string
)
1488 XHDC
= GetDC(GetDesktopWindow());
1491 __glutDetermineVisualFromString
= getVisualInfoFromString
;
1492 if (__glutDisplayString
) {
1493 free(__glutDisplayString
);
1496 __glutDisplayString
= __glutStrdup(string
);
1497 if (!__glutDisplayString
)
1498 __glutFatalError("out of memory.");
1500 __glutDisplayString
= NULL
;
1507 Criterion requiredWindowCriteria
[] =
1510 {TRANSPARENT
, EQ
, 0}
1512 int numRequiredWindowCriteria
= sizeof(requiredWindowCriteria
) / sizeof(Criterion
);
1513 int requiredWindowCriteriaMask
= (1 << LEVEL
) | (1 << TRANSPARENT
);
1515 Criterion requiredOverlayCriteria
[] =
1518 {TRANSPARENT
, EQ
, 1},
1519 {XPSEUDOCOLOR
, EQ
, 1},
1521 {BUFFER_SIZE
, GTE
, 1}
1523 int numRequiredOverlayCriteria
= sizeof(requiredOverlayCriteria
) / sizeof(Criterion
);
1524 int requiredOverlayCriteriaMask
=
1525 (1 << LEVEL
) | (1 << TRANSPARENT
) | (1 << XSTATICGRAY
) | (1 << RGBA
) | (1 << CI_MODE
);
1528 main(int argc
, char **argv
)
1533 char *str
, buffer
[1024];
1534 int tty
= isatty(fileno(stdin
));
1535 int overlay
= 0, showconfig
= 0;
1538 #if !defined(_WIN32)
1539 dpy
= XOpenDisplay(NULL
);
1541 printf("Could not connect to X server\n");
1544 __glutDisplay
= dpy
;
1545 __glutScreen
= DefaultScreen(__glutDisplay
);
1547 while (!feof(stdin
)) {
1550 str
= fgets(buffer
, 1023, stdin
);
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
);
1564 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1565 requiredOverlayCriteria
, numRequiredOverlayCriteria
, requiredOverlayCriteriaMask
, &fbc
);
1567 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1568 requiredWindowCriteria
, numRequiredWindowCriteria
, requiredWindowCriteriaMask
, &fbc
);
1573 printf("Display string: %s", str
);
1575 printf("Visual = 0x%x\n", 0);
1577 printf("Visual = 0x%x%s\n", vinfo
->visualid
, fbc
? " (needs FBC)" : "");
1579 if (treatAsSingle
) {
1580 printf("Treat as SINGLE.\n");
1583 int glxCapable
, bufferSize
, level
, renderType
, doubleBuffer
,
1584 stereo
, auxBuffers
, redSize
, greenSize
, blueSize
,
1585 alphaSize
, depthSize
, stencilSize
, acRedSize
, acGreenSize
,
1586 acBlueSize
, acAlphaSize
;
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
);
1617 printf("No match.\n");