glxinfo.c revision 7ec3b29a
1/* 2 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22 23/* 24 * This program is a work-alike of the IRIX glxinfo program. 25 * Command line options: 26 * -t print wide table 27 * -v print verbose information 28 * -display DisplayName specify the X display to interogate 29 * -B brief, print only the basics 30 * -b only print ID of "best" visual on screen 0 31 * -i use indirect rendering connection only 32 * -l print interesting OpenGL limits (added 5 Sep 2002) 33 * 34 * Brian Paul 26 January 2000 35 */ 36 37#define GLX_GLXEXT_PROTOTYPES 38#define GL_GLEXT_PROTOTYPES 39 40#include <assert.h> 41#include <X11/Xlib.h> 42#include <X11/Xutil.h> 43#include <GL/gl.h> 44#include <GL/glx.h> 45#include <stdio.h> 46#include <string.h> 47#include <stdlib.h> 48#include "glinfo_common.h" 49 50 51#ifndef GLX_NONE_EXT 52#define GLX_NONE_EXT 0x8000 53#endif 54 55#ifndef GLX_TRANSPARENT_RGB 56#define GLX_TRANSPARENT_RGB 0x8008 57#endif 58 59#ifndef GLX_RGBA_BIT 60#define GLX_RGBA_BIT 0x00000001 61#endif 62 63#ifndef GLX_COLOR_INDEX_BIT 64#define GLX_COLOR_INDEX_BIT 0x00000002 65#endif 66 67 68struct visual_attribs 69{ 70 /* X visual attribs */ 71 int id; /* May be visual ID or FBConfig ID */ 72 int vis_id; /* Visual ID. Only set for FBConfigs */ 73 int klass; 74 int depth; 75 int redMask, greenMask, blueMask; 76 int colormapSize; 77 int bitsPerRGB; 78 79 /* GL visual attribs */ 80 int supportsGL; 81 int drawableType; 82 int transparentType; 83 int transparentRedValue; 84 int transparentGreenValue; 85 int transparentBlueValue; 86 int transparentAlphaValue; 87 int transparentIndexValue; 88 int bufferSize; 89 int level; 90 int render_type; 91 int doubleBuffer; 92 int stereo; 93 int auxBuffers; 94 int redSize, greenSize, blueSize, alphaSize; 95 int depthSize; 96 int stencilSize; 97 int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize; 98 int numSamples, numMultisample; 99 int visualCaveat; 100 int floatComponents; 101 int packedfloatComponents; 102 int srgb; 103}; 104 105 106/** 107 * Version of the context that was created 108 * 109 * 20, 21, 30, 31, 32, etc. 110 */ 111static int version; 112 113/** 114 * GL Error checking/warning. 115 */ 116static void 117CheckError(int line) 118{ 119 int n; 120 n = glGetError(); 121 if (n) 122 printf("Warning: GL error 0x%x at line %d\n", n, line); 123} 124 125 126static void 127print_display_info(Display *dpy) 128{ 129 printf("name of display: %s\n", DisplayString(dpy)); 130} 131 132 133/** 134 * Choose a simple FB Config. 135 */ 136static GLXFBConfig * 137choose_fb_config(Display *dpy, int scrnum) 138{ 139 int fbAttribSingle[] = { 140 GLX_RENDER_TYPE, GLX_RGBA_BIT, 141 GLX_RED_SIZE, 1, 142 GLX_GREEN_SIZE, 1, 143 GLX_BLUE_SIZE, 1, 144 GLX_DOUBLEBUFFER, False, 145 None }; 146 int fbAttribDouble[] = { 147 GLX_RENDER_TYPE, GLX_RGBA_BIT, 148 GLX_RED_SIZE, 1, 149 GLX_GREEN_SIZE, 1, 150 GLX_BLUE_SIZE, 1, 151 GLX_DOUBLEBUFFER, True, 152 None }; 153 GLXFBConfig *configs; 154 int nConfigs; 155 156 configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs); 157 if (!configs) 158 configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs); 159 160 return configs; 161} 162 163 164static Bool CreateContextErrorFlag; 165 166static int 167create_context_error_handler(Display *dpy, XErrorEvent *error) 168{ 169 (void) dpy; 170 (void) error->error_code; 171 CreateContextErrorFlag = True; 172 return 0; 173} 174 175 176/** 177 * Try to create a GLX context of the given version with flags/options. 178 * Note: A version number is required in order to get a core profile 179 * (at least w/ NVIDIA). 180 */ 181static GLXContext 182create_context_flags(Display *dpy, GLXFBConfig fbconfig, int major, int minor, 183 int contextFlags, int profileMask, Bool direct) 184{ 185#ifdef GLX_ARB_create_context 186 static PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_func = 0; 187 static Bool firstCall = True; 188 int (*old_handler)(Display *, XErrorEvent *); 189 GLXContext context; 190 int attribs[20]; 191 int n = 0; 192 193 if (firstCall) { 194 /* See if we have GLX_ARB_create_context_profile and get pointer to 195 * glXCreateContextAttribsARB() function. 196 */ 197 const char *glxExt = glXQueryExtensionsString(dpy, 0); 198 if (extension_supported("GLX_ARB_create_context_profile", glxExt)) { 199 glXCreateContextAttribsARB_func = (PFNGLXCREATECONTEXTATTRIBSARBPROC) 200 glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB"); 201 } 202 firstCall = False; 203 } 204 205 if (!glXCreateContextAttribsARB_func) 206 return 0; 207 208 /* setup attribute array */ 209 if (major) { 210 attribs[n++] = GLX_CONTEXT_MAJOR_VERSION_ARB; 211 attribs[n++] = major; 212 attribs[n++] = GLX_CONTEXT_MINOR_VERSION_ARB; 213 attribs[n++] = minor; 214 } 215 if (contextFlags) { 216 attribs[n++] = GLX_CONTEXT_FLAGS_ARB; 217 attribs[n++] = contextFlags; 218 } 219#ifdef GLX_ARB_create_context_profile 220 if (profileMask) { 221 attribs[n++] = GLX_CONTEXT_PROFILE_MASK_ARB; 222 attribs[n++] = profileMask; 223 } 224#endif 225 attribs[n++] = 0; 226 227 /* install X error handler */ 228 old_handler = XSetErrorHandler(create_context_error_handler); 229 CreateContextErrorFlag = False; 230 231 /* try creating context */ 232 context = glXCreateContextAttribsARB_func(dpy, 233 fbconfig, 234 0, /* share_context */ 235 direct, 236 attribs); 237 238 /* restore error handler */ 239 XSetErrorHandler(old_handler); 240 241 if (CreateContextErrorFlag) 242 context = 0; 243 244 if (context && direct) { 245 if (!glXIsDirect(dpy, context)) { 246 glXDestroyContext(dpy, context); 247 return 0; 248 } 249 } 250 251 return context; 252#else 253 return 0; 254#endif 255} 256 257 258/** 259 * Try to create a GLX context of the newest version. 260 */ 261static GLXContext 262create_context_with_config(Display *dpy, GLXFBConfig config, 263 Bool coreProfile, Bool es2Profile, Bool direct) 264{ 265 GLXContext ctx = 0; 266 267 if (coreProfile) { 268 /* Try to create a core profile, starting with the newest version of 269 * GL that we're aware of. If we don't specify the version 270 */ 271 int i; 272 for (i = 0; gl_versions[i].major > 0; i++) { 273 /* don't bother below GL 3.0 */ 274 if (gl_versions[i].major == 3 && 275 gl_versions[i].minor == 0) 276 return 0; 277 ctx = create_context_flags(dpy, config, 278 gl_versions[i].major, 279 gl_versions[i].minor, 280 0x0, 281 GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 282 direct); 283 if (ctx) 284 return ctx; 285 } 286 /* couldn't get core profile context */ 287 return 0; 288 } 289 290 if (es2Profile) { 291#ifdef GLX_CONTEXT_ES2_PROFILE_BIT_EXT 292 if (extension_supported("GLX_EXT_create_context_es2_profile", 293 glXQueryExtensionsString(dpy, 0))) { 294 ctx = create_context_flags(dpy, config, 2, 0, 0x0, 295 GLX_CONTEXT_ES2_PROFILE_BIT_EXT, 296 direct); 297 return ctx; 298 } 299#endif 300 return 0; 301 } 302 303 /* GLX should return a context of the latest GL version that supports 304 * the full profile. 305 */ 306 ctx = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, direct); 307 308 /* make sure the context is direct, if direct was requested */ 309 if (ctx && direct) { 310 if (!glXIsDirect(dpy, ctx)) { 311 glXDestroyContext(dpy, ctx); 312 return 0; 313 } 314 } 315 316 return ctx; 317} 318 319 320static XVisualInfo * 321choose_xvisinfo(Display *dpy, int scrnum) 322{ 323 int attribSingle[] = { 324 GLX_RGBA, 325 GLX_RED_SIZE, 1, 326 GLX_GREEN_SIZE, 1, 327 GLX_BLUE_SIZE, 1, 328 None }; 329 int attribDouble[] = { 330 GLX_RGBA, 331 GLX_RED_SIZE, 1, 332 GLX_GREEN_SIZE, 1, 333 GLX_BLUE_SIZE, 1, 334 GLX_DOUBLEBUFFER, 335 None }; 336 XVisualInfo *visinfo; 337 338 visinfo = glXChooseVisual(dpy, scrnum, attribSingle); 339 if (!visinfo) 340 visinfo = glXChooseVisual(dpy, scrnum, attribDouble); 341 342 return visinfo; 343} 344 345 346static void 347query_renderer(void) 348{ 349#ifdef GLX_MESA_query_renderer 350 PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger; 351 PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC queryString; 352 unsigned int v[3]; 353 354 queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) 355 glXGetProcAddressARB((const GLubyte *) 356 "glXQueryCurrentRendererIntegerMESA"); 357 queryString = (PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) 358 glXGetProcAddressARB((const GLubyte *) 359 "glXQueryCurrentRendererStringMESA"); 360 361 printf("Extended renderer info (GLX_MESA_query_renderer):\n"); 362 queryInteger(GLX_RENDERER_VENDOR_ID_MESA, v); 363 printf(" Vendor: %s (0x%x)\n", 364 queryString(GLX_RENDERER_VENDOR_ID_MESA), *v); 365 queryInteger(GLX_RENDERER_DEVICE_ID_MESA, v); 366 printf(" Device: %s (0x%x)\n", 367 queryString(GLX_RENDERER_DEVICE_ID_MESA), *v); 368 queryInteger(GLX_RENDERER_VERSION_MESA, v); 369 printf(" Version: %d.%d.%d\n", v[0], v[1], v[2]); 370 queryInteger(GLX_RENDERER_ACCELERATED_MESA, v); 371 printf(" Accelerated: %s\n", *v ? "yes" : "no"); 372 queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, v); 373 printf(" Video memory: %dMB\n", *v); 374 queryInteger(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA, v); 375 printf(" Unified memory: %s\n", *v ? "yes" : "no"); 376 queryInteger(GLX_RENDERER_PREFERRED_PROFILE_MESA, v); 377 printf(" Preferred profile: %s (0x%x)\n", 378 *v == GLX_CONTEXT_CORE_PROFILE_BIT_ARB ? "core" : 379 *v == GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ? "compat" : 380 "unknown", *v); 381 queryInteger(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA, v); 382 printf(" Max core profile version: %d.%d\n", v[0], v[1]); 383 queryInteger(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA, v); 384 printf(" Max compat profile version: %d.%d\n", v[0], v[1]); 385 queryInteger(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA, v); 386 printf(" Max GLES1 profile version: %d.%d\n", v[0], v[1]); 387 queryInteger(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA, v); 388 printf(" Max GLES[23] profile version: %d.%d\n", v[0], v[1]); 389#endif 390} 391 392 393static Bool 394print_screen_info(Display *dpy, int scrnum, 395 const struct options *opts, 396 Bool coreProfile, Bool es2Profile, Bool limits, 397 Bool coreWorked) 398{ 399 Window win; 400 XSetWindowAttributes attr; 401 unsigned long mask; 402 Window root; 403 GLXContext ctx = NULL; 404 XVisualInfo *visinfo; 405 int width = 100, height = 100; 406 GLXFBConfig *fbconfigs; 407 const char *oglstring = coreProfile ? "OpenGL core profile" : 408 es2Profile ? "OpenGL ES profile" : "OpenGL"; 409 410 root = RootWindow(dpy, scrnum); 411 412 /* 413 * Choose FBConfig or XVisualInfo and create a context. 414 */ 415 fbconfigs = choose_fb_config(dpy, scrnum); 416 if (fbconfigs) { 417 ctx = create_context_with_config(dpy, fbconfigs[0], 418 coreProfile, es2Profile, 419 opts->allowDirect); 420 if (!ctx && opts->allowDirect && !coreProfile) { 421 /* try indirect */ 422 ctx = create_context_with_config(dpy, fbconfigs[0], 423 coreProfile, es2Profile, False); 424 } 425 426 visinfo = glXGetVisualFromFBConfig(dpy, fbconfigs[0]); 427 XFree(fbconfigs); 428 } 429 else if (!coreProfile && !es2Profile) { 430 visinfo = choose_xvisinfo(dpy, scrnum); 431 if (visinfo) 432 ctx = glXCreateContext(dpy, visinfo, NULL, opts->allowDirect); 433 } else 434 visinfo = NULL; 435 436 if (!visinfo && !coreProfile && !es2Profile) { 437 fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n"); 438 return False; 439 } 440 441 if (!ctx) { 442 if (!coreProfile && !es2Profile) 443 fprintf(stderr, "Error: glXCreateContext failed\n"); 444 XFree(visinfo); 445 return False; 446 } 447 448 /* 449 * Create a window so that we can just bind the context. 450 */ 451 attr.background_pixel = 0; 452 attr.border_pixel = 0; 453 attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); 454 attr.event_mask = StructureNotifyMask | ExposureMask; 455 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 456 win = XCreateWindow(dpy, root, 0, 0, width, height, 457 0, visinfo->depth, InputOutput, 458 visinfo->visual, mask, &attr); 459 460 if (glXMakeCurrent(dpy, win, ctx)) { 461 const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR); 462 const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION); 463 const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS); 464 const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR); 465 const char *clientVersion = glXGetClientString(dpy, GLX_VERSION); 466 const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS); 467 const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum); 468 const char *glVendor = (const char *) glGetString(GL_VENDOR); 469 const char *glRenderer = (const char *) glGetString(GL_RENDERER); 470 const char *glVersion = (const char *) glGetString(GL_VERSION); 471 char *glExtensions = NULL; 472 int glxVersionMajor = 0; 473 int glxVersionMinor = 0; 474 char *displayName = NULL; 475 char *colon = NULL, *period = NULL; 476 struct ext_functions extfuncs; 477 478 CheckError(__LINE__); 479 480 /* Get some ext functions */ 481 extfuncs.GetProgramivARB = (GETPROGRAMIVARBPROC) 482 glXGetProcAddressARB((GLubyte *) "glGetProgramivARB"); 483 extfuncs.GetStringi = (GETSTRINGIPROC) 484 glXGetProcAddressARB((GLubyte *) "glGetStringi"); 485 extfuncs.GetConvolutionParameteriv = (GETCONVOLUTIONPARAMETERIVPROC) 486 glXGetProcAddressARB((GLubyte *) "glGetConvolutionParameteriv"); 487 488 if (!glXQueryVersion(dpy, & glxVersionMajor, & glxVersionMinor)) { 489 fprintf(stderr, "Error: glXQueryVersion failed\n"); 490 exit(1); 491 } 492 493 /* Get list of GL extensions */ 494 if (coreProfile && extfuncs.GetStringi) 495 glExtensions = build_core_profile_extension_list(&extfuncs); 496 if (!glExtensions) { 497 coreProfile = False; 498 glExtensions = (char *) glGetString(GL_EXTENSIONS); 499 } 500 501 CheckError(__LINE__); 502 503 if (!coreWorked) { 504 /* Strip the screen number from the display name, if present. */ 505 if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) { 506 fprintf(stderr, "Error: malloc() failed\n"); 507 exit(1); 508 } 509 strcpy(displayName, DisplayString(dpy)); 510 colon = strrchr(displayName, ':'); 511 if (colon) { 512 period = strchr(colon, '.'); 513 if (period) 514 *period = '\0'; 515 } 516 517 printf("display: %s screen: %d\n", displayName, scrnum); 518 free(displayName); 519 printf("direct rendering: "); 520 if (glXIsDirect(dpy, ctx)) { 521 printf("Yes\n"); 522 } 523 else { 524 if (!opts->allowDirect) { 525 printf("No (-i specified)\n"); 526 } 527 else if (getenv("LIBGL_ALWAYS_INDIRECT")) { 528 printf("No (LIBGL_ALWAYS_INDIRECT set)\n"); 529 } 530 else { 531 printf("No (If you want to find out why, try setting " 532 "LIBGL_DEBUG=verbose)\n"); 533 } 534 } 535 if (opts->mode != Brief) { 536 printf("server glx vendor string: %s\n", serverVendor); 537 printf("server glx version string: %s\n", serverVersion); 538 printf("server glx extensions:\n"); 539 print_extension_list(serverExtensions, opts->singleLine); 540 printf("client glx vendor string: %s\n", clientVendor); 541 printf("client glx version string: %s\n", clientVersion); 542 printf("client glx extensions:\n"); 543 print_extension_list(clientExtensions, opts->singleLine); 544 printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor); 545 printf("GLX extensions:\n"); 546 print_extension_list(glxExtensions, opts->singleLine); 547 } 548 if (strstr(glxExtensions, "GLX_MESA_query_renderer")) 549 query_renderer(); 550 print_gpu_memory_info(glExtensions); 551 printf("OpenGL vendor string: %s\n", glVendor); 552 printf("OpenGL renderer string: %s\n", glRenderer); 553 } else 554 printf("\n"); 555 556 printf("%s version string: %s\n", oglstring, glVersion); 557 558 version = (glVersion[0] - '0') * 10 + (glVersion[2] - '0'); 559 560 CheckError(__LINE__); 561 562#ifdef GL_VERSION_2_0 563 if (version >= 20) { 564 char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); 565 printf("%s shading language version string: %s\n", oglstring, v); 566 } 567#endif 568 CheckError(__LINE__); 569#ifdef GL_VERSION_3_0 570 if (version >= 30 && !es2Profile) { 571 GLint flags; 572 glGetIntegerv(GL_CONTEXT_FLAGS, &flags); 573 printf("%s context flags: %s\n", oglstring, context_flags_string(flags)); 574 } 575#endif 576 CheckError(__LINE__); 577#ifdef GL_VERSION_3_2 578 if (version >= 32 && !es2Profile) { 579 GLint mask; 580 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); 581 printf("%s profile mask: %s\n", oglstring, profile_mask_string(mask)); 582 } 583#endif 584 585 CheckError(__LINE__); 586 587 if (opts->mode != Brief) { 588 printf("%s extensions:\n", oglstring); 589 print_extension_list(glExtensions, opts->singleLine); 590 } 591 592 if (limits) { 593 print_limits(glExtensions, oglstring, version, &extfuncs); 594 } 595 596 if (coreProfile) 597 free(glExtensions); 598 } 599 else { 600 fprintf(stderr, "Error: glXMakeCurrent failed\n"); 601 } 602 603 glXDestroyContext(dpy, ctx); 604 XFree(visinfo); 605 XDestroyWindow(dpy, win); 606 XSync(dpy, 1); 607 return True; 608} 609 610 611static const char * 612visual_class_name(int cls) 613{ 614 switch (cls) { 615 case StaticColor: 616 return "StaticColor"; 617 case PseudoColor: 618 return "PseudoColor"; 619 case StaticGray: 620 return "StaticGray"; 621 case GrayScale: 622 return "GrayScale"; 623 case TrueColor: 624 return "TrueColor"; 625 case DirectColor: 626 return "DirectColor"; 627 default: 628 return ""; 629 } 630} 631 632static const char * 633visual_drawable_type(int type) 634{ 635 const static struct bit_info bits[] = { 636 { GLX_WINDOW_BIT, "window" }, 637 { GLX_PIXMAP_BIT, "pixmap" }, 638 { GLX_PBUFFER_BIT, "pbuffer" } 639 }; 640 641 return bitmask_to_string(bits, ELEMENTS(bits), type); 642} 643 644static const char * 645visual_class_abbrev(int cls) 646{ 647 switch (cls) { 648 case StaticColor: 649 return "sc"; 650 case PseudoColor: 651 return "pc"; 652 case StaticGray: 653 return "sg"; 654 case GrayScale: 655 return "gs"; 656 case TrueColor: 657 return "tc"; 658 case DirectColor: 659 return "dc"; 660 default: 661 return ""; 662 } 663} 664 665static const char * 666visual_render_type_name(int type) 667{ 668 switch (type) { 669 case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT: 670 return "ufloat"; 671 case GLX_RGBA_FLOAT_BIT_ARB: 672 return "float"; 673 case GLX_RGBA_BIT: 674 return "rgba"; 675 case GLX_COLOR_INDEX_BIT: 676 return "ci"; 677 case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT: 678 return "rgba|ci"; 679 default: 680 return ""; 681 } 682} 683 684static const char * 685caveat_string(int caveat) 686{ 687 switch (caveat) { 688#ifdef GLX_EXT_visual_rating 689 case GLX_SLOW_VISUAL_EXT: 690 return "Slow"; 691 case GLX_NON_CONFORMANT_VISUAL_EXT: 692 return "Ncon"; 693 case GLX_NONE_EXT: 694 /* fall-through */ 695#endif 696 case 0: 697 /* fall-through */ 698 default: 699 return "None"; 700 } 701} 702 703 704static Bool 705get_visual_attribs(Display *dpy, XVisualInfo *vInfo, 706 struct visual_attribs *attribs) 707{ 708 const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); 709 int rgba; 710 711 memset(attribs, 0, sizeof(struct visual_attribs)); 712 713 attribs->id = vInfo->visualid; 714#if defined(__cplusplus) || defined(c_plusplus) 715 attribs->klass = vInfo->c_class; 716#else 717 attribs->klass = vInfo->class; 718#endif 719 attribs->depth = vInfo->depth; 720 attribs->redMask = vInfo->red_mask; 721 attribs->greenMask = vInfo->green_mask; 722 attribs->blueMask = vInfo->blue_mask; 723 attribs->colormapSize = vInfo->colormap_size; 724 attribs->bitsPerRGB = vInfo->bits_per_rgb; 725 726 if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 || 727 !attribs->supportsGL) 728 return False; 729 glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize); 730 glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); 731 glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba); 732 if (rgba) 733 attribs->render_type = GLX_RGBA_BIT; 734 else 735 attribs->render_type = GLX_COLOR_INDEX_BIT; 736 737 glXGetConfig(dpy, vInfo, GLX_DRAWABLE_TYPE, &attribs->drawableType); 738 glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); 739 glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo); 740 glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); 741 glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize); 742 glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize); 743 glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize); 744 glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize); 745 glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize); 746 glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize); 747 glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); 748 glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); 749 glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); 750 glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); 751 752 /* get transparent pixel stuff */ 753 glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType); 754 if (attribs->transparentType == GLX_TRANSPARENT_RGB) { 755 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); 756 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); 757 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); 758 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); 759 } 760 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { 761 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); 762 } 763 764 /* multisample attribs */ 765#ifdef GLX_ARB_multisample 766 if (ext && strstr(ext, "GLX_ARB_multisample")) { 767 glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample); 768 glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples); 769 } 770#endif 771 else { 772 attribs->numSamples = 0; 773 attribs->numMultisample = 0; 774 } 775 776#if defined(GLX_EXT_visual_rating) 777 if (ext && strstr(ext, "GLX_EXT_visual_rating")) { 778 glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat); 779 } 780 else { 781 attribs->visualCaveat = GLX_NONE_EXT; 782 } 783#else 784 attribs->visualCaveat = 0; 785#endif 786 787#if defined(GLX_EXT_framebuffer_sRGB) 788 if (ext && strstr(ext, "GLX_EXT_framebuffer_sRGB")) { 789 glXGetConfig(dpy, vInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &attribs->srgb); 790 } 791#endif 792 793 return True; 794} 795 796#ifdef GLX_VERSION_1_3 797 798static int 799glx_token_to_visual_class(int visual_type) 800{ 801 switch (visual_type) { 802 case GLX_TRUE_COLOR: 803 return TrueColor; 804 case GLX_DIRECT_COLOR: 805 return DirectColor; 806 case GLX_PSEUDO_COLOR: 807 return PseudoColor; 808 case GLX_STATIC_COLOR: 809 return StaticColor; 810 case GLX_GRAY_SCALE: 811 return GrayScale; 812 case GLX_STATIC_GRAY: 813 return StaticGray; 814 case GLX_NONE: 815 default: 816 return None; 817 } 818} 819 820static Bool 821get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig, 822 struct visual_attribs *attribs) 823{ 824 const char *ext = glXQueryExtensionsString(dpy, 0); 825 int visual_type; 826 XVisualInfo *vInfo; 827 828 memset(attribs, 0, sizeof(struct visual_attribs)); 829 830 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id); 831 832 vInfo = glXGetVisualFromFBConfig(dpy, fbconfig); 833 834 if (vInfo != NULL) { 835 attribs->vis_id = vInfo->visualid; 836 attribs->depth = vInfo->depth; 837 attribs->redMask = vInfo->red_mask; 838 attribs->greenMask = vInfo->green_mask; 839 attribs->blueMask = vInfo->blue_mask; 840 attribs->colormapSize = vInfo->colormap_size; 841 attribs->bitsPerRGB = vInfo->bits_per_rgb; 842 } 843 844 glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type); 845 attribs->klass = glx_token_to_visual_class(visual_type); 846 847 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DRAWABLE_TYPE, &attribs->drawableType); 848 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize); 849 glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level); 850 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type); 851 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); 852 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo); 853 glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers); 854 855 glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize); 856 glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize); 857 glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize); 858 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize); 859 glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize); 860 glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize); 861 862 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); 863 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); 864 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); 865 glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); 866 867 /* get transparent pixel stuff */ 868 glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType); 869 if (attribs->transparentType == GLX_TRANSPARENT_RGB) { 870 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); 871 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); 872 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); 873 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); 874 } 875 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { 876 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); 877 } 878 879 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample); 880 glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples); 881 glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat); 882 883#if defined(GLX_NV_float_buffer) 884 if (ext && strstr(ext, "GLX_NV_float_buffer")) { 885 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FLOAT_COMPONENTS_NV, &attribs->floatComponents); 886 } 887#endif 888#if defined(GLX_ARB_fbconfig_float) 889 if (ext && strstr(ext, "GLX_ARB_fbconfig_float")) { 890 if (attribs->render_type & GLX_RGBA_FLOAT_BIT_ARB) { 891 attribs->floatComponents = True; 892 } 893 } 894#endif 895#if defined(GLX_EXT_fbconfig_packed_float) 896 if (ext && strstr(ext, "GLX_EXT_fbconfig_packed_float")) { 897 if (attribs->render_type & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { 898 attribs->packedfloatComponents = True; 899 } 900 } 901#endif 902 903#if defined(GLX_EXT_framebuffer_sRGB) 904 if (ext && strstr(ext, "GLX_EXT_framebuffer_sRGB")) { 905 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &attribs->srgb); 906 } 907#endif 908 return True; 909} 910 911#endif 912 913 914 915static void 916print_visual_attribs_verbose(const struct visual_attribs *attribs, 917 int fbconfigs) 918{ 919 if (fbconfigs) { 920 printf("FBConfig ID: %x Visual ID=%x depth=%d class=%s, type=%s\n", 921 attribs->id, attribs->vis_id, attribs->depth, 922 visual_class_name(attribs->klass), 923 visual_drawable_type(attribs->drawableType)); 924 } 925 else { 926 printf("Visual ID: %x depth=%d class=%s, type=%s\n", 927 attribs->id, attribs->depth, visual_class_name(attribs->klass), 928 visual_drawable_type(attribs->drawableType)); 929 } 930 printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", 931 attribs->bufferSize, attribs->level, 932 visual_render_type_name(attribs->render_type), 933 attribs->doubleBuffer, attribs->stereo); 934 printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d float=%c sRGB=%c\n", 935 attribs->redSize, attribs->greenSize, 936 attribs->blueSize, attribs->alphaSize, 937 attribs->packedfloatComponents ? 'P' : attribs->floatComponents ? 'Y' : 'N', 938 attribs->srgb ? 'Y' : 'N'); 939 printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n", 940 attribs->auxBuffers, attribs->depthSize, attribs->stencilSize); 941 printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", 942 attribs->accumRedSize, attribs->accumGreenSize, 943 attribs->accumBlueSize, attribs->accumAlphaSize); 944 printf(" multiSample=%d multiSampleBuffers=%d\n", 945 attribs->numSamples, attribs->numMultisample); 946#ifdef GLX_EXT_visual_rating 947 if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0) 948 printf(" visualCaveat=None\n"); 949 else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT) 950 printf(" visualCaveat=Slow\n"); 951 else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT) 952 printf(" visualCaveat=Nonconformant\n"); 953#endif 954 if (attribs->transparentType == GLX_NONE) { 955 printf(" Opaque.\n"); 956 } 957 else if (attribs->transparentType == GLX_TRANSPARENT_RGB) { 958 printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue); 959 } 960 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { 961 printf(" Transparent index=%d\n",attribs->transparentIndexValue); 962 } 963} 964 965 966static void 967print_visual_attribs_short_header(void) 968{ 969 printf(" visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav\n"); 970 printf(" id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat\n"); 971 printf("----------------------------------------------------------------------------\n"); 972} 973 974 975static void 976print_visual_attribs_short(const struct visual_attribs *attribs) 977{ 978 const char *caveat = caveat_string(attribs->visualCaveat); 979 980 printf("0x%03x %2d %2s %2d %3d %2d %c%c %c %c %2d %2d %2d %2d %c %c %2d %2d %2d", 981 attribs->id, 982 attribs->depth, 983 visual_class_abbrev(attribs->klass), 984 attribs->transparentType != GLX_NONE, 985 attribs->bufferSize, 986 attribs->level, 987 (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ', 988 (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ', 989 attribs->doubleBuffer ? 'y' : '.', 990 attribs->stereo ? 'y' : '.', 991 attribs->redSize, attribs->greenSize, 992 attribs->blueSize, attribs->alphaSize, 993 attribs->packedfloatComponents ? 'u' : attribs->floatComponents ? 'f' : '.', 994 attribs->srgb ? 's' : '.', 995 attribs->auxBuffers, 996 attribs->depthSize, 997 attribs->stencilSize 998 ); 999 1000 printf(" %2d %2d %2d %2d %2d %1d %s\n", 1001 attribs->accumRedSize, attribs->accumGreenSize, 1002 attribs->accumBlueSize, attribs->accumAlphaSize, 1003 attribs->numSamples, attribs->numMultisample, 1004 caveat 1005 ); 1006} 1007 1008 1009static void 1010print_visual_attribs_long_header(void) 1011{ 1012 printf("Vis Vis Visual Trans buff lev render DB ste r g b a s aux dep ste accum buffer MS MS \n"); 1013 printf(" ID Depth Type parent size el type reo sz sz sz sz flt rgb buf th ncl r g b a num bufs caveats\n"); 1014 printf("--------------------------------------------------------------------------------------------------------------------\n"); 1015} 1016 1017 1018static void 1019print_visual_attribs_long(const struct visual_attribs *attribs) 1020{ 1021 const char *caveat = caveat_string(attribs->visualCaveat); 1022 1023 printf("0x%3x %2d %-11s %2d %3d %2d %4s %3d %3d %3d %3d %3d %3d", 1024 attribs->id, 1025 attribs->depth, 1026 visual_class_name(attribs->klass), 1027 attribs->transparentType != GLX_NONE, 1028 attribs->bufferSize, 1029 attribs->level, 1030 visual_render_type_name(attribs->render_type), 1031 attribs->doubleBuffer, 1032 attribs->stereo, 1033 attribs->redSize, attribs->greenSize, 1034 attribs->blueSize, attribs->alphaSize 1035 ); 1036 1037 printf(" %c %c %3d %4d %2d %3d %3d %3d %3d %2d %2d %6s\n", 1038 attribs->floatComponents ? 'f' : '.', 1039 attribs->srgb ? 's' : '.', 1040 attribs->auxBuffers, 1041 attribs->depthSize, 1042 attribs->stencilSize, 1043 attribs->accumRedSize, attribs->accumGreenSize, 1044 attribs->accumBlueSize, attribs->accumAlphaSize, 1045 attribs->numSamples, attribs->numMultisample, 1046 caveat 1047 ); 1048} 1049 1050 1051static void 1052print_visual_info(Display *dpy, int scrnum, InfoMode mode) 1053{ 1054 XVisualInfo theTemplate; 1055 XVisualInfo *visuals; 1056 int numVisuals, numGlxVisuals; 1057 long mask; 1058 int i; 1059 struct visual_attribs attribs; 1060 1061 /* get list of all visuals on this screen */ 1062 theTemplate.screen = scrnum; 1063 mask = VisualScreenMask; 1064 visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals); 1065 1066 numGlxVisuals = 0; 1067 for (i = 0; i < numVisuals; i++) { 1068 if (get_visual_attribs(dpy, &visuals[i], &attribs)) 1069 numGlxVisuals++; 1070 } 1071 1072 if (numGlxVisuals == 0) 1073 return; 1074 1075 printf("%d GLX Visuals\n", numGlxVisuals); 1076 1077 if (mode == Normal) 1078 print_visual_attribs_short_header(); 1079 else if (mode == Wide) 1080 print_visual_attribs_long_header(); 1081 1082 for (i = 0; i < numVisuals; i++) { 1083 if (!get_visual_attribs(dpy, &visuals[i], &attribs)) 1084 continue; 1085 1086 if (mode == Verbose) 1087 print_visual_attribs_verbose(&attribs, False); 1088 else if (mode == Normal) 1089 print_visual_attribs_short(&attribs); 1090 else if (mode == Wide) 1091 print_visual_attribs_long(&attribs); 1092 } 1093 printf("\n"); 1094 1095 XFree(visuals); 1096} 1097 1098#ifdef GLX_VERSION_1_3 1099 1100static void 1101print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode) 1102{ 1103 int numFBConfigs = 0; 1104 struct visual_attribs attribs; 1105 GLXFBConfig *fbconfigs; 1106 int i; 1107 1108 /* get list of all fbconfigs on this screen */ 1109 fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs); 1110 1111 if (numFBConfigs == 0) { 1112 XFree(fbconfigs); 1113 return; 1114 } 1115 1116 printf("%d GLXFBConfigs:\n", numFBConfigs); 1117 if (mode == Normal) 1118 print_visual_attribs_short_header(); 1119 else if (mode == Wide) 1120 print_visual_attribs_long_header(); 1121 1122 for (i = 0; i < numFBConfigs; i++) { 1123 get_fbconfig_attribs(dpy, fbconfigs[i], &attribs); 1124 1125 if (mode == Verbose) 1126 print_visual_attribs_verbose(&attribs, True); 1127 else if (mode == Normal) 1128 print_visual_attribs_short(&attribs); 1129 else if (mode == Wide) 1130 print_visual_attribs_long(&attribs); 1131 } 1132 printf("\n"); 1133 1134 XFree(fbconfigs); 1135} 1136 1137#endif 1138 1139/* 1140 * Stand-alone Mesa doesn't really implement the GLX protocol so it 1141 * doesn't really know the GLX attributes associated with an X visual. 1142 * The first time a visual is presented to Mesa's pseudo-GLX it 1143 * attaches ancilliary buffers to it (like depth and stencil). 1144 * But that usually only works if glXChooseVisual is used. 1145 * This function calls glXChooseVisual() to sort of "prime the pump" 1146 * for Mesa's GLX so that the visuals that get reported actually 1147 * reflect what applications will see. 1148 * This has no effect when using true GLX. 1149 */ 1150static void 1151mesa_hack(Display *dpy, int scrnum) 1152{ 1153 static int attribs[] = { 1154 GLX_RGBA, 1155 GLX_RED_SIZE, 1, 1156 GLX_GREEN_SIZE, 1, 1157 GLX_BLUE_SIZE, 1, 1158 GLX_DEPTH_SIZE, 1, 1159 GLX_STENCIL_SIZE, 1, 1160 GLX_ACCUM_RED_SIZE, 1, 1161 GLX_ACCUM_GREEN_SIZE, 1, 1162 GLX_ACCUM_BLUE_SIZE, 1, 1163 GLX_ACCUM_ALPHA_SIZE, 1, 1164 GLX_DOUBLEBUFFER, 1165 None 1166 }; 1167 XVisualInfo *visinfo; 1168 1169 visinfo = glXChooseVisual(dpy, scrnum, attribs); 1170 if (visinfo) 1171 XFree(visinfo); 1172} 1173 1174 1175/* 1176 * Examine all visuals to find the so-called best one. 1177 * We prefer deepest RGBA buffer with depth, stencil and accum 1178 * that has no caveats. 1179 */ 1180static int 1181find_best_visual(Display *dpy, int scrnum) 1182{ 1183 XVisualInfo theTemplate; 1184 XVisualInfo *visuals; 1185 int numVisuals; 1186 long mask; 1187 int i; 1188 struct visual_attribs bestVis; 1189 1190 /* get list of all visuals on this screen */ 1191 theTemplate.screen = scrnum; 1192 mask = VisualScreenMask; 1193 visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals); 1194 1195 /* init bestVis with first visual info */ 1196 get_visual_attribs(dpy, &visuals[0], &bestVis); 1197 1198 /* try to find a "better" visual */ 1199 for (i = 1; i < numVisuals; i++) { 1200 struct visual_attribs vis; 1201 1202 get_visual_attribs(dpy, &visuals[i], &vis); 1203 1204 /* always skip visuals with caveats */ 1205 if (vis.visualCaveat != GLX_NONE_EXT) 1206 continue; 1207 1208 /* see if this vis is better than bestVis */ 1209 if ((!bestVis.supportsGL && vis.supportsGL) || 1210 (bestVis.visualCaveat != GLX_NONE_EXT) || 1211 (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) || 1212 (!bestVis.doubleBuffer && vis.doubleBuffer) || 1213 (bestVis.redSize < vis.redSize) || 1214 (bestVis.greenSize < vis.greenSize) || 1215 (bestVis.blueSize < vis.blueSize) || 1216 (bestVis.alphaSize < vis.alphaSize) || 1217 (bestVis.depthSize < vis.depthSize) || 1218 (bestVis.stencilSize < vis.stencilSize) || 1219 (bestVis.accumRedSize < vis.accumRedSize)) { 1220 /* found a better visual */ 1221 bestVis = vis; 1222 } 1223 } 1224 1225 XFree(visuals); 1226 1227 return bestVis.id; 1228} 1229 1230 1231int 1232main(int argc, char *argv[]) 1233{ 1234 Display *dpy; 1235 int numScreens, scrnum; 1236 struct options opts; 1237 Bool coreWorked; 1238 1239 parse_args(argc, argv, &opts); 1240 1241 dpy = XOpenDisplay(opts.displayName); 1242 if (!dpy) { 1243 fprintf(stderr, "Error: unable to open display %s\n", 1244 XDisplayName(opts.displayName)); 1245 return -1; 1246 } 1247 1248 if (opts.findBest) { 1249 int b; 1250 mesa_hack(dpy, 0); 1251 b = find_best_visual(dpy, 0); 1252 printf("%d\n", b); 1253 } 1254 else { 1255 numScreens = ScreenCount(dpy); 1256 print_display_info(dpy); 1257 for (scrnum = 0; scrnum < numScreens; scrnum++) { 1258 mesa_hack(dpy, scrnum); 1259 coreWorked = print_screen_info(dpy, scrnum, &opts, 1260 True, False, opts.limits, False); 1261 print_screen_info(dpy, scrnum, &opts, False, False, 1262 opts.limits, coreWorked); 1263 print_screen_info(dpy, scrnum, &opts, False, True, False, True); 1264 1265 printf("\n"); 1266 1267 if (opts.mode != Brief) { 1268 print_visual_info(dpy, scrnum, opts.mode); 1269#ifdef GLX_VERSION_1_3 1270 print_fbconfig_info(dpy, scrnum, opts.mode); 1271#endif 1272 } 1273 1274 if (scrnum + 1 < numScreens) 1275 printf("\n\n"); 1276 } 1277 } 1278 1279 XCloseDisplay(dpy); 1280 1281 return 0; 1282} 1283