glxinfo: test GL_ATI_meminfo and GL_NVX_gpu_memory_info (v2)
[mesa-demos.git] / src / xdemos / glxinfo.c
blob1893f7bdcebb15eabb9b99cbf1890fb6f0864fce
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
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)
34 * Brian Paul 26 January 2000
37 #define GLX_GLXEXT_PROTOTYPES
38 #define GL_GLEXT_PROTOTYPES
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"
51 #ifndef GLX_NONE_EXT
52 #define GLX_NONE_EXT 0x8000
53 #endif
55 #ifndef GLX_TRANSPARENT_RGB
56 #define GLX_TRANSPARENT_RGB 0x8008
57 #endif
59 #ifndef GLX_RGBA_BIT
60 #define GLX_RGBA_BIT 0x00000001
61 #endif
63 #ifndef GLX_COLOR_INDEX_BIT
64 #define GLX_COLOR_INDEX_BIT 0x00000002
65 #endif
68 struct visual_attribs
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;
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;
107 * Version of the context that was created
109 * 20, 21, 30, 31, 32, etc.
111 static int version;
114 * GL Error checking/warning.
116 static void
117 CheckError(int line)
119 int n;
120 n = glGetError();
121 if (n)
122 printf("Warning: GL error 0x%x at line %d\n", n, line);
126 static void
127 print_display_info(Display *dpy)
129 printf("name of display: %s\n", DisplayString(dpy));
134 * Choose a simple FB Config.
136 static GLXFBConfig *
137 choose_fb_config(Display *dpy, int scrnum)
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;
156 configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
157 if (!configs)
158 configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
160 return configs;
164 static Bool CreateContextErrorFlag;
166 static int
167 create_context_error_handler(Display *dpy, XErrorEvent *error)
169 (void) dpy;
170 (void) error->error_code;
171 CreateContextErrorFlag = True;
172 return 0;
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).
181 static GLXContext
182 create_context_flags(Display *dpy, GLXFBConfig fbconfig, int major, int minor,
183 int contextFlags, int profileMask, Bool direct)
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;
193 if (firstCall) {
194 /* See if we have GLX_ARB_create_context_profile and get pointer to
195 * glXCreateContextAttribsARB() function.
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");
202 firstCall = False;
205 if (!glXCreateContextAttribsARB_func)
206 return 0;
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;
215 if (contextFlags) {
216 attribs[n++] = GLX_CONTEXT_FLAGS_ARB;
217 attribs[n++] = contextFlags;
219 #ifdef GLX_ARB_create_context_profile
220 if (profileMask) {
221 attribs[n++] = GLX_CONTEXT_PROFILE_MASK_ARB;
222 attribs[n++] = profileMask;
224 #endif
225 attribs[n++] = 0;
227 /* install X error handler */
228 old_handler = XSetErrorHandler(create_context_error_handler);
229 CreateContextErrorFlag = False;
231 /* try creating context */
232 context = glXCreateContextAttribsARB_func(dpy,
233 fbconfig,
234 0, /* share_context */
235 direct,
236 attribs);
238 /* restore error handler */
239 XSetErrorHandler(old_handler);
241 if (CreateContextErrorFlag)
242 context = 0;
244 if (context && direct) {
245 if (!glXIsDirect(dpy, context)) {
246 glXDestroyContext(dpy, context);
247 return 0;
251 return context;
252 #else
253 return 0;
254 #endif
259 * Try to create a GLX context of the newest version.
261 static GLXContext
262 create_context_with_config(Display *dpy, GLXFBConfig config,
263 Bool coreProfile, Bool es2Profile, Bool direct)
265 GLXContext ctx = 0;
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
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;
286 /* couldn't get core profile context */
287 return 0;
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;
299 #endif
300 return 0;
303 /* GLX should return a context of the latest GL version that supports
304 * the full profile.
306 ctx = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, direct);
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;
316 return ctx;
320 static XVisualInfo *
321 choose_xvisinfo(Display *dpy, int scrnum)
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;
338 visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
339 if (!visinfo)
340 visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
342 return visinfo;
346 static void
347 query_renderer(void)
349 #ifdef GLX_MESA_query_renderer
350 PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger;
351 PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC queryString;
352 unsigned int v[3];
354 queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)
355 glXGetProcAddressARB((const GLubyte *)
356 "glXQueryCurrentRendererIntegerMESA");
357 queryString = (PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC)
358 glXGetProcAddressARB((const GLubyte *)
359 "glXQueryCurrentRendererStringMESA");
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
393 static Bool
394 print_screen_info(Display *dpy, int scrnum,
395 const struct options *opts,
396 Bool coreProfile, Bool es2Profile, Bool limits,
397 Bool coreWorked)
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";
410 root = RootWindow(dpy, scrnum);
413 * Choose FBConfig or XVisualInfo and create a context.
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);
426 visinfo = glXGetVisualFromFBConfig(dpy, fbconfigs[0]);
427 XFree(fbconfigs);
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;
436 if (!visinfo && !coreProfile && !es2Profile) {
437 fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
438 return False;
441 if (!ctx) {
442 if (!coreProfile && !es2Profile)
443 fprintf(stderr, "Error: glXCreateContext failed\n");
444 XFree(visinfo);
445 return False;
449 * Create a window so that we can just bind the context.
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);
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;
478 CheckError(__LINE__);
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");
488 if (!glXQueryVersion(dpy, & glxVersionMajor, & glxVersionMinor)) {
489 fprintf(stderr, "Error: glXQueryVersion failed\n");
490 exit(1);
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);
501 CheckError(__LINE__);
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);
509 strcpy(displayName, DisplayString(dpy));
510 colon = strrchr(displayName, ':');
511 if (colon) {
512 period = strchr(colon, '.');
513 if (period)
514 *period = '\0';
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");
523 else {
524 if (!opts->allowDirect) {
525 printf("No (-i specified)\n");
527 else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
528 printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
530 else {
531 printf("No (If you want to find out why, try setting "
532 "LIBGL_DEBUG=verbose)\n");
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);
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");
556 printf("%s version string: %s\n", oglstring, glVersion);
558 version = (glVersion[0] - '0') * 10 + (glVersion[2] - '0');
560 CheckError(__LINE__);
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);
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));
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));
583 #endif
585 CheckError(__LINE__);
587 if (opts->mode != Brief) {
588 printf("%s extensions:\n", oglstring);
589 print_extension_list(glExtensions, opts->singleLine);
592 if (limits) {
593 print_limits(glExtensions, oglstring, version, &extfuncs);
596 if (coreProfile)
597 free(glExtensions);
599 else {
600 fprintf(stderr, "Error: glXMakeCurrent failed\n");
603 glXDestroyContext(dpy, ctx);
604 XFree(visinfo);
605 XDestroyWindow(dpy, win);
606 XSync(dpy, 1);
607 return True;
611 static const char *
612 visual_class_name(int cls)
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 "";
632 static const char *
633 visual_drawable_type(int type)
635 const static struct bit_info bits[] = {
636 { GLX_WINDOW_BIT, "window" },
637 { GLX_PIXMAP_BIT, "pixmap" },
638 { GLX_PBUFFER_BIT, "pbuffer" }
641 return bitmask_to_string(bits, ELEMENTS(bits), type);
644 static const char *
645 visual_class_abbrev(int cls)
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 "";
665 static const char *
666 visual_render_type_name(int type)
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 "";
684 static const char *
685 caveat_string(int caveat)
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";
704 static Bool
705 get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
706 struct visual_attribs *attribs)
708 const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
709 int rgba;
711 memset(attribs, 0, sizeof(struct visual_attribs));
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;
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;
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);
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);
760 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
761 glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
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);
770 #endif
771 else {
772 attribs->numSamples = 0;
773 attribs->numMultisample = 0;
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);
780 else {
781 attribs->visualCaveat = GLX_NONE_EXT;
783 #else
784 attribs->visualCaveat = 0;
785 #endif
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);
791 #endif
793 return True;
796 #ifdef GLX_VERSION_1_3
798 static int
799 glx_token_to_visual_class(int visual_type)
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;
820 static Bool
821 get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
822 struct visual_attribs *attribs)
824 const char *ext = glXQueryExtensionsString(dpy, 0);
825 int visual_type;
826 XVisualInfo *vInfo;
828 memset(attribs, 0, sizeof(struct visual_attribs));
830 glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id);
832 vInfo = glXGetVisualFromFBConfig(dpy, fbconfig);
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;
844 glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
845 attribs->klass = glx_token_to_visual_class(visual_type);
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);
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);
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);
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);
875 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
876 glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
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);
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);
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;
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;
901 #endif
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);
907 #endif
908 return True;
911 #endif
915 static void
916 print_visual_attribs_verbose(const struct visual_attribs *attribs,
917 int fbconfigs)
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));
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));
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");
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);
960 else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
961 printf(" Transparent index=%d\n",attribs->transparentIndexValue);
966 static void
967 print_visual_attribs_short_header(void)
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");
975 static void
976 print_visual_attribs_short(const struct visual_attribs *attribs)
978 const char *caveat = caveat_string(attribs->visualCaveat);
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
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
1009 static void
1010 print_visual_attribs_long_header(void)
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");
1018 static void
1019 print_visual_attribs_long(const struct visual_attribs *attribs)
1021 const char *caveat = caveat_string(attribs->visualCaveat);
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
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
1051 static void
1052 print_visual_info(Display *dpy, int scrnum, InfoMode mode)
1054 XVisualInfo theTemplate;
1055 XVisualInfo *visuals;
1056 int numVisuals, numGlxVisuals;
1057 long mask;
1058 int i;
1059 struct visual_attribs attribs;
1061 /* get list of all visuals on this screen */
1062 theTemplate.screen = scrnum;
1063 mask = VisualScreenMask;
1064 visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
1066 numGlxVisuals = 0;
1067 for (i = 0; i < numVisuals; i++) {
1068 if (get_visual_attribs(dpy, &visuals[i], &attribs))
1069 numGlxVisuals++;
1072 if (numGlxVisuals == 0)
1073 return;
1075 printf("%d GLX Visuals\n", numGlxVisuals);
1077 if (mode == Normal)
1078 print_visual_attribs_short_header();
1079 else if (mode == Wide)
1080 print_visual_attribs_long_header();
1082 for (i = 0; i < numVisuals; i++) {
1083 if (!get_visual_attribs(dpy, &visuals[i], &attribs))
1084 continue;
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);
1093 printf("\n");
1095 XFree(visuals);
1098 #ifdef GLX_VERSION_1_3
1100 static void
1101 print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode)
1103 int numFBConfigs = 0;
1104 struct visual_attribs attribs;
1105 GLXFBConfig *fbconfigs;
1106 int i;
1108 /* get list of all fbconfigs on this screen */
1109 fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs);
1111 if (numFBConfigs == 0) {
1112 XFree(fbconfigs);
1113 return;
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();
1122 for (i = 0; i < numFBConfigs; i++) {
1123 get_fbconfig_attribs(dpy, fbconfigs[i], &attribs);
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);
1132 printf("\n");
1134 XFree(fbconfigs);
1137 #endif
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.
1150 static void
1151 mesa_hack(Display *dpy, int scrnum)
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
1167 XVisualInfo *visinfo;
1169 visinfo = glXChooseVisual(dpy, scrnum, attribs);
1170 if (visinfo)
1171 XFree(visinfo);
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.
1180 static int
1181 find_best_visual(Display *dpy, int scrnum)
1183 XVisualInfo theTemplate;
1184 XVisualInfo *visuals;
1185 int numVisuals;
1186 long mask;
1187 int i;
1188 struct visual_attribs bestVis;
1190 /* get list of all visuals on this screen */
1191 theTemplate.screen = scrnum;
1192 mask = VisualScreenMask;
1193 visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
1195 /* init bestVis with first visual info */
1196 get_visual_attribs(dpy, &visuals[0], &bestVis);
1198 /* try to find a "better" visual */
1199 for (i = 1; i < numVisuals; i++) {
1200 struct visual_attribs vis;
1202 get_visual_attribs(dpy, &visuals[i], &vis);
1204 /* always skip visuals with caveats */
1205 if (vis.visualCaveat != GLX_NONE_EXT)
1206 continue;
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;
1225 XFree(visuals);
1227 return bestVis.id;
1232 main(int argc, char *argv[])
1234 Display *dpy;
1235 int numScreens, scrnum;
1236 struct options opts;
1237 Bool coreWorked;
1239 parse_args(argc, argv, &opts);
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;
1248 if (opts.findBest) {
1249 int b;
1250 mesa_hack(dpy, 0);
1251 b = find_best_visual(dpy, 0);
1252 printf("%d\n", b);
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);
1265 printf("\n");
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
1274 if (scrnum + 1 < numScreens)
1275 printf("\n\n");
1279 XCloseDisplay(dpy);
1281 return 0;