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 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
42 #include <X11/Xutil.h>
48 #include "glinfo_common.h"
52 #define GLX_NONE_EXT 0x8000
55 #ifndef GLX_TRANSPARENT_RGB
56 #define GLX_TRANSPARENT_RGB 0x8008
60 #define GLX_RGBA_BIT 0x00000001
63 #ifndef GLX_COLOR_INDEX_BIT
64 #define GLX_COLOR_INDEX_BIT 0x00000002
70 /* X visual attribs */
71 int id
; /* May be visual ID or FBConfig ID */
72 int vis_id
; /* Visual ID. Only set for FBConfigs */
75 int redMask
, greenMask
, blueMask
;
79 /* GL visual attribs */
83 int transparentRedValue
;
84 int transparentGreenValue
;
85 int transparentBlueValue
;
86 int transparentAlphaValue
;
87 int transparentIndexValue
;
94 int redSize
, greenSize
, blueSize
, alphaSize
;
97 int accumRedSize
, accumGreenSize
, accumBlueSize
, accumAlphaSize
;
98 int numSamples
, numMultisample
;
101 int packedfloatComponents
;
107 * Version of the context that was created
109 * 20, 21, 30, 31, 32, etc.
114 * GL Error checking/warning.
122 printf("Warning: GL error 0x%x at line %d\n", n
, line
);
127 print_display_info(Display
*dpy
)
129 printf("name of display: %s\n", DisplayString(dpy
));
134 * Choose a simple FB Config.
137 choose_fb_config(Display
*dpy
, int scrnum
)
139 int fbAttribSingle
[] = {
140 GLX_RENDER_TYPE
, GLX_RGBA_BIT
,
144 GLX_DOUBLEBUFFER
, False
,
146 int fbAttribDouble
[] = {
147 GLX_RENDER_TYPE
, GLX_RGBA_BIT
,
151 GLX_DOUBLEBUFFER
, True
,
153 GLXFBConfig
*configs
;
156 configs
= glXChooseFBConfig(dpy
, scrnum
, fbAttribSingle
, &nConfigs
);
158 configs
= glXChooseFBConfig(dpy
, scrnum
, fbAttribDouble
, &nConfigs
);
164 static Bool CreateContextErrorFlag
;
167 create_context_error_handler(Display
*dpy
, XErrorEvent
*error
)
170 (void) error
->error_code
;
171 CreateContextErrorFlag
= True
;
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).
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
*);
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");
205 if (!glXCreateContextAttribsARB_func
)
208 /* setup attribute array */
210 attribs
[n
++] = GLX_CONTEXT_MAJOR_VERSION_ARB
;
211 attribs
[n
++] = major
;
212 attribs
[n
++] = GLX_CONTEXT_MINOR_VERSION_ARB
;
213 attribs
[n
++] = minor
;
216 attribs
[n
++] = GLX_CONTEXT_FLAGS_ARB
;
217 attribs
[n
++] = contextFlags
;
219 #ifdef GLX_ARB_create_context_profile
221 attribs
[n
++] = GLX_CONTEXT_PROFILE_MASK_ARB
;
222 attribs
[n
++] = profileMask
;
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
,
234 0, /* share_context */
238 /* restore error handler */
239 XSetErrorHandler(old_handler
);
241 if (CreateContextErrorFlag
)
244 if (context
&& direct
) {
245 if (!glXIsDirect(dpy
, context
)) {
246 glXDestroyContext(dpy
, context
);
259 * Try to create a GLX context of the newest version.
262 create_context_with_config(Display
*dpy
, GLXFBConfig config
,
263 Bool coreProfile
, Bool es2Profile
, Bool direct
)
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
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)
277 ctx
= create_context_flags(dpy
, config
,
278 gl_versions
[i
].major
,
279 gl_versions
[i
].minor
,
281 GLX_CONTEXT_CORE_PROFILE_BIT_ARB
,
286 /* couldn't get core profile context */
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
,
303 /* GLX should return a context of the latest GL version that supports
306 ctx
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, direct
);
308 /* make sure the context is direct, if direct was requested */
310 if (!glXIsDirect(dpy
, ctx
)) {
311 glXDestroyContext(dpy
, ctx
);
321 choose_xvisinfo(Display
*dpy
, int scrnum
)
323 int attribSingle
[] = {
329 int attribDouble
[] = {
336 XVisualInfo
*visinfo
;
338 visinfo
= glXChooseVisual(dpy
, scrnum
, attribSingle
);
340 visinfo
= glXChooseVisual(dpy
, scrnum
, attribDouble
);
349 #ifdef GLX_MESA_query_renderer
350 PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger
;
351 PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC queryString
;
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" :
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]);
394 print_screen_info(Display
*dpy
, int scrnum
,
395 const struct options
*opts
,
396 Bool coreProfile
, Bool es2Profile
, Bool limits
,
400 XSetWindowAttributes attr
;
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
);
417 ctx
= create_context_with_config(dpy
, fbconfigs
[0],
418 coreProfile
, es2Profile
,
420 if (!ctx
&& opts
->allowDirect
&& !coreProfile
) {
422 ctx
= create_context_with_config(dpy
, fbconfigs
[0],
423 coreProfile
, es2Profile
, False
);
426 visinfo
= glXGetVisualFromFBConfig(dpy
, fbconfigs
[0]);
429 else if (!coreProfile
&& !es2Profile
) {
430 visinfo
= choose_xvisinfo(dpy
, scrnum
);
432 ctx
= glXCreateContext(dpy
, visinfo
, NULL
, opts
->allowDirect
);
436 if (!visinfo
&& !coreProfile
&& !es2Profile
) {
437 fprintf(stderr
, "Error: couldn't find RGB GLX visual or fbconfig\n");
442 if (!coreProfile
&& !es2Profile
)
443 fprintf(stderr
, "Error: glXCreateContext failed\n");
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");
493 /* Get list of GL extensions */
494 if (coreProfile
&& extfuncs
.GetStringi
)
495 glExtensions
= build_core_profile_extension_list(&extfuncs
);
498 glExtensions
= (char *) glGetString(GL_EXTENSIONS
);
501 CheckError(__LINE__
);
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");
509 strcpy(displayName
, DisplayString(dpy
));
510 colon
= strrchr(displayName
, ':');
512 period
= strchr(colon
, '.');
517 printf("display: %s screen: %d\n", displayName
, scrnum
);
519 printf("direct rendering: ");
520 if (glXIsDirect(dpy
, ctx
)) {
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");
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"))
550 print_gpu_memory_info(glExtensions
);
551 printf("OpenGL vendor string: %s\n", glVendor
);
552 printf("OpenGL renderer string: %s\n", glRenderer
);
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
564 char *v
= (char *) glGetString(GL_SHADING_LANGUAGE_VERSION
);
565 printf("%s shading language version string: %s\n", oglstring
, v
);
568 CheckError(__LINE__
);
569 #ifdef GL_VERSION_3_0
570 if (version
>= 30 && !es2Profile
) {
572 glGetIntegerv(GL_CONTEXT_FLAGS
, &flags
);
573 printf("%s context flags: %s\n", oglstring
, context_flags_string(flags
));
576 CheckError(__LINE__
);
577 #ifdef GL_VERSION_3_2
578 if (version
>= 32 && !es2Profile
) {
580 glGetIntegerv(GL_CONTEXT_PROFILE_MASK
, &mask
);
581 printf("%s profile mask: %s\n", oglstring
, profile_mask_string(mask
));
585 CheckError(__LINE__
);
587 if (opts
->mode
!= Brief
) {
588 printf("%s extensions:\n", oglstring
);
589 print_extension_list(glExtensions
, opts
->singleLine
);
593 print_limits(glExtensions
, oglstring
, version
, &extfuncs
);
600 fprintf(stderr
, "Error: glXMakeCurrent failed\n");
603 glXDestroyContext(dpy
, ctx
);
605 XDestroyWindow(dpy
, win
);
612 visual_class_name(int cls
)
616 return "StaticColor";
618 return "PseudoColor";
626 return "DirectColor";
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
);
645 visual_class_abbrev(int cls
)
666 visual_render_type_name(int type
)
669 case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT
:
671 case GLX_RGBA_FLOAT_BIT_ARB
:
675 case GLX_COLOR_INDEX_BIT
:
677 case GLX_RGBA_BIT
| GLX_COLOR_INDEX_BIT
:
685 caveat_string(int caveat
)
688 #ifdef GLX_EXT_visual_rating
689 case GLX_SLOW_VISUAL_EXT
:
691 case GLX_NON_CONFORMANT_VISUAL_EXT
:
705 get_visual_attribs(Display
*dpy
, XVisualInfo
*vInfo
,
706 struct visual_attribs
*attribs
)
708 const char *ext
= glXQueryExtensionsString(dpy
, vInfo
->screen
);
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
;
717 attribs
->klass
= vInfo
->class;
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
)
729 glXGetConfig(dpy
, vInfo
, GLX_BUFFER_SIZE
, &attribs
->bufferSize
);
730 glXGetConfig(dpy
, vInfo
, GLX_LEVEL
, &attribs
->level
);
731 glXGetConfig(dpy
, vInfo
, GLX_RGBA
, &rgba
);
733 attribs
->render_type
= GLX_RGBA_BIT
;
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
);
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
);
781 attribs
->visualCaveat
= GLX_NONE_EXT
;
784 attribs
->visualCaveat
= 0;
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
);
796 #ifdef GLX_VERSION_1_3
799 glx_token_to_visual_class(int visual_type
)
801 switch (visual_type
) {
804 case GLX_DIRECT_COLOR
:
806 case GLX_PSEUDO_COLOR
:
808 case GLX_STATIC_COLOR
:
812 case GLX_STATIC_GRAY
:
821 get_fbconfig_attribs(Display
*dpy
, GLXFBConfig fbconfig
,
822 struct visual_attribs
*attribs
)
824 const char *ext
= glXQueryExtensionsString(dpy
, 0);
828 memset(attribs
, 0, sizeof(struct visual_attribs
));
830 glXGetFBConfigAttrib(dpy
, fbconfig
, GLX_FBCONFIG_ID
, &attribs
->id
);
832 vInfo
= glXGetVisualFromFBConfig(dpy
, fbconfig
);
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
);
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
;
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
;
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
);
916 print_visual_attribs_verbose(const struct visual_attribs
*attribs
,
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
));
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");
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
);
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");
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",
983 visual_class_abbrev(attribs
->klass
),
984 attribs
->transparentType
!= GLX_NONE
,
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' : '.',
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
,
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");
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",
1026 visual_class_name(attribs
->klass
),
1027 attribs
->transparentType
!= GLX_NONE
,
1028 attribs
->bufferSize
,
1030 visual_render_type_name(attribs
->render_type
),
1031 attribs
->doubleBuffer
,
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
,
1042 attribs
->stencilSize
,
1043 attribs
->accumRedSize
, attribs
->accumGreenSize
,
1044 attribs
->accumBlueSize
, attribs
->accumAlphaSize
,
1045 attribs
->numSamples
, attribs
->numMultisample
,
1052 print_visual_info(Display
*dpy
, int scrnum
, InfoMode mode
)
1054 XVisualInfo theTemplate
;
1055 XVisualInfo
*visuals
;
1056 int numVisuals
, numGlxVisuals
;
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
);
1067 for (i
= 0; i
< numVisuals
; i
++) {
1068 if (get_visual_attribs(dpy
, &visuals
[i
], &attribs
))
1072 if (numGlxVisuals
== 0)
1075 printf("%d GLX Visuals\n", numGlxVisuals
);
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
))
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
);
1098 #ifdef GLX_VERSION_1_3
1101 print_fbconfig_info(Display
*dpy
, int scrnum
, InfoMode mode
)
1103 int numFBConfigs
= 0;
1104 struct visual_attribs attribs
;
1105 GLXFBConfig
*fbconfigs
;
1108 /* get list of all fbconfigs on this screen */
1109 fbconfigs
= glXGetFBConfigs(dpy
, scrnum
, &numFBConfigs
);
1111 if (numFBConfigs
== 0) {
1116 printf("%d GLXFBConfigs:\n", numFBConfigs
);
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
);
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.
1151 mesa_hack(Display
*dpy
, int scrnum
)
1153 static int attribs
[] = {
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,
1167 XVisualInfo
*visinfo
;
1169 visinfo
= glXChooseVisual(dpy
, scrnum
, attribs
);
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.
1181 find_best_visual(Display
*dpy
, int scrnum
)
1183 XVisualInfo theTemplate
;
1184 XVisualInfo
*visuals
;
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
)
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 */
1232 main(int argc
, char *argv
[])
1235 int numScreens
, scrnum
;
1236 struct options opts
;
1239 parse_args(argc
, argv
, &opts
);
1241 dpy
= XOpenDisplay(opts
.displayName
);
1243 fprintf(stderr
, "Error: unable to open display %s\n",
1244 XDisplayName(opts
.displayName
));
1248 if (opts
.findBest
) {
1251 b
= find_best_visual(dpy
, 0);
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
);
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
);
1274 if (scrnum
+ 1 < numScreens
)