2 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
27 * -v print verbose information
28 * -display DisplayName specify the X display to interogate
29 * -b only print ID of "best" visual on screen 0
30 * -i use indirect rendering connection only
31 * -l print interesting OpenGL limits (added 5 Sep 2002)
33 * Brian Paul 26 January 2000
36 #define GLX_GLXEXT_PROTOTYPES
37 #define GL_GLEXT_PROTOTYPES
41 #include <X11/Xutil.h>
47 #include "glinfo_common.h"
51 #define GLX_NONE_EXT 0x8000
54 #ifndef GLX_TRANSPARENT_RGB
55 #define GLX_TRANSPARENT_RGB 0x8008
59 #define GLX_RGBA_BIT 0x00000001
62 #ifndef GLX_COLOR_INDEX_BIT
63 #define GLX_COLOR_INDEX_BIT 0x00000002
69 /* X visual attribs */
70 int id
; /* May be visual ID or FBConfig ID */
71 int vis_id
; /* Visual ID. Only set for FBConfigs */
74 int redMask
, greenMask
, blueMask
;
78 /* GL visual attribs */
82 int transparentRedValue
;
83 int transparentGreenValue
;
84 int transparentBlueValue
;
85 int transparentAlphaValue
;
86 int transparentIndexValue
;
93 int redSize
, greenSize
, blueSize
, alphaSize
;
96 int accumRedSize
, accumGreenSize
, accumBlueSize
, accumAlphaSize
;
97 int numSamples
, numMultisample
;
100 int packedfloatComponents
;
106 * Version of the context that was created
108 * 20, 21, 30, 31, 32, etc.
113 * GL Error checking/warning.
121 printf("Warning: GL error 0x%x at line %d\n", n
, line
);
126 print_display_info(Display
*dpy
)
128 printf("name of display: %s\n", DisplayString(dpy
));
133 * Choose a simple FB Config.
136 choose_fb_config(Display
*dpy
, int scrnum
)
138 int fbAttribSingle
[] = {
139 GLX_RENDER_TYPE
, GLX_RGBA_BIT
,
143 GLX_DOUBLEBUFFER
, False
,
145 int fbAttribDouble
[] = {
146 GLX_RENDER_TYPE
, GLX_RGBA_BIT
,
150 GLX_DOUBLEBUFFER
, True
,
152 GLXFBConfig
*configs
;
155 configs
= glXChooseFBConfig(dpy
, scrnum
, fbAttribSingle
, &nConfigs
);
157 configs
= glXChooseFBConfig(dpy
, scrnum
, fbAttribDouble
, &nConfigs
);
163 static Bool CreateContextErrorFlag
;
166 create_context_error_handler(Display
*dpy
, XErrorEvent
*error
)
169 (void) error
->error_code
;
170 CreateContextErrorFlag
= True
;
176 * Try to create a GLX context of the given version with flags/options.
177 * Note: A version number is required in order to get a core profile
178 * (at least w/ NVIDIA).
181 create_context_flags(Display
*dpy
, GLXFBConfig fbconfig
, int major
, int minor
,
182 int contextFlags
, int profileMask
, Bool direct
)
184 #ifdef GLX_ARB_create_context
185 static PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_func
= 0;
186 static Bool firstCall
= True
;
187 int (*old_handler
)(Display
*, XErrorEvent
*);
193 /* See if we have GLX_ARB_create_context_profile and get pointer to
194 * glXCreateContextAttribsARB() function.
196 const char *glxExt
= glXQueryExtensionsString(dpy
, 0);
197 if (extension_supported("GLX_ARB_create_context_profile", glxExt
)) {
198 glXCreateContextAttribsARB_func
= (PFNGLXCREATECONTEXTATTRIBSARBPROC
)
199 glXGetProcAddress((const GLubyte
*) "glXCreateContextAttribsARB");
204 if (!glXCreateContextAttribsARB_func
)
207 /* setup attribute array */
209 attribs
[n
++] = GLX_CONTEXT_MAJOR_VERSION_ARB
;
210 attribs
[n
++] = major
;
211 attribs
[n
++] = GLX_CONTEXT_MINOR_VERSION_ARB
;
212 attribs
[n
++] = minor
;
215 attribs
[n
++] = GLX_CONTEXT_FLAGS_ARB
;
216 attribs
[n
++] = contextFlags
;
218 #ifdef GLX_ARB_create_context_profile
220 attribs
[n
++] = GLX_CONTEXT_PROFILE_MASK_ARB
;
221 attribs
[n
++] = profileMask
;
226 /* install X error handler */
227 old_handler
= XSetErrorHandler(create_context_error_handler
);
228 CreateContextErrorFlag
= False
;
230 /* try creating context */
231 context
= glXCreateContextAttribsARB_func(dpy
,
233 0, /* share_context */
237 /* restore error handler */
238 XSetErrorHandler(old_handler
);
240 if (CreateContextErrorFlag
)
243 if (context
&& direct
) {
244 if (!glXIsDirect(dpy
, context
)) {
245 glXDestroyContext(dpy
, context
);
258 * Try to create a GLX context of the newest version.
261 create_context_with_config(Display
*dpy
, GLXFBConfig config
,
262 Bool coreProfile
, Bool es2Profile
, Bool direct
)
267 /* Try to create a core profile, starting with the newest version of
268 * GL that we're aware of. If we don't specify the version
271 for (i
= 0; gl_versions
[i
].major
> 0; i
++) {
272 /* don't bother below GL 3.0 */
273 if (gl_versions
[i
].major
== 3 &&
274 gl_versions
[i
].minor
== 0)
276 ctx
= create_context_flags(dpy
, config
,
277 gl_versions
[i
].major
,
278 gl_versions
[i
].minor
,
280 GLX_CONTEXT_CORE_PROFILE_BIT_ARB
,
285 /* couldn't get core profile context */
290 #ifdef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
291 if (extension_supported("GLX_EXT_create_context_es2_profile",
292 glXQueryExtensionsString(dpy
, 0))) {
293 ctx
= create_context_flags(dpy
, config
, 2, 0, 0x0,
294 GLX_CONTEXT_ES2_PROFILE_BIT_EXT
,
302 /* GLX should return a context of the latest GL version that supports
305 ctx
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, direct
);
307 /* make sure the context is direct, if direct was requested */
309 if (!glXIsDirect(dpy
, ctx
)) {
310 glXDestroyContext(dpy
, ctx
);
320 choose_xvisinfo(Display
*dpy
, int scrnum
)
322 int attribSingle
[] = {
328 int attribDouble
[] = {
335 XVisualInfo
*visinfo
;
337 visinfo
= glXChooseVisual(dpy
, scrnum
, attribSingle
);
339 visinfo
= glXChooseVisual(dpy
, scrnum
, attribDouble
);
348 #ifdef GLX_MESA_query_renderer
349 PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger
;
350 PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC queryString
;
353 queryInteger
= (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC
)
354 glXGetProcAddressARB((const GLubyte
*)
355 "glXQueryCurrentRendererIntegerMESA");
356 queryString
= (PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC
)
357 glXGetProcAddressARB((const GLubyte
*)
358 "glXQueryCurrentRendererStringMESA");
360 printf("Extended renderer info (GLX_MESA_query_renderer):\n");
361 queryInteger(GLX_RENDERER_VENDOR_ID_MESA
, v
);
362 printf(" Vendor: %s (0x%x)\n",
363 queryString(GLX_RENDERER_VENDOR_ID_MESA
), *v
);
364 queryInteger(GLX_RENDERER_DEVICE_ID_MESA
, v
);
365 printf(" Device: %s (0x%x)\n",
366 queryString(GLX_RENDERER_DEVICE_ID_MESA
), *v
);
367 queryInteger(GLX_RENDERER_VERSION_MESA
, v
);
368 printf(" Version: %d.%d.%d\n", v
[0], v
[1], v
[2]);
369 queryInteger(GLX_RENDERER_ACCELERATED_MESA
, v
);
370 printf(" Accelerated: %s\n", *v
? "yes" : "no");
371 queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA
, v
);
372 printf(" Video memory: %dMB\n", *v
);
373 queryInteger(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA
, v
);
374 printf(" Unified memory: %s\n", *v
? "yes" : "no");
375 queryInteger(GLX_RENDERER_PREFERRED_PROFILE_MESA
, v
);
376 printf(" Preferred profile: %s (0x%x)\n",
377 *v
== GLX_CONTEXT_CORE_PROFILE_BIT_ARB
? "core" :
378 *v
== GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
? "compat" :
380 queryInteger(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA
, v
);
381 printf(" Max core profile version: %d.%d\n", v
[0], v
[1]);
382 queryInteger(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA
, v
);
383 printf(" Max compat profile version: %d.%d\n", v
[0], v
[1]);
384 queryInteger(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA
, v
);
385 printf(" Max GLES1 profile version: %d.%d\n", v
[0], v
[1]);
386 queryInteger(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA
, v
);
387 printf(" Max GLES[23] profile version: %d.%d\n", v
[0], v
[1]);
393 print_screen_info(Display
*dpy
, int scrnum
, Bool allowDirect
,
394 Bool coreProfile
, Bool es2Profile
, Bool limits
,
395 Bool singleLine
, Bool coreWorked
)
398 XSetWindowAttributes attr
;
401 GLXContext ctx
= NULL
;
402 XVisualInfo
*visinfo
;
403 int width
= 100, height
= 100;
404 GLXFBConfig
*fbconfigs
;
405 const char *oglstring
= coreProfile
? "OpenGL core profile" :
406 es2Profile
? "OpenGL ES profile" : "OpenGL";
408 root
= RootWindow(dpy
, scrnum
);
411 * Choose FBConfig or XVisualInfo and create a context.
413 fbconfigs
= choose_fb_config(dpy
, scrnum
);
415 ctx
= create_context_with_config(dpy
, fbconfigs
[0],
416 coreProfile
, es2Profile
, allowDirect
);
417 if (!ctx
&& allowDirect
&& !coreProfile
) {
419 ctx
= create_context_with_config(dpy
, fbconfigs
[0],
420 coreProfile
, es2Profile
, False
);
423 visinfo
= glXGetVisualFromFBConfig(dpy
, fbconfigs
[0]);
426 else if (!coreProfile
&& !es2Profile
) {
427 visinfo
= choose_xvisinfo(dpy
, scrnum
);
429 ctx
= glXCreateContext(dpy
, visinfo
, NULL
, allowDirect
);
433 if (!visinfo
&& !coreProfile
&& !es2Profile
) {
434 fprintf(stderr
, "Error: couldn't find RGB GLX visual or fbconfig\n");
439 if (!coreProfile
&& !es2Profile
)
440 fprintf(stderr
, "Error: glXCreateContext failed\n");
446 * Create a window so that we can just bind the context.
448 attr
.background_pixel
= 0;
449 attr
.border_pixel
= 0;
450 attr
.colormap
= XCreateColormap(dpy
, root
, visinfo
->visual
, AllocNone
);
451 attr
.event_mask
= StructureNotifyMask
| ExposureMask
;
452 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
453 win
= XCreateWindow(dpy
, root
, 0, 0, width
, height
,
454 0, visinfo
->depth
, InputOutput
,
455 visinfo
->visual
, mask
, &attr
);
457 if (glXMakeCurrent(dpy
, win
, ctx
)) {
458 const char *serverVendor
= glXQueryServerString(dpy
, scrnum
, GLX_VENDOR
);
459 const char *serverVersion
= glXQueryServerString(dpy
, scrnum
, GLX_VERSION
);
460 const char *serverExtensions
= glXQueryServerString(dpy
, scrnum
, GLX_EXTENSIONS
);
461 const char *clientVendor
= glXGetClientString(dpy
, GLX_VENDOR
);
462 const char *clientVersion
= glXGetClientString(dpy
, GLX_VERSION
);
463 const char *clientExtensions
= glXGetClientString(dpy
, GLX_EXTENSIONS
);
464 const char *glxExtensions
= glXQueryExtensionsString(dpy
, scrnum
);
465 const char *glVendor
= (const char *) glGetString(GL_VENDOR
);
466 const char *glRenderer
= (const char *) glGetString(GL_RENDERER
);
467 const char *glVersion
= (const char *) glGetString(GL_VERSION
);
471 char *displayName
= NULL
;
472 char *colon
= NULL
, *period
= NULL
;
473 struct ext_functions extfuncs
;
475 CheckError(__LINE__
);
477 /* Get some ext functions */
478 extfuncs
.GetProgramivARB
= (GETPROGRAMIVARBPROC
)
479 glXGetProcAddressARB((GLubyte
*) "glGetProgramivARB");
480 extfuncs
.GetStringi
= (GETSTRINGIPROC
)
481 glXGetProcAddressARB((GLubyte
*) "glGetStringi");
482 extfuncs
.GetConvolutionParameteriv
= (GETCONVOLUTIONPARAMETERIVPROC
)
483 glXGetProcAddressARB((GLubyte
*) "glGetConvolutionParameteriv");
485 /* Get list of GL extensions */
487 glExtensions
= build_core_profile_extension_list(&extfuncs
);
490 glExtensions
= (char *) glGetString(GL_EXTENSIONS
);
493 CheckError(__LINE__
);
495 if (! glXQueryVersion( dpy
, & glxVersionMajor
, & glxVersionMinor
)) {
496 fprintf(stderr
, "Error: glXQueryVersion failed\n");
501 /* Strip the screen number from the display name, if present. */
502 if (!(displayName
= (char *) malloc(strlen(DisplayString(dpy
)) + 1))) {
503 fprintf(stderr
, "Error: malloc() failed\n");
506 strcpy(displayName
, DisplayString(dpy
));
507 colon
= strrchr(displayName
, ':');
509 period
= strchr(colon
, '.');
514 printf("display: %s screen: %d\n", displayName
, scrnum
);
516 printf("direct rendering: ");
517 if (glXIsDirect(dpy
, ctx
)) {
522 printf("No (-i specified)\n");
524 else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
525 printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
528 printf("No (If you want to find out why, try setting "
529 "LIBGL_DEBUG=verbose)\n");
532 printf("server glx vendor string: %s\n", serverVendor
);
533 printf("server glx version string: %s\n", serverVersion
);
534 printf("server glx extensions:\n");
535 print_extension_list(serverExtensions
, singleLine
);
536 printf("client glx vendor string: %s\n", clientVendor
);
537 printf("client glx version string: %s\n", clientVersion
);
538 printf("client glx extensions:\n");
539 print_extension_list(clientExtensions
, singleLine
);
540 printf("GLX version: %u.%u\n", glxVersionMajor
, glxVersionMinor
);
541 printf("GLX extensions:\n");
542 print_extension_list(glxExtensions
, singleLine
);
543 if (strstr(glxExtensions
, "GLX_MESA_query_renderer"))
545 printf("OpenGL vendor string: %s\n", glVendor
);
546 printf("OpenGL renderer string: %s\n", glRenderer
);
550 printf("%s version string: %s\n", oglstring
, glVersion
);
552 version
= (glVersion
[0] - '0') * 10 + (glVersion
[2] - '0');
554 CheckError(__LINE__
);
556 #ifdef GL_VERSION_2_0
558 char *v
= (char *) glGetString(GL_SHADING_LANGUAGE_VERSION
);
559 printf("%s shading language version string: %s\n", oglstring
, v
);
562 CheckError(__LINE__
);
563 #ifdef GL_VERSION_3_0
564 if (version
>= 30 && !es2Profile
) {
566 glGetIntegerv(GL_CONTEXT_FLAGS
, &flags
);
567 printf("%s context flags: %s\n", oglstring
, context_flags_string(flags
));
570 CheckError(__LINE__
);
571 #ifdef GL_VERSION_3_2
572 if (version
>= 32 && !es2Profile
) {
574 glGetIntegerv(GL_CONTEXT_PROFILE_MASK
, &mask
);
575 printf("%s profile mask: %s\n", oglstring
, profile_mask_string(mask
));
579 CheckError(__LINE__
);
581 printf("%s extensions:\n", oglstring
);
582 print_extension_list(glExtensions
, singleLine
);
584 CheckError(__LINE__
);
587 print_limits(glExtensions
, oglstring
, version
, &extfuncs
);
594 fprintf(stderr
, "Error: glXMakeCurrent failed\n");
597 glXDestroyContext(dpy
, ctx
);
599 XDestroyWindow(dpy
, win
);
606 visual_class_name(int cls
)
610 return "StaticColor";
612 return "PseudoColor";
620 return "DirectColor";
627 visual_drawable_type(int type
)
629 const static struct bit_info bits
[] = {
630 { GLX_WINDOW_BIT
, "window" },
631 { GLX_PIXMAP_BIT
, "pixmap" },
632 { GLX_PBUFFER_BIT
, "pbuffer" }
635 return bitmask_to_string(bits
, ELEMENTS(bits
), type
);
639 visual_class_abbrev(int cls
)
660 visual_render_type_name(int type
)
663 case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT
:
665 case GLX_RGBA_FLOAT_BIT_ARB
:
669 case GLX_COLOR_INDEX_BIT
:
671 case GLX_RGBA_BIT
| GLX_COLOR_INDEX_BIT
:
679 caveat_string(int caveat
)
682 #ifdef GLX_EXT_visual_rating
683 case GLX_SLOW_VISUAL_EXT
:
685 case GLX_NON_CONFORMANT_VISUAL_EXT
:
699 get_visual_attribs(Display
*dpy
, XVisualInfo
*vInfo
,
700 struct visual_attribs
*attribs
)
702 const char *ext
= glXQueryExtensionsString(dpy
, vInfo
->screen
);
705 memset(attribs
, 0, sizeof(struct visual_attribs
));
707 attribs
->id
= vInfo
->visualid
;
708 #if defined(__cplusplus) || defined(c_plusplus)
709 attribs
->klass
= vInfo
->c_class
;
711 attribs
->klass
= vInfo
->class;
713 attribs
->depth
= vInfo
->depth
;
714 attribs
->redMask
= vInfo
->red_mask
;
715 attribs
->greenMask
= vInfo
->green_mask
;
716 attribs
->blueMask
= vInfo
->blue_mask
;
717 attribs
->colormapSize
= vInfo
->colormap_size
;
718 attribs
->bitsPerRGB
= vInfo
->bits_per_rgb
;
720 if (glXGetConfig(dpy
, vInfo
, GLX_USE_GL
, &attribs
->supportsGL
) != 0 ||
721 !attribs
->supportsGL
)
723 glXGetConfig(dpy
, vInfo
, GLX_BUFFER_SIZE
, &attribs
->bufferSize
);
724 glXGetConfig(dpy
, vInfo
, GLX_LEVEL
, &attribs
->level
);
725 glXGetConfig(dpy
, vInfo
, GLX_RGBA
, &rgba
);
727 attribs
->render_type
= GLX_RGBA_BIT
;
729 attribs
->render_type
= GLX_COLOR_INDEX_BIT
;
731 glXGetConfig(dpy
, vInfo
, GLX_DRAWABLE_TYPE
, &attribs
->drawableType
);
732 glXGetConfig(dpy
, vInfo
, GLX_DOUBLEBUFFER
, &attribs
->doubleBuffer
);
733 glXGetConfig(dpy
, vInfo
, GLX_STEREO
, &attribs
->stereo
);
734 glXGetConfig(dpy
, vInfo
, GLX_AUX_BUFFERS
, &attribs
->auxBuffers
);
735 glXGetConfig(dpy
, vInfo
, GLX_RED_SIZE
, &attribs
->redSize
);
736 glXGetConfig(dpy
, vInfo
, GLX_GREEN_SIZE
, &attribs
->greenSize
);
737 glXGetConfig(dpy
, vInfo
, GLX_BLUE_SIZE
, &attribs
->blueSize
);
738 glXGetConfig(dpy
, vInfo
, GLX_ALPHA_SIZE
, &attribs
->alphaSize
);
739 glXGetConfig(dpy
, vInfo
, GLX_DEPTH_SIZE
, &attribs
->depthSize
);
740 glXGetConfig(dpy
, vInfo
, GLX_STENCIL_SIZE
, &attribs
->stencilSize
);
741 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_RED_SIZE
, &attribs
->accumRedSize
);
742 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_GREEN_SIZE
, &attribs
->accumGreenSize
);
743 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_BLUE_SIZE
, &attribs
->accumBlueSize
);
744 glXGetConfig(dpy
, vInfo
, GLX_ACCUM_ALPHA_SIZE
, &attribs
->accumAlphaSize
);
746 /* get transparent pixel stuff */
747 glXGetConfig(dpy
, vInfo
,GLX_TRANSPARENT_TYPE
, &attribs
->transparentType
);
748 if (attribs
->transparentType
== GLX_TRANSPARENT_RGB
) {
749 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_RED_VALUE
, &attribs
->transparentRedValue
);
750 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_GREEN_VALUE
, &attribs
->transparentGreenValue
);
751 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_BLUE_VALUE
, &attribs
->transparentBlueValue
);
752 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_ALPHA_VALUE
, &attribs
->transparentAlphaValue
);
754 else if (attribs
->transparentType
== GLX_TRANSPARENT_INDEX
) {
755 glXGetConfig(dpy
, vInfo
, GLX_TRANSPARENT_INDEX_VALUE
, &attribs
->transparentIndexValue
);
758 /* multisample attribs */
759 #ifdef GLX_ARB_multisample
760 if (ext
&& strstr(ext
, "GLX_ARB_multisample")) {
761 glXGetConfig(dpy
, vInfo
, GLX_SAMPLE_BUFFERS_ARB
, &attribs
->numMultisample
);
762 glXGetConfig(dpy
, vInfo
, GLX_SAMPLES_ARB
, &attribs
->numSamples
);
766 attribs
->numSamples
= 0;
767 attribs
->numMultisample
= 0;
770 #if defined(GLX_EXT_visual_rating)
771 if (ext
&& strstr(ext
, "GLX_EXT_visual_rating")) {
772 glXGetConfig(dpy
, vInfo
, GLX_VISUAL_CAVEAT_EXT
, &attribs
->visualCaveat
);
775 attribs
->visualCaveat
= GLX_NONE_EXT
;
778 attribs
->visualCaveat
= 0;
781 #if defined(GLX_EXT_framebuffer_sRGB)
782 if (ext
&& strstr(ext
, "GLX_EXT_framebuffer_sRGB")) {
783 glXGetConfig(dpy
, vInfo
, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT
, &attribs
->srgb
);
790 #ifdef GLX_VERSION_1_3
793 glx_token_to_visual_class(int visual_type
)
795 switch (visual_type
) {
798 case GLX_DIRECT_COLOR
:
800 case GLX_PSEUDO_COLOR
:
802 case GLX_STATIC_COLOR
:
806 case GLX_STATIC_GRAY
:
815 get_fbconfig_attribs(Display
*dpy
, GLXFBConfig fbconfig
,
816 struct visual_attribs
*attribs
)
818 const char *ext
= glXQueryExtensionsString(dpy
, 0);
822 memset(attribs
, 0, sizeof(struct visual_attribs
));
824 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_FBCONFIG_ID
, &attribs
->id
);
826 vInfo
= glXGetVisualFromFBConfig(dpy
, fbconfig
);
829 attribs
->vis_id
= vInfo
->visualid
;
830 attribs
->depth
= vInfo
->depth
;
831 attribs
->redMask
= vInfo
->red_mask
;
832 attribs
->greenMask
= vInfo
->green_mask
;
833 attribs
->blueMask
= vInfo
->blue_mask
;
834 attribs
->colormapSize
= vInfo
->colormap_size
;
835 attribs
->bitsPerRGB
= vInfo
->bits_per_rgb
;
838 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_X_VISUAL_TYPE
, &visual_type
);
839 attribs
->klass
= glx_token_to_visual_class(visual_type
);
841 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_DRAWABLE_TYPE
, &attribs
->drawableType
);
842 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_BUFFER_SIZE
, &attribs
->bufferSize
);
843 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_LEVEL
, &attribs
->level
);
844 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_RENDER_TYPE
, &attribs
->render_type
);
845 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_DOUBLEBUFFER
, &attribs
->doubleBuffer
);
846 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_STEREO
, &attribs
->stereo
);
847 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_AUX_BUFFERS
, &attribs
->auxBuffers
);
849 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_RED_SIZE
, &attribs
->redSize
);
850 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_GREEN_SIZE
, &attribs
->greenSize
);
851 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_BLUE_SIZE
, &attribs
->blueSize
);
852 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_ALPHA_SIZE
, &attribs
->alphaSize
);
853 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_DEPTH_SIZE
, &attribs
->depthSize
);
854 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_STENCIL_SIZE
, &attribs
->stencilSize
);
856 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_ACCUM_RED_SIZE
, &attribs
->accumRedSize
);
857 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_ACCUM_GREEN_SIZE
, &attribs
->accumGreenSize
);
858 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_ACCUM_BLUE_SIZE
, &attribs
->accumBlueSize
);
859 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_ACCUM_ALPHA_SIZE
, &attribs
->accumAlphaSize
);
861 /* get transparent pixel stuff */
862 glXGetFBConfigAttrib(dpy
, fbconfig
,GLX_TRANSPARENT_TYPE
, &attribs
->transparentType
);
863 if (attribs
->transparentType
== GLX_TRANSPARENT_RGB
) {
864 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_TRANSPARENT_RED_VALUE
, &attribs
->transparentRedValue
);
865 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_TRANSPARENT_GREEN_VALUE
, &attribs
->transparentGreenValue
);
866 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_TRANSPARENT_BLUE_VALUE
, &attribs
->transparentBlueValue
);
867 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_TRANSPARENT_ALPHA_VALUE
, &attribs
->transparentAlphaValue
);
869 else if (attribs
->transparentType
== GLX_TRANSPARENT_INDEX
) {
870 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_TRANSPARENT_INDEX_VALUE
, &attribs
->transparentIndexValue
);
873 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_SAMPLE_BUFFERS
, &attribs
->numMultisample
);
874 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_SAMPLES
, &attribs
->numSamples
);
875 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_CONFIG_CAVEAT
, &attribs
->visualCaveat
);
877 #if defined(GLX_NV_float_buffer)
878 if (ext
&& strstr(ext
, "GLX_NV_float_buffer")) {
879 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_FLOAT_COMPONENTS_NV
, &attribs
->floatComponents
);
882 #if defined(GLX_ARB_fbconfig_float)
883 if (ext
&& strstr(ext
, "GLX_ARB_fbconfig_float")) {
884 if (attribs
->render_type
& GLX_RGBA_FLOAT_BIT_ARB
) {
885 attribs
->floatComponents
= True
;
889 #if defined(GLX_EXT_fbconfig_packed_float)
890 if (ext
&& strstr(ext
, "GLX_EXT_fbconfig_packed_float")) {
891 if (attribs
->render_type
& GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT
) {
892 attribs
->packedfloatComponents
= True
;
897 #if defined(GLX_EXT_framebuffer_sRGB)
898 if (ext
&& strstr(ext
, "GLX_EXT_framebuffer_sRGB")) {
899 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT
, &attribs
->srgb
);
910 print_visual_attribs_verbose(const struct visual_attribs
*attribs
,
914 printf("FBConfig ID: %x Visual ID=%x depth=%d class=%s, type=%s\n",
915 attribs
->id
, attribs
->vis_id
, attribs
->depth
,
916 visual_class_name(attribs
->klass
),
917 visual_drawable_type(attribs
->drawableType
));
920 printf("Visual ID: %x depth=%d class=%s, type=%s\n",
921 attribs
->id
, attribs
->depth
, visual_class_name(attribs
->klass
),
922 visual_drawable_type(attribs
->drawableType
));
924 printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
925 attribs
->bufferSize
, attribs
->level
,
926 visual_render_type_name(attribs
->render_type
),
927 attribs
->doubleBuffer
, attribs
->stereo
);
928 printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d float=%c sRGB=%c\n",
929 attribs
->redSize
, attribs
->greenSize
,
930 attribs
->blueSize
, attribs
->alphaSize
,
931 attribs
->packedfloatComponents
? 'P' : attribs
->floatComponents
? 'Y' : 'N',
932 attribs
->srgb
? 'Y' : 'N');
933 printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
934 attribs
->auxBuffers
, attribs
->depthSize
, attribs
->stencilSize
);
935 printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
936 attribs
->accumRedSize
, attribs
->accumGreenSize
,
937 attribs
->accumBlueSize
, attribs
->accumAlphaSize
);
938 printf(" multiSample=%d multiSampleBuffers=%d\n",
939 attribs
->numSamples
, attribs
->numMultisample
);
940 #ifdef GLX_EXT_visual_rating
941 if (attribs
->visualCaveat
== GLX_NONE_EXT
|| attribs
->visualCaveat
== 0)
942 printf(" visualCaveat=None\n");
943 else if (attribs
->visualCaveat
== GLX_SLOW_VISUAL_EXT
)
944 printf(" visualCaveat=Slow\n");
945 else if (attribs
->visualCaveat
== GLX_NON_CONFORMANT_VISUAL_EXT
)
946 printf(" visualCaveat=Nonconformant\n");
948 if (attribs
->transparentType
== GLX_NONE
) {
949 printf(" Opaque.\n");
951 else if (attribs
->transparentType
== GLX_TRANSPARENT_RGB
) {
952 printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs
->transparentRedValue
,attribs
->transparentGreenValue
,attribs
->transparentBlueValue
,attribs
->transparentAlphaValue
);
954 else if (attribs
->transparentType
== GLX_TRANSPARENT_INDEX
) {
955 printf(" Transparent index=%d\n",attribs
->transparentIndexValue
);
961 print_visual_attribs_short_header(void)
963 printf(" visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav\n");
964 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");
965 printf("----------------------------------------------------------------------------\n");
970 print_visual_attribs_short(const struct visual_attribs
*attribs
)
972 const char *caveat
= caveat_string(attribs
->visualCaveat
);
974 printf("0x%03x %2d %2s %2d %3d %2d %c%c %c %c %2d %2d %2d %2d %c %c %2d %2d %2d",
977 visual_class_abbrev(attribs
->klass
),
978 attribs
->transparentType
!= GLX_NONE
,
981 (attribs
->render_type
& GLX_RGBA_BIT
) ? 'r' : ' ',
982 (attribs
->render_type
& GLX_COLOR_INDEX_BIT
) ? 'c' : ' ',
983 attribs
->doubleBuffer
? 'y' : '.',
984 attribs
->stereo
? 'y' : '.',
985 attribs
->redSize
, attribs
->greenSize
,
986 attribs
->blueSize
, attribs
->alphaSize
,
987 attribs
->packedfloatComponents
? 'u' : attribs
->floatComponents
? 'f' : '.',
988 attribs
->srgb
? 's' : '.',
994 printf(" %2d %2d %2d %2d %2d %1d %s\n",
995 attribs
->accumRedSize
, attribs
->accumGreenSize
,
996 attribs
->accumBlueSize
, attribs
->accumAlphaSize
,
997 attribs
->numSamples
, attribs
->numMultisample
,
1004 print_visual_attribs_long_header(void)
1006 printf("Vis Vis Visual Trans buff lev render DB ste r g b a s aux dep ste accum buffer MS MS \n");
1007 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");
1008 printf("--------------------------------------------------------------------------------------------------------------------\n");
1013 print_visual_attribs_long(const struct visual_attribs
*attribs
)
1015 const char *caveat
= caveat_string(attribs
->visualCaveat
);
1017 printf("0x%3x %2d %-11s %2d %3d %2d %4s %3d %3d %3d %3d %3d %3d",
1020 visual_class_name(attribs
->klass
),
1021 attribs
->transparentType
!= GLX_NONE
,
1022 attribs
->bufferSize
,
1024 visual_render_type_name(attribs
->render_type
),
1025 attribs
->doubleBuffer
,
1027 attribs
->redSize
, attribs
->greenSize
,
1028 attribs
->blueSize
, attribs
->alphaSize
1031 printf(" %c %c %3d %4d %2d %3d %3d %3d %3d %2d %2d %6s\n",
1032 attribs
->floatComponents
? 'f' : '.',
1033 attribs
->srgb
? 's' : '.',
1034 attribs
->auxBuffers
,
1036 attribs
->stencilSize
,
1037 attribs
->accumRedSize
, attribs
->accumGreenSize
,
1038 attribs
->accumBlueSize
, attribs
->accumAlphaSize
,
1039 attribs
->numSamples
, attribs
->numMultisample
,
1046 print_visual_info(Display
*dpy
, int scrnum
, InfoMode mode
)
1048 XVisualInfo theTemplate
;
1049 XVisualInfo
*visuals
;
1050 int numVisuals
, numGlxVisuals
;
1053 struct visual_attribs attribs
;
1055 /* get list of all visuals on this screen */
1056 theTemplate
.screen
= scrnum
;
1057 mask
= VisualScreenMask
;
1058 visuals
= XGetVisualInfo(dpy
, mask
, &theTemplate
, &numVisuals
);
1061 for (i
= 0; i
< numVisuals
; i
++) {
1062 if (get_visual_attribs(dpy
, &visuals
[i
], &attribs
))
1066 if (numGlxVisuals
== 0)
1069 printf("%d GLX Visuals\n", numGlxVisuals
);
1072 print_visual_attribs_short_header();
1073 else if (mode
== Wide
)
1074 print_visual_attribs_long_header();
1076 for (i
= 0; i
< numVisuals
; i
++) {
1077 if (!get_visual_attribs(dpy
, &visuals
[i
], &attribs
))
1080 if (mode
== Verbose
)
1081 print_visual_attribs_verbose(&attribs
, False
);
1082 else if (mode
== Normal
)
1083 print_visual_attribs_short(&attribs
);
1084 else if (mode
== Wide
)
1085 print_visual_attribs_long(&attribs
);
1092 #ifdef GLX_VERSION_1_3
1095 print_fbconfig_info(Display
*dpy
, int scrnum
, InfoMode mode
)
1097 int numFBConfigs
= 0;
1098 struct visual_attribs attribs
;
1099 GLXFBConfig
*fbconfigs
;
1102 /* get list of all fbconfigs on this screen */
1103 fbconfigs
= glXGetFBConfigs(dpy
, scrnum
, &numFBConfigs
);
1105 if (numFBConfigs
== 0) {
1110 printf("%d GLXFBConfigs:\n", numFBConfigs
);
1112 print_visual_attribs_short_header();
1113 else if (mode
== Wide
)
1114 print_visual_attribs_long_header();
1116 for (i
= 0; i
< numFBConfigs
; i
++) {
1117 get_fbconfig_attribs(dpy
, fbconfigs
[i
], &attribs
);
1119 if (mode
== Verbose
)
1120 print_visual_attribs_verbose(&attribs
, True
);
1121 else if (mode
== Normal
)
1122 print_visual_attribs_short(&attribs
);
1123 else if (mode
== Wide
)
1124 print_visual_attribs_long(&attribs
);
1134 * Stand-alone Mesa doesn't really implement the GLX protocol so it
1135 * doesn't really know the GLX attributes associated with an X visual.
1136 * The first time a visual is presented to Mesa's pseudo-GLX it
1137 * attaches ancilliary buffers to it (like depth and stencil).
1138 * But that usually only works if glXChooseVisual is used.
1139 * This function calls glXChooseVisual() to sort of "prime the pump"
1140 * for Mesa's GLX so that the visuals that get reported actually
1141 * reflect what applications will see.
1142 * This has no effect when using true GLX.
1145 mesa_hack(Display
*dpy
, int scrnum
)
1147 static int attribs
[] = {
1153 GLX_STENCIL_SIZE
, 1,
1154 GLX_ACCUM_RED_SIZE
, 1,
1155 GLX_ACCUM_GREEN_SIZE
, 1,
1156 GLX_ACCUM_BLUE_SIZE
, 1,
1157 GLX_ACCUM_ALPHA_SIZE
, 1,
1161 XVisualInfo
*visinfo
;
1163 visinfo
= glXChooseVisual(dpy
, scrnum
, attribs
);
1170 * Examine all visuals to find the so-called best one.
1171 * We prefer deepest RGBA buffer with depth, stencil and accum
1172 * that has no caveats.
1175 find_best_visual(Display
*dpy
, int scrnum
)
1177 XVisualInfo theTemplate
;
1178 XVisualInfo
*visuals
;
1182 struct visual_attribs bestVis
;
1184 /* get list of all visuals on this screen */
1185 theTemplate
.screen
= scrnum
;
1186 mask
= VisualScreenMask
;
1187 visuals
= XGetVisualInfo(dpy
, mask
, &theTemplate
, &numVisuals
);
1189 /* init bestVis with first visual info */
1190 get_visual_attribs(dpy
, &visuals
[0], &bestVis
);
1192 /* try to find a "better" visual */
1193 for (i
= 1; i
< numVisuals
; i
++) {
1194 struct visual_attribs vis
;
1196 get_visual_attribs(dpy
, &visuals
[i
], &vis
);
1198 /* always skip visuals with caveats */
1199 if (vis
.visualCaveat
!= GLX_NONE_EXT
)
1202 /* see if this vis is better than bestVis */
1203 if ((!bestVis
.supportsGL
&& vis
.supportsGL
) ||
1204 (bestVis
.visualCaveat
!= GLX_NONE_EXT
) ||
1205 (!(bestVis
.render_type
& GLX_RGBA_BIT
) && (vis
.render_type
& GLX_RGBA_BIT
)) ||
1206 (!bestVis
.doubleBuffer
&& vis
.doubleBuffer
) ||
1207 (bestVis
.redSize
< vis
.redSize
) ||
1208 (bestVis
.greenSize
< vis
.greenSize
) ||
1209 (bestVis
.blueSize
< vis
.blueSize
) ||
1210 (bestVis
.alphaSize
< vis
.alphaSize
) ||
1211 (bestVis
.depthSize
< vis
.depthSize
) ||
1212 (bestVis
.stencilSize
< vis
.stencilSize
) ||
1213 (bestVis
.accumRedSize
< vis
.accumRedSize
)) {
1214 /* found a better visual */
1226 main(int argc
, char *argv
[])
1229 int numScreens
, scrnum
;
1230 struct options opts
;
1233 parse_args(argc
, argv
, &opts
);
1235 dpy
= XOpenDisplay(opts
.displayName
);
1237 fprintf(stderr
, "Error: unable to open display %s\n",
1238 XDisplayName(opts
.displayName
));
1242 if (opts
.findBest
) {
1245 b
= find_best_visual(dpy
, 0);
1249 numScreens
= ScreenCount(dpy
);
1250 print_display_info(dpy
);
1251 for (scrnum
= 0; scrnum
< numScreens
; scrnum
++) {
1252 mesa_hack(dpy
, scrnum
);
1253 coreWorked
= print_screen_info(dpy
, scrnum
, opts
.allowDirect
,
1254 True
, False
, opts
.limits
,
1255 opts
.singleLine
, False
);
1256 print_screen_info(dpy
, scrnum
, opts
.allowDirect
, False
, False
,
1257 opts
.limits
, opts
.singleLine
, coreWorked
);
1258 print_screen_info(dpy
, scrnum
, opts
.allowDirect
, False
, True
, False
,
1259 opts
.singleLine
, True
);
1262 print_visual_info(dpy
, scrnum
, opts
.mode
);
1263 #ifdef GLX_VERSION_1_3
1264 print_fbconfig_info(dpy
, scrnum
, opts
.mode
);
1266 if (scrnum
+ 1 < numScreens
)