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
) {
297 for (i
= 0; i
< n
; i
++) {
300 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
303 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], GLX_USE_GL
, &glcapable
);
304 if (rc
== 0 && glcapable
) {
305 mode
->valid
= 1; /* Assume the best until proven
307 for (j
= 0; j
< NUM_GLXCAPS
; j
++) {
308 rc
= glXGetConfig(__glutDisplay
, vlist
[i
], glxcap
[j
], &mode
->cap
[j
]);
314 mode
->cap
[XVISUAL
] = ChoosePixelFormat(XHDC
, vlist
[i
]);
316 mode
->cap
[XVISUAL
] = (int) vlist
[i
]->visualid
;
318 mode
->cap
[XSTATICGRAY
] = 0;
319 mode
->cap
[XGRAYSCALE
] = 0;
320 mode
->cap
[XSTATICCOLOR
] = 0;
321 mode
->cap
[XPSEUDOCOLOR
] = 0;
322 mode
->cap
[XTRUECOLOR
] = 0;
323 mode
->cap
[XDIRECTCOLOR
] = 0;
325 #if defined(__cplusplus) || defined(c_plusplus)
326 switch (vlist
[i
]->c_class
) {
328 switch (vlist
[i
]->class) {
331 mode
->cap
[XSTATICGRAY
] = 1;
334 mode
->cap
[XGRAYSCALE
] = 1;
337 mode
->cap
[XSTATICCOLOR
] = 1;
340 mode
->cap
[XPSEUDOCOLOR
] = 1;
343 mode
->cap
[XTRUECOLOR
] = 1;
346 mode
->cap
[XDIRECTCOLOR
] = 1;
350 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
354 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
355 564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
356 in <GL/glx.h> despite claiming to support
357 GLX_EXT_visual_rating. */
358 #ifndef GLX_VISUAL_CAVEAT_EXT
359 #define GLX_VISUAL_CAVEAT_EXT 0x20
362 rc
= glXGetConfig(__glutDisplay
,
363 vlist
[i
], GLX_VISUAL_CAVEAT_EXT
, &rating
);
366 mode
->cap
[CONFORMANT
] = 1;
369 case GLX_SLOW_VISUAL_EXT
:
371 mode
->cap
[CONFORMANT
] = 1;
374 /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
375 properly defined in /usr/include/GL/glxtokens.h */
376 #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
377 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
380 case GLX_NON_CONFORMANT_VISUAL_EXT
:
382 mode
->cap
[CONFORMANT
] = 0;
385 default: /* XXX Hopefully this is a good default
388 mode
->cap
[CONFORMANT
] = 1;
393 mode
->cap
[TRANSPARENT
] = 0;
397 mode
->cap
[CONFORMANT
] = 1;
399 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
403 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
404 564 for Alpha did not properly define
405 GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
406 support GLX_EXT_visual_info. */
407 #ifndef GLX_TRANSPARENT_TYPE_EXT
408 #define GLX_TRANSPARENT_TYPE_EXT 0x23
411 rc
= glXGetConfig(__glutDisplay
,
412 vlist
[i
], GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
414 mode
->cap
[TRANSPARENT
] = 0;
416 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
419 mode
->cap
[TRANSPARENT
] = 0;
422 mode
->cap
[TRANSPARENT
] = 0;
424 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
426 rc
= glXGetConfig(__glutDisplay
,
427 vlist
[i
], GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
429 mode
->cap
[SAMPLES
] = 0;
432 mode
->cap
[SAMPLES
] = 0;
435 mode
->cap
[SAMPLES
] = 0;
438 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
441 int fbconfigID
, drawType
, renderType
;
443 fbc
= __glut_glXGetFBConfigFromVisualSGIX(__glutDisplay
, vlist
[i
]);
445 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
446 GLX_FBCONFIG_ID_SGIX
, &fbconfigID
);
447 if ((rc
== 0) && (fbconfigID
!= None
)) {
448 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
449 GLX_DRAWABLE_TYPE_SGIX
, &drawType
);
450 if ((rc
== 0) && (drawType
& GLX_WINDOW_BIT_SGIX
)) {
451 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
, fbc
,
452 GLX_RENDER_TYPE_SGIX
, &renderType
);
453 if ((rc
== 0) && (renderType
& GLX_RGBA_BIT_SGIX
)) {
455 mode
->valid
= 1; /* Assume the best until
458 assert(glxcap
[0] == GLX_RGBA
);
461 /* Start with "j = 1" to skip the GLX_RGBA attribute. */
462 for (j
= 1; j
< NUM_GLXCAPS
; j
++) {
463 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
464 fbc
, glxcap
[j
], &mode
->cap
[j
]);
470 mode
->cap
[XVISUAL
] = (int) vlist
[i
]->visualid
;
471 mode
->cap
[XSTATICGRAY
] = 0;
472 mode
->cap
[XGRAYSCALE
] = 0;
473 mode
->cap
[XSTATICCOLOR
] = 0;
474 mode
->cap
[XPSEUDOCOLOR
] = 0;
475 mode
->cap
[XTRUECOLOR
] = 0;
476 mode
->cap
[XDIRECTCOLOR
] = 0;
477 #if defined(__cplusplus) || defined(c_plusplus)
478 switch (vlist
[i
]->c_class
) {
480 switch (vlist
[i
]->class) {
483 mode
->cap
[XSTATICGRAY
] = 1;
486 mode
->cap
[XGRAYSCALE
] = 1;
489 mode
->cap
[XSTATICCOLOR
] = 1;
492 mode
->cap
[XPSEUDOCOLOR
] = 1;
495 mode
->cap
[XTRUECOLOR
] = 1;
498 mode
->cap
[XDIRECTCOLOR
] = 1;
501 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
505 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
506 564 for Alpha did not properly define GLX_VISUAL_CAVEAT_EXT
507 in <GL/glx.h> despite claiming to support
508 GLX_EXT_visual_rating. */
509 #ifndef GLX_VISUAL_CAVEAT_EXT
510 #define GLX_VISUAL_CAVEAT_EXT 0x20
513 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
514 fbc
, GLX_VISUAL_CAVEAT_EXT
, &rating
);
517 mode
->cap
[CONFORMANT
] = 1;
520 case GLX_SLOW_VISUAL_EXT
:
522 mode
->cap
[CONFORMANT
] = 1;
525 /* IRIX 5.3 for the R10K Indigo2 may have shipped without this
526 properly defined in /usr/include/GL/glxtokens.h */
527 #ifndef GLX_NON_CONFORMANT_VISUAL_EXT
528 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
531 case GLX_NON_CONFORMANT_VISUAL_EXT
:
533 mode
->cap
[CONFORMANT
] = 0;
536 default: /* XXX Hopefully this is a good
537 default assumption. */
539 mode
->cap
[CONFORMANT
] = 1;
544 mode
->cap
[TRANSPARENT
] = 0;
548 mode
->cap
[CONFORMANT
] = 1;
550 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
554 /* babcock@cs.montana.edu reported that DEC UNIX (OSF1) V4.0
555 564 for Alpha did not properly define
556 GLX_TRANSPARENT_TYPE_EXT in <GL/glx.h> despite claiming to
557 support GLX_EXT_visual_info. */
558 #ifndef GLX_TRANSPARENT_TYPE_EXT
559 #define GLX_TRANSPARENT_TYPE_EXT 0x23
562 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
563 fbc
, GLX_TRANSPARENT_TYPE_EXT
, &transparent
);
565 mode
->cap
[TRANSPARENT
] = 0;
567 mode
->cap
[TRANSPARENT
] = (transparent
!= GLX_NONE_EXT
);
570 mode
->cap
[TRANSPARENT
] = 0;
573 mode
->cap
[TRANSPARENT
] = 0;
575 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
577 rc
= __glut_glXGetFBConfigAttribSGIX(__glutDisplay
,
578 fbc
, GLX_SAMPLES_SGIS
, &mode
->cap
[SAMPLES
]);
580 mode
->cap
[SAMPLES
] = 0;
583 mode
->cap
[SAMPLES
] = 0;
586 mode
->cap
[SAMPLES
] = 0;
590 /* Fbconfig is not RGBA; GLUT only uses RGBA
592 /* XXX Code could be exteneded to handle color
593 index FBconfigs, but seems a color index
594 window-renderable FBconfig would also be
595 advertised as an X visual. */
599 /* Fbconfig does not support window rendering;
600 not a valid FBconfig for GLUT windows. */
604 /* FBconfig ID is None (zero); not a valid
609 /* FBconfig ID is None (zero); not a valid FBconfig. */
613 /* No SGIX_fbconfig GLX sever implementation support. */
617 /* No SGIX_fbconfig GLX extension API support. */
629 findMatch(FrameBufferMode
* fbmodes
, int nfbmodes
,
630 Criterion
* criteria
, int ncriteria
, void **fbc
)
632 FrameBufferMode
*found
;
633 int *bestScore
, *thisScore
;
634 int i
, j
, numok
, result
= 0, worse
, better
;
637 numok
= 1; /* "num" capability is indexed from 1,
640 /* XXX alloca canidate. */
641 bestScore
= (int *) malloc(ncriteria
* sizeof(int));
643 __glutFatalError("out of memory.");
644 for (j
= 0; j
< ncriteria
; j
++) {
645 /* Very negative number. */
646 bestScore
[j
] = -32768;
649 /* XXX alloca canidate. */
650 thisScore
= (int *) malloc(ncriteria
* sizeof(int));
652 __glutFatalError("out of memory.");
654 for (i
= 0; i
< nfbmodes
; i
++) {
655 if (fbmodes
[i
].valid
) {
659 printf("Visual 0x%x\n", fbmodes
[i
].vi
->visualid
);
666 for (j
= 0; j
< ncriteria
; j
++) {
667 int cap
, cvalue
, fbvalue
;
669 cap
= criteria
[j
].capability
;
670 cvalue
= criteria
[j
].value
;
674 fbvalue
= fbmodes
[i
].cap
[cap
];
678 printf(" %s %s %d to %d\n",
679 capstr
[cap
], compstr
[criteria
[j
].comparison
], cvalue
, fbvalue
);
681 switch (criteria
[j
].comparison
) {
683 result
= cvalue
== fbvalue
;
687 result
= cvalue
!= fbvalue
;
691 result
= fbvalue
< cvalue
;
692 thisScore
[j
] = fbvalue
- cvalue
;
695 result
= fbvalue
> cvalue
;
696 thisScore
[j
] = fbvalue
- cvalue
;
699 result
= fbvalue
<= cvalue
;
700 thisScore
[j
] = fbvalue
- cvalue
;
703 result
= (fbvalue
>= cvalue
);
704 thisScore
[j
] = fbvalue
- cvalue
;
707 result
= fbvalue
>= cvalue
;
708 thisScore
[j
] = cvalue
- fbvalue
;
714 printf(" result=%d score=%d bestScore=%d\n", result
, thisScore
[j
], bestScore
[j
]);
718 if (better
|| thisScore
[j
] > bestScore
[j
]) {
720 } else if (thisScore
[j
] == bestScore
[j
]) {
735 if (better
&& !worse
) {
737 for (j
= 0; j
< ncriteria
; j
++) {
738 bestScore
[j
] = thisScore
[j
];
750 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
760 parseCriteria(char *word
, Criterion
* criterion
, int *mask
,
761 Bool
* allowDoubleAsSingle
)
763 char *cstr
, *vstr
, *response
;
764 int comparator
, value
= 0;
765 int rgb
, rgba
, acc
, acca
, count
, i
;
767 cstr
= strpbrk(word
, "=><!~");
779 if (cstr
[1] == '=') {
788 if (cstr
[1] == '=') {
797 if (cstr
[1] == '=') {
807 value
= (int) strtol(vstr
, &response
, 0);
808 if (response
== vstr
) {
809 /* Not a valid number. */
818 if (!strcmp(word
, "alpha")) {
819 criterion
[0].capability
= ALPHA_SIZE
;
820 if (comparator
== NONE
) {
821 criterion
[0].comparison
= GTE
;
822 criterion
[0].value
= 1;
824 criterion
[0].comparison
= comparator
;
825 criterion
[0].value
= value
;
827 *mask
|= (1 << RGBA
);
828 *mask
|= (1 << ALPHA_SIZE
);
829 *mask
|= (1 << RGBA_MODE
);
832 acca
= !strcmp(word
, "acca");
833 acc
= !strcmp(word
, "acc");
835 criterion
[0].capability
= ACCUM_RED_SIZE
;
836 criterion
[1].capability
= ACCUM_GREEN_SIZE
;
837 criterion
[2].capability
= ACCUM_BLUE_SIZE
;
838 criterion
[3].capability
= ACCUM_ALPHA_SIZE
;
843 criterion
[3].comparison
= MIN
;
844 criterion
[3].value
= 0;
846 if (comparator
== NONE
) {
850 for (i
= 0; i
< count
; i
++) {
851 criterion
[i
].comparison
= comparator
;
852 criterion
[i
].value
= value
;
854 *mask
|= (1 << ACCUM_RED_SIZE
);
857 if (!strcmp(word
, "auxbufs")) {
858 criterion
[0].capability
= AUX_BUFFERS
;
859 if (comparator
== NONE
) {
860 criterion
[0].comparison
= MIN
;
861 criterion
[0].value
= 1;
863 criterion
[0].comparison
= comparator
;
864 criterion
[0].value
= value
;
866 *mask
|= (1 << AUX_BUFFERS
);
871 if (!strcmp(word
, "blue")) {
872 criterion
[0].capability
= BLUE_SIZE
;
873 if (comparator
== NONE
) {
874 criterion
[0].comparison
= GTE
;
875 criterion
[0].value
= 1;
877 criterion
[0].comparison
= comparator
;
878 criterion
[0].value
= value
;
880 *mask
|= (1 << RGBA
);
881 *mask
|= (1 << RGBA_MODE
);
884 if (!strcmp(word
, "buffer")) {
885 criterion
[0].capability
= BUFFER_SIZE
;
886 if (comparator
== NONE
) {
887 criterion
[0].comparison
= GTE
;
888 criterion
[0].value
= 1;
890 criterion
[0].comparison
= comparator
;
891 criterion
[0].value
= value
;
897 if (!strcmp(word
, "conformant")) {
898 criterion
[0].capability
= CONFORMANT
;
899 if (comparator
== NONE
) {
900 criterion
[0].comparison
= EQ
;
901 criterion
[0].value
= 1;
903 criterion
[0].comparison
= comparator
;
904 criterion
[0].value
= value
;
906 *mask
|= (1 << CONFORMANT
);
911 if (!strcmp(word
, "depth")) {
912 criterion
[0].capability
= DEPTH_SIZE
;
913 if (comparator
== NONE
) {
914 criterion
[0].comparison
= GTE
;
915 criterion
[0].value
= 12;
917 criterion
[0].comparison
= comparator
;
918 criterion
[0].value
= value
;
920 *mask
|= (1 << DEPTH_SIZE
);
923 if (!strcmp(word
, "double")) {
924 criterion
[0].capability
= DOUBLEBUFFER
;
925 if (comparator
== NONE
) {
926 criterion
[0].comparison
= EQ
;
927 criterion
[0].value
= 1;
929 criterion
[0].comparison
= comparator
;
930 criterion
[0].value
= value
;
932 *mask
|= (1 << DOUBLEBUFFER
);
937 if (!strcmp(word
, "green")) {
938 criterion
[0].capability
= GREEN_SIZE
;
939 if (comparator
== NONE
) {
940 criterion
[0].comparison
= GTE
;
941 criterion
[0].value
= 1;
943 criterion
[0].comparison
= comparator
;
944 criterion
[0].value
= value
;
946 *mask
|= (1 << RGBA
);
947 *mask
|= (1 << RGBA_MODE
);
952 if (!strcmp(word
, "index")) {
953 criterion
[0].capability
= RGBA
;
954 criterion
[0].comparison
= EQ
;
955 criterion
[0].value
= 0;
956 *mask
|= (1 << RGBA
);
957 *mask
|= (1 << CI_MODE
);
958 criterion
[1].capability
= BUFFER_SIZE
;
959 if (comparator
== NONE
) {
960 criterion
[1].comparison
= GTE
;
961 criterion
[1].value
= 1;
963 criterion
[1].comparison
= comparator
;
964 criterion
[1].value
= value
;
970 if (!strcmp(word
, "luminance")) {
971 criterion
[0].capability
= RGBA
;
972 criterion
[0].comparison
= EQ
;
973 criterion
[0].value
= 1;
975 criterion
[1].capability
= RED_SIZE
;
976 if (comparator
== NONE
) {
977 criterion
[1].comparison
= GTE
;
978 criterion
[1].value
= 1;
980 criterion
[1].comparison
= comparator
;
981 criterion
[1].value
= value
;
984 criterion
[2].capability
= GREEN_SIZE
;
985 criterion
[2].comparison
= EQ
;
986 criterion
[2].value
= 0;
988 criterion
[3].capability
= BLUE_SIZE
;
989 criterion
[3].comparison
= EQ
;
990 criterion
[3].value
= 0;
992 *mask
|= (1 << RGBA
);
993 *mask
|= (1 << RGBA_MODE
);
994 *mask
|= (1 << LUMINANCE_MODE
);
999 if (!strcmp(word
, "num")) {
1000 criterion
[0].capability
= NUM
;
1001 if (comparator
== NONE
) {
1004 criterion
[0].comparison
= comparator
;
1005 criterion
[0].value
= value
;
1011 if (!strcmp(word
, "red")) {
1012 criterion
[0].capability
= RED_SIZE
;
1013 if (comparator
== NONE
) {
1014 criterion
[0].comparison
= GTE
;
1015 criterion
[0].value
= 1;
1017 criterion
[0].comparison
= comparator
;
1018 criterion
[0].value
= value
;
1020 *mask
|= (1 << RGBA
);
1021 *mask
|= (1 << RGBA_MODE
);
1024 rgba
= !strcmp(word
, "rgba");
1025 rgb
= !strcmp(word
, "rgb");
1027 criterion
[0].capability
= RGBA
;
1028 criterion
[0].comparison
= EQ
;
1029 criterion
[0].value
= 1;
1031 criterion
[1].capability
= RED_SIZE
;
1032 criterion
[2].capability
= GREEN_SIZE
;
1033 criterion
[3].capability
= BLUE_SIZE
;
1034 criterion
[4].capability
= ALPHA_SIZE
;
1039 criterion
[4].comparison
= MIN
;
1040 criterion
[4].value
= 0;
1042 if (comparator
== NONE
) {
1046 for (i
= 1; i
< count
; i
++) {
1047 criterion
[i
].comparison
= comparator
;
1048 criterion
[i
].value
= value
;
1050 *mask
|= (1 << RGBA
);
1051 *mask
|= (1 << RGBA_MODE
);
1056 if (!strcmp(word
, "stencil")) {
1057 criterion
[0].capability
= STENCIL_SIZE
;
1058 if (comparator
== NONE
) {
1059 criterion
[0].comparison
= MIN
;
1060 criterion
[0].value
= 1;
1062 criterion
[0].comparison
= comparator
;
1063 criterion
[0].value
= value
;
1065 *mask
|= (1 << STENCIL_SIZE
);
1068 if (!strcmp(word
, "single")) {
1069 criterion
[0].capability
= DOUBLEBUFFER
;
1070 if (comparator
== NONE
) {
1071 criterion
[0].comparison
= EQ
;
1072 criterion
[0].value
= 0;
1073 *allowDoubleAsSingle
= True
;
1074 *mask
|= (1 << DOUBLEBUFFER
);
1080 if (!strcmp(word
, "stereo")) {
1081 criterion
[0].capability
= STEREO
;
1082 if (comparator
== NONE
) {
1083 criterion
[0].comparison
= EQ
;
1084 criterion
[0].value
= 1;
1086 criterion
[0].comparison
= comparator
;
1087 criterion
[0].value
= value
;
1089 *mask
|= (1 << STEREO
);
1092 if (!strcmp(word
, "samples")) {
1093 criterion
[0].capability
= SAMPLES
;
1094 if (comparator
== NONE
) {
1095 criterion
[0].comparison
= LTE
;
1096 criterion
[0].value
= 4;
1098 criterion
[0].comparison
= comparator
;
1099 criterion
[0].value
= value
;
1101 *mask
|= (1 << SAMPLES
);
1104 if (!strcmp(word
, "slow")) {
1105 criterion
[0].capability
= SLOW
;
1106 if (comparator
== NONE
) {
1107 /* Just "slow" means permit fast visuals, but accept
1108 slow ones in preference. Presumably the slow ones
1109 must be higher quality or something else desirable. */
1110 criterion
[0].comparison
= GTE
;
1111 criterion
[0].value
= 0;
1113 criterion
[0].comparison
= comparator
;
1114 criterion
[0].value
= value
;
1116 *mask
|= (1 << SLOW
);
1122 if (!strcmp(word
, "win32pfd")) {
1123 criterion
[0].capability
= XVISUAL
;
1124 if (comparator
== NONE
) {
1127 criterion
[0].comparison
= comparator
;
1128 criterion
[0].value
= value
;
1134 #if !defined(_WIN32)
1136 if (!strcmp(word
, "xvisual")) {
1137 if (comparator
== NONE
) {
1140 criterion
[0].capability
= XVISUAL
;
1141 criterion
[0].comparison
= comparator
;
1142 criterion
[0].value
= value
;
1143 /* Set everything in "mask" so that no default criteria
1144 get used. Assume the program really wants the
1145 xvisual specified. */
1150 /* Be a little over-eager to fill in the comparison and
1151 value so we won't have to replicate the code after each
1153 if (comparator
== NONE
) {
1154 criterion
[0].comparison
= EQ
;
1155 criterion
[0].value
= 1;
1157 criterion
[0].comparison
= comparator
;
1158 criterion
[0].value
= value
;
1161 if (!strcmp(word
, "xstaticgray")) {
1162 criterion
[0].capability
= XSTATICGRAY
;
1163 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1167 if (!strcmp(word
, "xgrayscale")) {
1168 criterion
[0].capability
= XGRAYSCALE
;
1169 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1173 if (!strcmp(word
, "xstaticcolor")) {
1174 criterion
[0].capability
= XSTATICCOLOR
;
1175 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1179 if (!strcmp(word
, "xpseudocolor")) {
1180 criterion
[0].capability
= XPSEUDOCOLOR
;
1181 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1185 if (!strcmp(word
, "xtruecolor")) {
1186 criterion
[0].capability
= XTRUECOLOR
;
1187 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1191 if (!strcmp(word
, "xdirectcolor")) {
1192 criterion
[0].capability
= XDIRECTCOLOR
;
1193 *mask
|= (1 << XSTATICGRAY
); /* Indicates _any_ visual
1205 parseModeString(char *mode
, int *ncriteria
, Bool
* allowDoubleAsSingle
,
1206 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
)
1208 Criterion
*criteria
= NULL
;
1209 int n
, mask
, parsed
, i
;
1212 *allowDoubleAsSingle
= False
;
1213 copy
= __glutStrdup(mode
);
1214 /* Attempt to estimate how many criteria entries should be
1217 word
= strtok(copy
, " \t");
1220 word
= strtok(NULL
, " \t");
1222 /* Overestimate by 4 times ("rgba" might add four criteria
1223 entries) plus add in possible defaults plus space for
1224 required criteria. */
1225 criteria
= (Criterion
*) malloc((4 * n
+ 30 + nRequired
) * sizeof(Criterion
));
1227 __glutFatalError("out of memory.");
1230 /* Re-copy the copy of the mode string. */
1233 /* First add the required criteria (these match at the
1234 highest priority). Typically these will be used to force a
1235 specific level (layer), transparency, and/or visual type. */
1236 mask
= requiredMask
;
1237 for (i
= 0; i
< nRequired
; i
++) {
1238 criteria
[i
] = requiredCriteria
[i
];
1242 word
= strtok(copy
, " \t");
1244 parsed
= parseCriteria(word
, &criteria
[n
], &mask
, allowDoubleAsSingle
);
1248 __glutWarning("Unrecognized display string word: %s (ignoring)\n", word
);
1250 word
= strtok(NULL
, " \t");
1253 #if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
1254 if (__glutIsSupportedByGLX("GLX_SGIS_multisample")) {
1255 if (!(mask
& (1 << SAMPLES
))) {
1256 criteria
[n
].capability
= SAMPLES
;
1257 criteria
[n
].comparison
= EQ
;
1258 criteria
[n
].value
= 0;
1261 /* Multisample visuals are marked nonconformant. If
1262 multisampling was requeste and no conformant
1263 preference was set, assume that we will settle for a
1264 non-conformant visual to get multisampling. */
1265 if (!(mask
& (1 << CONFORMANT
))) {
1266 criteria
[n
].capability
= CONFORMANT
;
1267 criteria
[n
].comparison
= MIN
;
1268 criteria
[n
].value
= 0;
1270 mask
|= (1 << CONFORMANT
);
1275 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
1276 if (__glutIsSupportedByGLX("GLX_EXT_visual_info")) {
1277 if (!(mask
& (1 << TRANSPARENT
))) {
1278 criteria
[n
].capability
= TRANSPARENT
;
1279 criteria
[n
].comparison
= EQ
;
1280 criteria
[n
].value
= 0;
1285 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_rating)
1286 if (__glutIsSupportedByGLX("GLX_EXT_visual_rating")) {
1287 if (!(mask
& (1 << SLOW
))) {
1288 criteria
[n
].capability
= SLOW
;
1289 criteria
[n
].comparison
= EQ
;
1290 criteria
[n
].value
= 0;
1293 if (!(mask
& (1 << CONFORMANT
))) {
1294 criteria
[n
].capability
= CONFORMANT
;
1295 criteria
[n
].comparison
= EQ
;
1296 criteria
[n
].value
= 1;
1301 if (!(mask
& (1 << ACCUM_RED_SIZE
))) {
1302 criteria
[n
].capability
= ACCUM_RED_SIZE
;
1303 criteria
[n
].comparison
= MIN
;
1304 criteria
[n
].value
= 0;
1305 criteria
[n
+ 1].capability
= ACCUM_GREEN_SIZE
;
1306 criteria
[n
+ 1].comparison
= MIN
;
1307 criteria
[n
+ 1].value
= 0;
1308 criteria
[n
+ 2].capability
= ACCUM_BLUE_SIZE
;
1309 criteria
[n
+ 2].comparison
= MIN
;
1310 criteria
[n
+ 2].value
= 0;
1311 criteria
[n
+ 3].capability
= ACCUM_ALPHA_SIZE
;
1312 criteria
[n
+ 3].comparison
= MIN
;
1313 criteria
[n
+ 3].value
= 0;
1316 if (!(mask
& (1 << AUX_BUFFERS
))) {
1317 criteria
[n
].capability
= AUX_BUFFERS
;
1318 criteria
[n
].comparison
= MIN
;
1319 criteria
[n
].value
= 0;
1322 if (!(mask
& (1 << RGBA
))) {
1323 criteria
[n
].capability
= RGBA
;
1324 criteria
[n
].comparison
= EQ
;
1325 criteria
[n
].value
= 1;
1326 criteria
[n
+ 1].capability
= RED_SIZE
;
1327 criteria
[n
+ 1].comparison
= GTE
;
1328 criteria
[n
+ 1].value
= 1;
1329 criteria
[n
+ 2].capability
= GREEN_SIZE
;
1330 criteria
[n
+ 2].comparison
= GTE
;
1331 criteria
[n
+ 2].value
= 1;
1332 criteria
[n
+ 3].capability
= BLUE_SIZE
;
1333 criteria
[n
+ 3].comparison
= GTE
;
1334 criteria
[n
+ 3].value
= 1;
1335 criteria
[n
+ 4].capability
= ALPHA_SIZE
;
1336 criteria
[n
+ 4].comparison
= MIN
;
1337 criteria
[n
+ 4].value
= 0;
1339 mask
|= (1 << RGBA_MODE
);
1341 #if !defined(_WIN32)
1342 if (!(mask
& (1 << XSTATICGRAY
))) {
1343 assert(isMesaGLX
!= -1);
1344 if ((mask
& (1 << RGBA_MODE
)) && !isMesaGLX
) {
1345 /* Normally, request an RGBA mode visual be TrueColor,
1346 except in the case of Mesa where we trust Mesa (and
1347 other code in GLUT) to handle any type of RGBA visual
1349 if (mask
& (1 << LUMINANCE_MODE
)) {
1350 /* If RGBA luminance was requested, actually go for
1351 a StaticGray visual. */
1352 criteria
[n
].capability
= XSTATICGRAY
;
1354 criteria
[n
].capability
= XTRUECOLOR
;
1356 criteria
[n
].value
= 1;
1357 criteria
[n
].comparison
= EQ
;
1361 if (mask
& (1 << CI_MODE
)) {
1362 criteria
[n
].capability
= XPSEUDOCOLOR
;
1363 criteria
[n
].value
= 1;
1364 criteria
[n
].comparison
= EQ
;
1369 if (!(mask
& (1 << STEREO
))) {
1370 criteria
[n
].capability
= STEREO
;
1371 criteria
[n
].comparison
= EQ
;
1372 criteria
[n
].value
= 0;
1375 if (!(mask
& (1 << DOUBLEBUFFER
))) {
1376 criteria
[n
].capability
= DOUBLEBUFFER
;
1377 criteria
[n
].comparison
= EQ
;
1378 criteria
[n
].value
= 0;
1379 *allowDoubleAsSingle
= True
;
1382 if (!(mask
& (1 << DEPTH_SIZE
))) {
1383 criteria
[n
].capability
= DEPTH_SIZE
;
1384 criteria
[n
].comparison
= MIN
;
1385 criteria
[n
].value
= 0;
1388 if (!(mask
& (1 << STENCIL_SIZE
))) {
1389 criteria
[n
].capability
= STENCIL_SIZE
;
1390 criteria
[n
].comparison
= MIN
;
1391 criteria
[n
].value
= 0;
1394 if (!(mask
& (1 << LEVEL
))) {
1395 criteria
[n
].capability
= LEVEL
;
1396 criteria
[n
].comparison
= EQ
;
1397 criteria
[n
].value
= 0;
1401 /* Since over-estimated the size needed; squeeze it down to
1403 criteria
= (Criterion
*) realloc(criteria
, n
* sizeof(Criterion
));
1405 /* Should never happen since should be shrinking down! */
1406 __glutFatalError("out of memory.");
1409 /* For portability, avoid "realloc(ptr,0)" call. */
1419 static FrameBufferMode
*fbmodes
= NULL
;
1420 static int nfbmodes
= 0;
1422 static XVisualInfo
*
1423 getVisualInfoFromString(char *string
, Bool
* treatAsSingle
,
1424 Criterion
* requiredCriteria
, int nRequired
, int requiredMask
, void **fbc
)
1426 Criterion
*criteria
;
1427 XVisualInfo
*visinfo
;
1428 Bool allowDoubleAsSingle
;
1432 fbmodes
= loadVisuals(&nfbmodes
);
1434 criteria
= parseModeString(string
, &ncriteria
,
1435 &allowDoubleAsSingle
, requiredCriteria
, nRequired
, requiredMask
);
1436 if (criteria
== NULL
) {
1437 __glutWarning("failed to parse mode string");
1441 printCriteria(criteria
, ncriteria
);
1443 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
1447 if (allowDoubleAsSingle
) {
1448 /* Rewrite criteria so that we now look for a double
1449 buffered visual which will then get treated as a
1450 single buffered visual. */
1451 for (i
= 0; i
< ncriteria
; i
++) {
1452 if (criteria
[i
].capability
== DOUBLEBUFFER
1453 && criteria
[i
].comparison
== EQ
1454 && criteria
[i
].value
== 0) {
1455 criteria
[i
].value
= 1;
1458 visinfo
= findMatch(fbmodes
, nfbmodes
, criteria
, ncriteria
, fbc
);
1468 /* We could have a valid pixel format for drawing to a
1469 bitmap. However, we don't want to draw into a bitmap, we
1470 need one that can be used with a window, so make sure
1471 that this is true. */
1472 if (!(visinfo
->dwFlags
& PFD_DRAW_TO_WINDOW
))
1483 glutInitDisplayString(const char *string
)
1486 XHDC
= GetDC(GetDesktopWindow());
1489 __glutDetermineVisualFromString
= getVisualInfoFromString
;
1490 if (__glutDisplayString
) {
1491 free(__glutDisplayString
);
1494 __glutDisplayString
= __glutStrdup(string
);
1495 if (!__glutDisplayString
)
1496 __glutFatalError("out of memory.");
1498 __glutDisplayString
= NULL
;
1505 Criterion requiredWindowCriteria
[] =
1508 {TRANSPARENT
, EQ
, 0}
1510 int numRequiredWindowCriteria
= sizeof(requiredWindowCriteria
) / sizeof(Criterion
);
1511 int requiredWindowCriteriaMask
= (1 << LEVEL
) | (1 << TRANSPARENT
);
1513 Criterion requiredOverlayCriteria
[] =
1516 {TRANSPARENT
, EQ
, 1},
1517 {XPSEUDOCOLOR
, EQ
, 1},
1519 {BUFFER_SIZE
, GTE
, 1}
1521 int numRequiredOverlayCriteria
= sizeof(requiredOverlayCriteria
) / sizeof(Criterion
);
1522 int requiredOverlayCriteriaMask
=
1523 (1 << LEVEL
) | (1 << TRANSPARENT
) | (1 << XSTATICGRAY
) | (1 << RGBA
) | (1 << CI_MODE
);
1526 main(int argc
, char **argv
)
1531 char *str
, buffer
[1024];
1532 int tty
= isatty(fileno(stdin
));
1533 int overlay
= 0, showconfig
= 0;
1536 #if !defined(_WIN32)
1537 dpy
= XOpenDisplay(NULL
);
1539 printf("Could not connect to X server\n");
1542 __glutDisplay
= dpy
;
1543 __glutScreen
= DefaultScreen(__glutDisplay
);
1545 while (!feof(stdin
)) {
1548 str
= fgets(buffer
, 1023, stdin
);
1551 if (!strcmp("v", str
)) {
1552 verbose
= 1 - verbose
;
1553 printf("verbose = %d\n\n", verbose
);
1554 } else if (!strcmp("s", str
)) {
1555 showconfig
= 1 - showconfig
;
1556 printf("showconfig = %d\n\n", showconfig
);
1557 } else if (!strcmp("o", str
)) {
1558 overlay
= 1 - overlay
;
1559 printf("overlay = %d\n\n", overlay
);
1562 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1563 requiredOverlayCriteria
, numRequiredOverlayCriteria
, requiredOverlayCriteriaMask
, &fbc
);
1565 vinfo
= getVisualInfoFromString(str
, &treatAsSingle
,
1566 requiredWindowCriteria
, numRequiredWindowCriteria
, requiredWindowCriteriaMask
, &fbc
);
1571 printf("Display string: %s", str
);
1573 printf("Visual = 0x%x\n", 0);
1575 printf("Visual = 0x%x%s\n", vinfo
->visualid
, fbc
? " (needs FBC)" : "");
1577 if (treatAsSingle
) {
1578 printf("Treat as SINGLE.\n");
1581 int glxCapable
, bufferSize
, level
, renderType
, doubleBuffer
,
1582 stereo
, auxBuffers
, redSize
, greenSize
, blueSize
,
1583 alphaSize
, depthSize
, stencilSize
, acRedSize
, acGreenSize
,
1584 acBlueSize
, acAlphaSize
;
1586 glXGetConfig(dpy
, vinfo
, GLX_BUFFER_SIZE
, &bufferSize
);
1587 glXGetConfig(dpy
, vinfo
, GLX_LEVEL
, &level
);
1588 glXGetConfig(dpy
, vinfo
, GLX_RGBA
, &renderType
);
1589 glXGetConfig(dpy
, vinfo
, GLX_DOUBLEBUFFER
, &doubleBuffer
);
1590 glXGetConfig(dpy
, vinfo
, GLX_STEREO
, &stereo
);
1591 glXGetConfig(dpy
, vinfo
, GLX_AUX_BUFFERS
, &auxBuffers
);
1592 glXGetConfig(dpy
, vinfo
, GLX_RED_SIZE
, &redSize
);
1593 glXGetConfig(dpy
, vinfo
, GLX_GREEN_SIZE
, &greenSize
);
1594 glXGetConfig(dpy
, vinfo
, GLX_BLUE_SIZE
, &blueSize
);
1595 glXGetConfig(dpy
, vinfo
, GLX_ALPHA_SIZE
, &alphaSize
);
1596 glXGetConfig(dpy
, vinfo
, GLX_DEPTH_SIZE
, &depthSize
);
1597 glXGetConfig(dpy
, vinfo
, GLX_STENCIL_SIZE
, &stencilSize
);
1598 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_RED_SIZE
, &acRedSize
);
1599 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_GREEN_SIZE
, &acGreenSize
);
1600 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_BLUE_SIZE
, &acBlueSize
);
1601 glXGetConfig(dpy
, vinfo
, GLX_ACCUM_ALPHA_SIZE
, &acAlphaSize
);
1602 printf("RGBA = (%d, %d, %d, %d)\n", redSize
, greenSize
, blueSize
, alphaSize
);
1603 printf("acc = (%d, %d, %d, %d)\n", acRedSize
, acGreenSize
, acBlueSize
, acAlphaSize
);
1604 printf("db = %d\n", doubleBuffer
);
1605 printf("str = %d\n", stereo
);
1606 printf("aux = %d\n", auxBuffers
);
1607 printf("lvl = %d\n", level
);
1608 printf("buf = %d\n", bufferSize
);
1609 printf("rgba = %d\n", renderType
);
1610 printf("z = %d\n", depthSize
);
1611 printf("s = %d\n", stencilSize
);
1615 printf("No match.\n");