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");