1/* 2 * Copyright (C) 2009 VMware, Inc. 3 * Copyright (C) 1999-2006 Brian Paul 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24 25/* 26 * This program is a work-alike of the GLX glxinfo program. 27 * Command line options: 28 * -t print wide table 29 * -v print verbose information 30 * -b only print ID of "best" visual on screen 0 31 * -l print interesting OpenGL limits (added 5 Sep 2002) 32 */ 33 34 35#include <windows.h> 36#include <stdbool.h> 37#include <GL/glew.h> 38#include <GL/wglew.h> 39#include <assert.h> 40#include <stdio.h> 41#include <string.h> 42#include <stdlib.h> 43#include "glinfo_common.h" 44 45 46static GLboolean have_WGL_ARB_create_context; 47static GLboolean have_WGL_ARB_pbuffer; 48static GLboolean have_WGL_ARB_pixel_format; 49static GLboolean have_WGL_ARB_multisample; 50static GLboolean have_WGL_ARB_framebuffer_sRGB; /* or EXT version */ 51 52static PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB_func; 53static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB_func; 54 55 56/** 57 * An extension of PIXELFORMATDESCRIPTOR to handle multisample, etc. 58 */ 59struct format_info { 60 PIXELFORMATDESCRIPTOR pfd; 61 int sampleBuffers, numSamples; 62 int transparency; 63 bool floatComponents; 64 bool srgb; 65 bool draw_to_bitmap; 66 bool draw_to_pbuffer; 67 bool gdi_drawing; 68}; 69 70 71static LRESULT CALLBACK 72WndProc(HWND hWnd, 73 UINT uMsg, 74 WPARAM wParam, 75 LPARAM lParam ) 76{ 77 switch (uMsg) { 78 case WM_DESTROY: 79 PostQuitMessage(0); 80 break; 81 default: 82 return DefWindowProc(hWnd, uMsg, wParam, lParam); 83 } 84 85 return 0; 86} 87 88 89static void 90print_screen_info(HDC _hdc, const struct options *opts, GLboolean coreProfile) 91{ 92 WNDCLASS wc; 93 HWND win; 94 HGLRC ctx; 95 int visinfo; 96 HDC hdc; 97 PIXELFORMATDESCRIPTOR pfd; 98 int version; 99 const char *oglString = "OpenGL"; 100 101 memset(&wc, 0, sizeof wc); 102 wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); 103 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 104 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 105 wc.lpfnWndProc = WndProc; 106 wc.lpszClassName = "wglinfo"; 107 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 108 RegisterClass(&wc); 109 110 win = CreateWindowEx(0, 111 wc.lpszClassName, 112 "wglinfo", 113 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 114 CW_USEDEFAULT, 115 CW_USEDEFAULT, 116 CW_USEDEFAULT, 117 CW_USEDEFAULT, 118 NULL, 119 NULL, 120 wc.hInstance, 121 NULL); 122 if (!win) { 123 fprintf(stderr, "Couldn't create window\n"); 124 return; 125 } 126 127 hdc = GetDC(win); 128 if (!hdc) { 129 fprintf(stderr, "Couldn't obtain HDC\n"); 130 return; 131 } 132 133 memset(&pfd, 0, sizeof(pfd)); 134 pfd.cColorBits = 3; 135 pfd.cRedBits = 1; 136 pfd.cGreenBits = 1; 137 pfd.cBlueBits = 1; 138 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; 139 pfd.iLayerType = PFD_MAIN_PLANE; 140 pfd.iPixelType = PFD_TYPE_RGBA; 141 pfd.nSize = sizeof(pfd); 142 pfd.nVersion = 1; 143 144 visinfo = ChoosePixelFormat(hdc, &pfd); 145 if (!visinfo) { 146 pfd.dwFlags |= PFD_DOUBLEBUFFER; 147 visinfo = ChoosePixelFormat(hdc, &pfd); 148 } 149 150 if (!visinfo) { 151 fprintf(stderr, "Error: couldn't find RGB WGL visual\n"); 152 return; 153 } 154 155 SetPixelFormat(hdc, visinfo, &pfd); 156 ctx = wglCreateContext(hdc); 157 if (!ctx) { 158 fprintf(stderr, "Error: wglCreateContext failed\n"); 159 return; 160 } 161 162 if (wglMakeCurrent(hdc, ctx)) { 163#if defined(WGL_ARB_extensions_string) 164 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB_func = 165 (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); 166#endif 167 const char *glVendor, *glRenderer, *glVersion, *glExtensions; 168 const char *wglExtensions = NULL; 169 struct ext_functions extfuncs; 170 171#if defined(WGL_ARB_extensions_string) 172 if (wglGetExtensionsStringARB_func) { 173 wglExtensions = wglGetExtensionsStringARB_func(hdc); 174 if (extension_supported("WGL_ARB_pbuffer", wglExtensions)) { 175 have_WGL_ARB_pbuffer = GL_TRUE; 176 } 177 if (extension_supported("WGL_ARB_pixel_format", wglExtensions)) { 178 have_WGL_ARB_pixel_format = GL_TRUE; 179 } 180 if (extension_supported("WGL_ARB_multisample", wglExtensions)) { 181 have_WGL_ARB_multisample = GL_TRUE; 182 } 183 if (extension_supported("WGL_ARB_create_context", wglExtensions)) { 184 have_WGL_ARB_create_context = GL_TRUE; 185 } 186 if (extension_supported("WGL_ARB_framebuffer_sRGB", wglExtensions) || 187 extension_supported("WGL_EXT_framebuffer_sRGB", wglExtensions)) { 188 have_WGL_ARB_framebuffer_sRGB = GL_TRUE; 189 } 190 } 191#endif 192 193 if (coreProfile && have_WGL_ARB_create_context) { 194 /* Try to create a new, core context */ 195 HGLRC core_ctx = 0; 196 int i; 197 198 wglCreateContextAttribsARB_func = 199 (PFNWGLCREATECONTEXTATTRIBSARBPROC) 200 wglGetProcAddress("wglCreateContextAttribsARB"); 201 assert(wglCreateContextAttribsARB_func); 202 if (!wglCreateContextAttribsARB_func) { 203 printf("Failed to get wglCreateContextAttribsARB pointer."); 204 return; 205 } 206 207 for (i = 0; gl_versions[i].major > 0; i++) { 208 int attribs[10], n; 209 210 /* don't bother below GL 3.1 */ 211 if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) { 212 break; 213 } 214 215 n = 0; 216 attribs[n++] = WGL_CONTEXT_MAJOR_VERSION_ARB; 217 attribs[n++] = gl_versions[i].major; 218 attribs[n++] = WGL_CONTEXT_MINOR_VERSION_ARB; 219 attribs[n++] = gl_versions[i].minor; 220 if (gl_versions[i].major * 10 + gl_versions[i].minor > 31) { 221 attribs[n++] = WGL_CONTEXT_PROFILE_MASK_ARB; 222 attribs[n++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; 223 } 224 attribs[n++] = 0; 225 226 core_ctx = wglCreateContextAttribsARB_func(hdc, 0, attribs); 227 if (core_ctx) { 228 break; 229 } 230 } 231 232 if (!core_ctx) { 233 printf("Failed to create core profile context.\n"); 234 return; 235 } 236 237 ctx = core_ctx; 238 if (!wglMakeCurrent(hdc, ctx)) { 239 printf("Failed to bind core profile context.\n"); 240 return; 241 } 242 oglString = "OpenGL core profile"; 243 } 244 else { 245 coreProfile = GL_FALSE; 246 } 247 248 extfuncs.GetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) 249 wglGetProcAddress("glGetProgramivARB"); 250 extfuncs.GetStringi = (PFNGLGETSTRINGIPROC) 251 wglGetProcAddress("glGetStringi"); 252 extfuncs.GetConvolutionParameteriv = (GETCONVOLUTIONPARAMETERIVPROC) 253 wglGetProcAddress("glGetConvolutionParameteriv"); 254 255 glVendor = (const char *) glGetString(GL_VENDOR); 256 glRenderer = (const char *) glGetString(GL_RENDERER); 257 glVersion = (const char *) glGetString(GL_VERSION); 258 if (coreProfile) { 259 glExtensions = build_core_profile_extension_list(&extfuncs); 260 } 261 else { 262 glExtensions = (const char *) glGetString(GL_EXTENSIONS); 263 } 264 265 /* 266 * Print all the vendor, version, extension strings. 267 */ 268 269 if (!coreProfile) { 270 if (wglExtensions && opts->mode != Brief) { 271 printf("WGL extensions:\n"); 272 print_extension_list(wglExtensions, opts->singleLine); 273 } 274 printf("OpenGL vendor string: %s\n", glVendor); 275 printf("OpenGL renderer string: %s\n", glRenderer); 276 } 277 278 printf("%s version string: %s\n", oglString, glVersion); 279 280 version = (glVersion[0] - '0') * 10 + (glVersion[2] - '0'); 281 282#ifdef GL_VERSION_2_0 283 if (version >= 20) { 284 char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); 285 printf("%s shading language version string: %s\n", oglString, v); 286 } 287#endif 288#ifdef GL_VERSION_3_0 289 if (version >= 30) { 290 GLint flags; 291 glGetIntegerv(GL_CONTEXT_FLAGS, &flags); 292 printf("%s context flags: %s\n", oglString, context_flags_string(flags)); 293 } 294#endif 295#ifdef GL_VERSION_3_2 296 if (version >= 32) { 297 GLint mask; 298 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); 299 printf("%s profile mask: %s\n", oglString, profile_mask_string(mask)); 300 } 301#endif 302 303 if (opts->mode != Brief) { 304 printf("%s extensions:\n", oglString); 305 print_extension_list(glExtensions, opts->singleLine); 306 } 307 308 if (opts->limits) { 309 print_limits(glExtensions, oglString, version, &extfuncs); 310 } 311 } 312 else { 313 fprintf(stderr, "Error: wglMakeCurrent failed\n"); 314 } 315 316 DestroyWindow(win); 317} 318 319 320static const char * 321visual_render_type_name(BYTE iPixelType) 322{ 323 switch (iPixelType) { 324 case PFD_TYPE_RGBA: 325 return "rgba"; 326 case PFD_TYPE_COLORINDEX: 327 return "ci"; 328 default: 329 return ""; 330 } 331} 332 333static void 334print_visual_attribs_verbose(int iPixelFormat, const struct format_info *info) 335{ 336 printf("Visual ID: %x generic=%d drawToWindow=%d drawToBitmap=%d drawToPBuffer=%d GDI=%d\n", 337 iPixelFormat, 338 info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0, 339 info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0, 340 info->draw_to_bitmap, 341 info->draw_to_pbuffer, 342 info->gdi_drawing); 343 printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", 344 0 /* info->pfd.bufferSize */, 0 /* info->pfd.level */, 345 visual_render_type_name(info->pfd.iPixelType), 346 info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 1 : 0, 347 info->pfd.dwFlags & PFD_STEREO ? 1 : 0); 348 printf(" rgba: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d float=%c sRGB=%c\n", 349 info->pfd.cRedBits, info->pfd.cGreenBits, 350 info->pfd.cBlueBits, info->pfd.cAlphaBits, 351 info->floatComponents ? 'Y' : 'N', 352 info->srgb ? 'Y' : 'N'); 353 printf(" cAuxBuffers=%d cDepthBits=%d cStencilBits=%d\n", 354 info->pfd.cAuxBuffers, info->pfd.cDepthBits, info->pfd.cStencilBits); 355 printf(" accum: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d\n", 356 info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits, 357 info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits); 358 printf(" multiSample=%d multiSampleBuffers=%d\n", 359 info->numSamples, info->sampleBuffers); 360 if (info->pfd.dwFlags & PFD_SWAP_EXCHANGE) 361 printf(" swapMethod = Exchange\n"); 362 else if (info->pfd.dwFlags & PFD_SWAP_COPY) 363 printf(" swapMethod = Copy\n"); 364 else 365 printf(" swapMethod = Undefined\n"); 366} 367 368 369static void 370print_visual_attribs_short_header(void) 371{ 372 printf(" visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms \n"); 373 printf(" id gen win sp sz l ci b ro r g b a F gb bf th cl r g b a ns b\n"); 374 printf("-------------------------------------------------------------------------\n"); 375} 376 377 378static void 379print_visual_attribs_short(int iPixelFormat, const struct format_info *info) 380{ 381 printf("0x%03x %2d %2d %2d %3d %2d %c%c %c %c %2d %2d %2d %2d %c %c %2d %2d %2d", 382 iPixelFormat, 383 info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0, 384 info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0, 385 info->transparency, 386 info->pfd.cColorBits, 387 0 /* info->pfd.level */, 388 info->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : ' ', 389 info->pfd.iPixelType == PFD_TYPE_COLORINDEX ? 'c' : ' ', 390 info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.', 391 info->pfd.dwFlags & PFD_STEREO ? 'y' : '.', 392 info->pfd.cRedBits, info->pfd.cGreenBits, 393 info->pfd.cBlueBits, info->pfd.cAlphaBits, 394 info->floatComponents ? 'f' : '.', 395 info->srgb ? 's' : '.', 396 info->pfd.cAuxBuffers, 397 info->pfd.cDepthBits, 398 info->pfd.cStencilBits 399 ); 400 401 printf(" %2d %2d %2d %2d %2d %1d\n", 402 info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits, 403 info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits, 404 info->numSamples, info->sampleBuffers); 405} 406 407 408static void 409print_visual_attribs_long_header(void) 410{ 411 printf("Vis Vis Visual Trans buff lev render DB ste r g b a s aux dep ste accum buffers MS MS \n"); 412 printf(" ID Depth Type parent size el type reo sz sz sz sz flt rgb buf th ncl r g b a num bufs\n"); 413 printf("------------------------------------------------------------------------------------------------------------\n"); 414} 415 416 417static void 418print_visual_attribs_long(int iPixelFormat, const struct format_info *info) 419{ 420 printf("0x%3x %2d %11d %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d", 421 iPixelFormat, 422 info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0, 423 info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0, 424 0, 425 0 /* info->pfd.bufferSize */, 426 0 /* info->pfd.level */, 427 visual_render_type_name(info->pfd.iPixelType), 428 info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 1 : 0, 429 info->pfd.dwFlags & PFD_STEREO ? 1 : 0, 430 info->pfd.cRedBits, info->pfd.cGreenBits, 431 info->pfd.cBlueBits, info->pfd.cAlphaBits 432 ); 433 434 printf(" %c %c %3d %4d %2d %3d %3d %3d %3d %2d %2d\n", 435 info->floatComponents ? 'f' : '.', 436 info->srgb ? 's' : '.', 437 info->pfd.cAuxBuffers, 438 info->pfd.cDepthBits, 439 info->pfd.cStencilBits, 440 info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits, 441 info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits, 442 info->sampleBuffers, info->numSamples 443 ); 444} 445 446 447/** 448 * Wrapper for wglGetPixelFormatAttribivARB() 449 * \param attrib the WGL_* attribute to query 450 * \return value of the attribute, or 0 if failure 451 */ 452static int 453get_pf_attrib(HDC hdc, int pf, int attrib) 454{ 455 int layer = 0, value; 456 assert(have_WGL_ARB_pixel_format); 457 if (wglGetPixelFormatAttribivARB_func(hdc, pf, layer, 1, &attrib, &value)) { 458 return value; 459 } 460 else { 461 return 0; 462 } 463} 464 465 466/** 467 * Fill in the format_info fields for the pixel format given by pf. 468 */ 469static GLboolean 470get_format_info(HDC hdc, int pf, struct format_info *info) 471{ 472 memset(info, 0, sizeof(*info)); 473 474 if (have_WGL_ARB_pixel_format) { 475 int swapMethod; 476 477 info->pfd.dwFlags = 0; 478 if (get_pf_attrib(hdc, pf, WGL_DRAW_TO_WINDOW_ARB)) 479 info->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; 480 if (!get_pf_attrib(hdc, pf, WGL_ACCELERATION_ARB)) 481 info->pfd.dwFlags |= PFD_GENERIC_FORMAT; 482 if (get_pf_attrib(hdc, pf, WGL_SUPPORT_OPENGL_ARB)) 483 info->pfd.dwFlags |= PFD_SUPPORT_OPENGL; 484 if (get_pf_attrib(hdc, pf, WGL_DOUBLE_BUFFER_ARB)) 485 info->pfd.dwFlags |= PFD_DOUBLEBUFFER; 486 if (get_pf_attrib(hdc, pf, WGL_STEREO_ARB)) 487 info->pfd.dwFlags |= PFD_STEREO; 488 489 if (get_pf_attrib(hdc, pf, WGL_DRAW_TO_BITMAP_ARB)) 490 info->draw_to_bitmap = true; 491 if (have_WGL_ARB_pbuffer && get_pf_attrib(hdc, pf, WGL_DRAW_TO_PBUFFER_ARB)) 492 info->draw_to_pbuffer = true; 493 if (get_pf_attrib(hdc, pf, WGL_SUPPORT_GDI_ARB)) 494 info->gdi_drawing = true; 495 496 swapMethod = get_pf_attrib(hdc, pf, WGL_SWAP_METHOD_ARB); 497 if (swapMethod == WGL_SWAP_EXCHANGE_ARB) 498 info->pfd.dwFlags |= PFD_SWAP_EXCHANGE; 499 else if (swapMethod == WGL_SWAP_COPY_ARB) 500 info->pfd.dwFlags |= PFD_SWAP_COPY; 501 502 int pixel_type = get_pf_attrib(hdc, pf, WGL_PIXEL_TYPE_ARB); 503 if (pixel_type == WGL_TYPE_RGBA_ARB) 504 info->pfd.iPixelType = PFD_TYPE_RGBA; 505 else if (pixel_type == WGL_TYPE_COLORINDEX_ARB) 506 info->pfd.iPixelType = PFD_TYPE_COLORINDEX; 507 else if (pixel_type == WGL_TYPE_RGBA_FLOAT_ARB) { 508 info->pfd.iPixelType = PFD_TYPE_RGBA; 509 info->floatComponents = true; 510 } 511 512 info->pfd.cColorBits = get_pf_attrib(hdc, pf, WGL_COLOR_BITS_ARB); 513 info->pfd.cRedBits = get_pf_attrib(hdc, pf, WGL_RED_BITS_ARB); 514 info->pfd.cGreenBits = get_pf_attrib(hdc, pf, WGL_GREEN_BITS_ARB); 515 info->pfd.cBlueBits = get_pf_attrib(hdc, pf, WGL_BLUE_BITS_ARB); 516 info->pfd.cAlphaBits = get_pf_attrib(hdc, pf, WGL_ALPHA_BITS_ARB); 517 518 info->pfd.cDepthBits = get_pf_attrib(hdc, pf, WGL_DEPTH_BITS_ARB); 519 info->pfd.cStencilBits = get_pf_attrib(hdc, pf, WGL_STENCIL_BITS_ARB); 520 info->pfd.cAuxBuffers = get_pf_attrib(hdc, pf, WGL_AUX_BUFFERS_ARB); 521 522 info->pfd.cAccumRedBits = get_pf_attrib(hdc, pf, 523 WGL_ACCUM_RED_BITS_ARB); 524 info->pfd.cAccumGreenBits = get_pf_attrib(hdc, pf, 525 WGL_ACCUM_GREEN_BITS_ARB); 526 info->pfd.cAccumBlueBits = get_pf_attrib(hdc, pf, 527 WGL_ACCUM_BLUE_BITS_ARB); 528 info->pfd.cAccumAlphaBits = get_pf_attrib(hdc, pf, 529 WGL_ACCUM_ALPHA_BITS_ARB); 530 531 info->sampleBuffers = get_pf_attrib(hdc, pf, WGL_SAMPLE_BUFFERS_ARB); 532 info->numSamples = get_pf_attrib(hdc, pf, WGL_SAMPLES_ARB); 533 534 info->transparency = get_pf_attrib(hdc, pf, WGL_TRANSPARENT_ARB); 535 536 if (have_WGL_ARB_framebuffer_sRGB) { 537 info->srgb = get_pf_attrib(hdc, pf, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); 538 } 539 } 540 else { 541 if (!DescribePixelFormat(hdc, pf, 542 sizeof(PIXELFORMATDESCRIPTOR), &info->pfd)) 543 return GL_FALSE; 544 } 545 return GL_TRUE; 546} 547 548 549 550static void 551print_visual_info(HDC hdc, InfoMode mode) 552{ 553 struct format_info info; 554 int numVisuals, numWglVisuals; 555 int i; 556 557 wglGetPixelFormatAttribivARB_func = 558 (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) 559 wglGetProcAddress("wglGetPixelFormatAttribivARB"); 560 561 /* Get number of visuals / pixel formats */ 562 numVisuals = DescribePixelFormat(hdc, 1, 563 sizeof(PIXELFORMATDESCRIPTOR), NULL); 564 printf("%d Regular pixel formats\n", numVisuals); 565 566 if (have_WGL_ARB_pixel_format) { 567 int numExtVisuals = get_pf_attrib(hdc, 0, WGL_NUMBER_PIXEL_FORMATS_ARB); 568 printf("%d Regular + Extended pixel formats\n", numExtVisuals); 569 numVisuals = numExtVisuals; 570 } 571 572 if (numVisuals == 0) 573 return; 574 575 numWglVisuals = 0; 576 for (i = 0; i < numVisuals; i++) { 577 if(!DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &info.pfd)) 578 continue; 579 580 //if(!(info.pfd.dwFlags & PFD_SUPPORT_OPENGL)) 581 // continue; 582 583 ++numWglVisuals; 584 } 585 586 printf("%d WGL Visuals\n", numWglVisuals); 587 588 if (mode == Normal) 589 print_visual_attribs_short_header(); 590 else if (mode == Wide) 591 print_visual_attribs_long_header(); 592 593 for (i = 0; i < numVisuals; i++) { 594 get_format_info(hdc, i, &info); 595 596 if (mode == Verbose) 597 print_visual_attribs_verbose(i, &info); 598 else if (mode == Normal) 599 print_visual_attribs_short(i, &info); 600 else if (mode == Wide) 601 print_visual_attribs_long(i, &info); 602 } 603 printf("\n"); 604} 605 606 607/* 608 * Examine all visuals to find the so-called best one. 609 * We prefer deepest RGBA buffer with depth, stencil and accum 610 * that has no caveats. 611 */ 612static int 613find_best_visual(HDC hdc) 614{ 615#if 0 616 XVisualInfo theTemplate; 617 XVisualInfo *visuals; 618 int numVisuals; 619 long mask; 620 int i; 621 struct visual_attribs bestVis; 622 623 /* get list of all visuals on this screen */ 624 theTemplate.screen = scrnum; 625 mask = VisualScreenMask; 626 visuals = XGetVisualInfo(hdc, mask, &theTemplate, &numVisuals); 627 628 /* init bestVis with first visual info */ 629 get_visual_attribs(hdc, &visuals[0], &bestVis); 630 631 /* try to find a "better" visual */ 632 for (i = 1; i < numVisuals; i++) { 633 struct visual_attribs vis; 634 635 get_visual_attribs(hdc, &visuals[i], &vis); 636 637 /* always skip visuals with caveats */ 638 if (vis.visualCaveat != GLX_NONE_EXT) 639 continue; 640 641 /* see if this vis is better than bestVis */ 642 if ((!bestVis.supportsGL && vis.supportsGL) || 643 (bestVis.visualCaveat != GLX_NONE_EXT) || 644 (bestVis.iPixelType != vis.iPixelType) || 645 (!bestVis.doubleBuffer && vis.doubleBuffer) || 646 (bestVis.cRedBits < vis.cRedBits) || 647 (bestVis.cGreenBits < vis.cGreenBits) || 648 (bestVis.cBlueBits < vis.cBlueBits) || 649 (bestVis.cAlphaBits < vis.cAlphaBits) || 650 (bestVis.cDepthBits < vis.cDepthBits) || 651 (bestVis.cStencilBits < vis.cStencilBits) || 652 (bestVis.cAccumRedBits < vis.cAccumRedBits)) { 653 /* found a better visual */ 654 bestVis = vis; 655 } 656 } 657 658 return bestVis.id; 659#else 660 return 0; 661#endif 662} 663 664 665 666int 667main(int argc, char *argv[]) 668{ 669 HDC hdc; 670 struct options opts; 671 672 parse_args(argc, argv, &opts); 673 674 hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 675 676 if (opts.findBest) { 677 int b; 678 b = find_best_visual(hdc); 679 printf("%d\n", b); 680 } 681 else { 682 print_screen_info(hdc, &opts, GL_FALSE); 683 printf("\n"); 684 print_screen_info(hdc, &opts, GL_TRUE); 685 printf("\n"); 686 if (opts.mode != Brief) { 687 print_visual_info(hdc, opts.mode); 688 } 689 } 690 691 return 0; 692} 693