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