132001f49Smrg/*
232001f49Smrg * Copyright (C) 2009  VMware, Inc.
332001f49Smrg * Copyright (C) 1999-2006  Brian Paul
432001f49Smrg * All Rights Reserved.
532001f49Smrg *
632001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
732001f49Smrg * copy of this software and associated documentation files (the "Software"),
832001f49Smrg * to deal in the Software without restriction, including without limitation
932001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1032001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1132001f49Smrg * Software is furnished to do so, subject to the following conditions:
1232001f49Smrg *
1332001f49Smrg * The above copyright notice and this permission notice shall be included
1432001f49Smrg * in all copies or substantial portions of the Software.
1532001f49Smrg *
1632001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1732001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1932001f49Smrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2032001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2132001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2232001f49Smrg */
2332001f49Smrg
2432001f49Smrg
2532001f49Smrg/*
2632001f49Smrg * This program is a work-alike of the GLX glxinfo program.
2732001f49Smrg * Command line options:
2832001f49Smrg *  -t                     print wide table
2932001f49Smrg *  -v                     print verbose information
3032001f49Smrg *  -b                     only print ID of "best" visual on screen 0
3132001f49Smrg *  -l                     print interesting OpenGL limits (added 5 Sep 2002)
3232001f49Smrg */
3332001f49Smrg
3432001f49Smrg
357ec3b29aSmrg#include <windows.h>
367ec3b29aSmrg#include <stdbool.h>
3732001f49Smrg#include <GL/glew.h>
3832001f49Smrg#include <GL/wglew.h>
3932001f49Smrg#include <assert.h>
4032001f49Smrg#include <stdio.h>
4132001f49Smrg#include <string.h>
4232001f49Smrg#include <stdlib.h>
4332001f49Smrg#include "glinfo_common.h"
4432001f49Smrg
4532001f49Smrg
467ec3b29aSmrgstatic GLboolean have_WGL_ARB_create_context;
477ec3b29aSmrgstatic GLboolean have_WGL_ARB_pbuffer;
487ec3b29aSmrgstatic GLboolean have_WGL_ARB_pixel_format;
497ec3b29aSmrgstatic GLboolean have_WGL_ARB_multisample;
507ec3b29aSmrgstatic GLboolean have_WGL_ARB_framebuffer_sRGB; /* or EXT version */
517ec3b29aSmrg
527ec3b29aSmrgstatic PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB_func;
537ec3b29aSmrgstatic PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB_func;
5432001f49Smrg
5532001f49Smrg
567ec3b29aSmrg/**
577ec3b29aSmrg * An extension of PIXELFORMATDESCRIPTOR to handle multisample, etc.
587ec3b29aSmrg */
597ec3b29aSmrgstruct format_info {
607ec3b29aSmrg   PIXELFORMATDESCRIPTOR pfd;
617ec3b29aSmrg   int sampleBuffers, numSamples;
627ec3b29aSmrg   int transparency;
637ec3b29aSmrg   bool floatComponents;
647ec3b29aSmrg   bool srgb;
657ec3b29aSmrg   bool draw_to_bitmap;
667ec3b29aSmrg   bool draw_to_pbuffer;
677ec3b29aSmrg   bool gdi_drawing;
687ec3b29aSmrg};
697ec3b29aSmrg
7032001f49Smrg
7132001f49Smrgstatic LRESULT CALLBACK
7232001f49SmrgWndProc(HWND hWnd,
7332001f49Smrg        UINT uMsg,
7432001f49Smrg        WPARAM wParam,
7532001f49Smrg        LPARAM lParam )
7632001f49Smrg{
7732001f49Smrg   switch (uMsg) {
7832001f49Smrg   case WM_DESTROY:
7932001f49Smrg      PostQuitMessage(0);
8032001f49Smrg      break;
8132001f49Smrg   default:
8232001f49Smrg      return DefWindowProc(hWnd, uMsg, wParam, lParam);
8332001f49Smrg   }
8432001f49Smrg
8532001f49Smrg   return 0;
8632001f49Smrg}
8732001f49Smrg
8832001f49Smrg
8932001f49Smrgstatic void
907ec3b29aSmrgprint_screen_info(HDC _hdc, const struct options *opts, GLboolean coreProfile)
9132001f49Smrg{
9232001f49Smrg   WNDCLASS wc;
9332001f49Smrg   HWND win;
9432001f49Smrg   HGLRC ctx;
9532001f49Smrg   int visinfo;
9632001f49Smrg   HDC hdc;
9732001f49Smrg   PIXELFORMATDESCRIPTOR pfd;
9832001f49Smrg   int version;
9932001f49Smrg   const char *oglString = "OpenGL";
10032001f49Smrg
10132001f49Smrg   memset(&wc, 0, sizeof wc);
10232001f49Smrg   wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
10332001f49Smrg   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
10432001f49Smrg   wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
10532001f49Smrg   wc.lpfnWndProc = WndProc;
10632001f49Smrg   wc.lpszClassName = "wglinfo";
10732001f49Smrg   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
10832001f49Smrg   RegisterClass(&wc);
10932001f49Smrg
11032001f49Smrg   win = CreateWindowEx(0,
11132001f49Smrg                        wc.lpszClassName,
11232001f49Smrg                        "wglinfo",
11332001f49Smrg                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
11432001f49Smrg                        CW_USEDEFAULT,
11532001f49Smrg                        CW_USEDEFAULT,
11632001f49Smrg                        CW_USEDEFAULT,
11732001f49Smrg                        CW_USEDEFAULT,
11832001f49Smrg                        NULL,
11932001f49Smrg                        NULL,
12032001f49Smrg                        wc.hInstance,
12132001f49Smrg                        NULL);
12232001f49Smrg   if (!win) {
12332001f49Smrg      fprintf(stderr, "Couldn't create window\n");
12432001f49Smrg      return;
12532001f49Smrg   }
12632001f49Smrg
12732001f49Smrg   hdc = GetDC(win);
12832001f49Smrg   if (!hdc) {
12932001f49Smrg      fprintf(stderr, "Couldn't obtain HDC\n");
13032001f49Smrg      return;
13132001f49Smrg   }
13232001f49Smrg
1337ec3b29aSmrg   memset(&pfd, 0, sizeof(pfd));
13432001f49Smrg   pfd.cColorBits = 3;
13532001f49Smrg   pfd.cRedBits = 1;
13632001f49Smrg   pfd.cGreenBits = 1;
13732001f49Smrg   pfd.cBlueBits = 1;
13832001f49Smrg   pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
13932001f49Smrg   pfd.iLayerType = PFD_MAIN_PLANE;
14032001f49Smrg   pfd.iPixelType = PFD_TYPE_RGBA;
14132001f49Smrg   pfd.nSize = sizeof(pfd);
14232001f49Smrg   pfd.nVersion = 1;
14332001f49Smrg
14432001f49Smrg   visinfo = ChoosePixelFormat(hdc, &pfd);
14532001f49Smrg   if (!visinfo) {
14632001f49Smrg      pfd.dwFlags |= PFD_DOUBLEBUFFER;
14732001f49Smrg      visinfo = ChoosePixelFormat(hdc, &pfd);
14832001f49Smrg   }
14932001f49Smrg
15032001f49Smrg   if (!visinfo) {
15132001f49Smrg      fprintf(stderr, "Error: couldn't find RGB WGL visual\n");
15232001f49Smrg      return;
15332001f49Smrg   }
15432001f49Smrg
15532001f49Smrg   SetPixelFormat(hdc, visinfo, &pfd);
15632001f49Smrg   ctx = wglCreateContext(hdc);
15732001f49Smrg   if (!ctx) {
15832001f49Smrg      fprintf(stderr, "Error: wglCreateContext failed\n");
15932001f49Smrg      return;
16032001f49Smrg   }
16132001f49Smrg
16232001f49Smrg   if (wglMakeCurrent(hdc, ctx)) {
16332001f49Smrg#if defined(WGL_ARB_extensions_string)
16432001f49Smrg      PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB_func =
16532001f49Smrg         (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
16632001f49Smrg#endif
1677ec3b29aSmrg      const char *glVendor, *glRenderer, *glVersion, *glExtensions;
1687ec3b29aSmrg      const char *wglExtensions = NULL;
16932001f49Smrg      struct ext_functions extfuncs;
17032001f49Smrg
17132001f49Smrg#if defined(WGL_ARB_extensions_string)
17232001f49Smrg      if (wglGetExtensionsStringARB_func) {
1737ec3b29aSmrg         wglExtensions = wglGetExtensionsStringARB_func(hdc);
1747ec3b29aSmrg         if (extension_supported("WGL_ARB_pbuffer", wglExtensions)) {
1757ec3b29aSmrg            have_WGL_ARB_pbuffer = GL_TRUE;
1767ec3b29aSmrg         }
1777ec3b29aSmrg         if (extension_supported("WGL_ARB_pixel_format", wglExtensions)) {
1787ec3b29aSmrg            have_WGL_ARB_pixel_format = GL_TRUE;
1797ec3b29aSmrg         }
1807ec3b29aSmrg         if (extension_supported("WGL_ARB_multisample", wglExtensions)) {
1817ec3b29aSmrg            have_WGL_ARB_multisample = GL_TRUE;
1827ec3b29aSmrg         }
1837ec3b29aSmrg         if (extension_supported("WGL_ARB_create_context", wglExtensions)) {
1847ec3b29aSmrg            have_WGL_ARB_create_context = GL_TRUE;
1857ec3b29aSmrg         }
1867ec3b29aSmrg         if (extension_supported("WGL_ARB_framebuffer_sRGB", wglExtensions) ||
1877ec3b29aSmrg             extension_supported("WGL_EXT_framebuffer_sRGB", wglExtensions)) {
1887ec3b29aSmrg            have_WGL_ARB_framebuffer_sRGB = GL_TRUE;
18932001f49Smrg         }
19032001f49Smrg      }
19132001f49Smrg#endif
1927ec3b29aSmrg
1937ec3b29aSmrg      if (coreProfile && have_WGL_ARB_create_context) {
1947ec3b29aSmrg         /* Try to create a new, core context */
1957ec3b29aSmrg         HGLRC core_ctx = 0;
1967ec3b29aSmrg         int i;
1977ec3b29aSmrg
1987ec3b29aSmrg         wglCreateContextAttribsARB_func =
1997ec3b29aSmrg            (PFNWGLCREATECONTEXTATTRIBSARBPROC)
2007ec3b29aSmrg            wglGetProcAddress("wglCreateContextAttribsARB");
2017ec3b29aSmrg         assert(wglCreateContextAttribsARB_func);
2027ec3b29aSmrg         if (!wglCreateContextAttribsARB_func) {
2037ec3b29aSmrg            printf("Failed to get wglCreateContextAttribsARB pointer.");
2047ec3b29aSmrg            return;
2057ec3b29aSmrg         }
2067ec3b29aSmrg
2077ec3b29aSmrg         for (i = 0; gl_versions[i].major > 0; i++) {
2087ec3b29aSmrg            int attribs[10], n;
2097ec3b29aSmrg
2107ec3b29aSmrg            /* don't bother below GL 3.1 */
2117ec3b29aSmrg            if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) {
2127ec3b29aSmrg               break;
2137ec3b29aSmrg            }
2147ec3b29aSmrg
2157ec3b29aSmrg            n = 0;
2167ec3b29aSmrg            attribs[n++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
2177ec3b29aSmrg            attribs[n++] = gl_versions[i].major;
2187ec3b29aSmrg            attribs[n++] = WGL_CONTEXT_MINOR_VERSION_ARB;
2197ec3b29aSmrg            attribs[n++] = gl_versions[i].minor;
2207ec3b29aSmrg            if (gl_versions[i].major * 10 + gl_versions[i].minor > 31) {
2217ec3b29aSmrg               attribs[n++] = WGL_CONTEXT_PROFILE_MASK_ARB;
2227ec3b29aSmrg               attribs[n++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
2237ec3b29aSmrg            }
2247ec3b29aSmrg            attribs[n++] = 0;
2257ec3b29aSmrg
2267ec3b29aSmrg            core_ctx = wglCreateContextAttribsARB_func(hdc, 0, attribs);
2277ec3b29aSmrg            if (core_ctx) {
2287ec3b29aSmrg               break;
2297ec3b29aSmrg            }
2307ec3b29aSmrg         }
2317ec3b29aSmrg
2327ec3b29aSmrg         if (!core_ctx) {
2337ec3b29aSmrg            printf("Failed to create core profile context.\n");
2347ec3b29aSmrg            return;
2357ec3b29aSmrg         }
2367ec3b29aSmrg
2377ec3b29aSmrg         ctx = core_ctx;
2387ec3b29aSmrg         if (!wglMakeCurrent(hdc, ctx)) {
2397ec3b29aSmrg            printf("Failed to bind core profile context.\n");
2407ec3b29aSmrg            return;
2417ec3b29aSmrg         }
2427ec3b29aSmrg         oglString = "OpenGL core profile";
2437ec3b29aSmrg      }
2447ec3b29aSmrg      else {
2457ec3b29aSmrg         coreProfile = GL_FALSE;
24632001f49Smrg      }
24732001f49Smrg
24832001f49Smrg      extfuncs.GetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)
24932001f49Smrg         wglGetProcAddress("glGetProgramivARB");
25032001f49Smrg      extfuncs.GetStringi = (PFNGLGETSTRINGIPROC)
25132001f49Smrg         wglGetProcAddress("glGetStringi");
25232001f49Smrg      extfuncs.GetConvolutionParameteriv = (GETCONVOLUTIONPARAMETERIVPROC)
25332001f49Smrg         wglGetProcAddress("glGetConvolutionParameteriv");
25432001f49Smrg
2557ec3b29aSmrg      glVendor = (const char *) glGetString(GL_VENDOR);
2567ec3b29aSmrg      glRenderer = (const char *) glGetString(GL_RENDERER);
2577ec3b29aSmrg      glVersion = (const char *) glGetString(GL_VERSION);
2587ec3b29aSmrg      if (coreProfile) {
2597ec3b29aSmrg         glExtensions = build_core_profile_extension_list(&extfuncs);
2607ec3b29aSmrg      }
2617ec3b29aSmrg      else {
2627ec3b29aSmrg         glExtensions = (const char *) glGetString(GL_EXTENSIONS);
2637ec3b29aSmrg      }
2647ec3b29aSmrg
2657ec3b29aSmrg      /*
2667ec3b29aSmrg       * Print all the vendor, version, extension strings.
2677ec3b29aSmrg       */
2687ec3b29aSmrg
2697ec3b29aSmrg      if (!coreProfile) {
2707ec3b29aSmrg         if (wglExtensions && opts->mode != Brief) {
2717ec3b29aSmrg            printf("WGL extensions:\n");
2727ec3b29aSmrg            print_extension_list(wglExtensions, opts->singleLine);
2737ec3b29aSmrg         }
2747ec3b29aSmrg         printf("OpenGL vendor string: %s\n", glVendor);
2757ec3b29aSmrg         printf("OpenGL renderer string: %s\n", glRenderer);
2767ec3b29aSmrg      }
2777ec3b29aSmrg
2787ec3b29aSmrg      printf("%s version string: %s\n", oglString, glVersion);
2797ec3b29aSmrg
28032001f49Smrg      version = (glVersion[0] - '0') * 10 + (glVersion[2] - '0');
28132001f49Smrg
2827ec3b29aSmrg#ifdef GL_VERSION_2_0
2837ec3b29aSmrg      if (version >= 20) {
2847ec3b29aSmrg         char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
2857ec3b29aSmrg         printf("%s shading language version string: %s\n", oglString, v);
2867ec3b29aSmrg      }
2877ec3b29aSmrg#endif
2887ec3b29aSmrg#ifdef GL_VERSION_3_0
2897ec3b29aSmrg      if (version >= 30) {
2907ec3b29aSmrg         GLint flags;
2917ec3b29aSmrg         glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
2927ec3b29aSmrg         printf("%s context flags: %s\n", oglString, context_flags_string(flags));
2937ec3b29aSmrg      }
2947ec3b29aSmrg#endif
2957ec3b29aSmrg#ifdef GL_VERSION_3_2
2967ec3b29aSmrg      if (version >= 32) {
2977ec3b29aSmrg         GLint mask;
2987ec3b29aSmrg         glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
2997ec3b29aSmrg         printf("%s profile mask: %s\n", oglString, profile_mask_string(mask));
3007ec3b29aSmrg      }
3017ec3b29aSmrg#endif
3027ec3b29aSmrg
3037ec3b29aSmrg      if (opts->mode != Brief) {
3047ec3b29aSmrg         printf("%s extensions:\n", oglString);
3057ec3b29aSmrg         print_extension_list(glExtensions, opts->singleLine);
3067ec3b29aSmrg      }
3077ec3b29aSmrg
3087ec3b29aSmrg      if (opts->limits) {
30932001f49Smrg         print_limits(glExtensions, oglString, version, &extfuncs);
31032001f49Smrg      }
31132001f49Smrg   }
31232001f49Smrg   else {
31332001f49Smrg      fprintf(stderr, "Error: wglMakeCurrent failed\n");
31432001f49Smrg   }
31532001f49Smrg
31632001f49Smrg   DestroyWindow(win);
31732001f49Smrg}
31832001f49Smrg
31932001f49Smrg
32032001f49Smrgstatic const char *
32132001f49Smrgvisual_render_type_name(BYTE iPixelType)
32232001f49Smrg{
32332001f49Smrg   switch (iPixelType) {
32432001f49Smrg      case PFD_TYPE_RGBA:
32532001f49Smrg         return "rgba";
32632001f49Smrg      case PFD_TYPE_COLORINDEX:
32732001f49Smrg         return "ci";
32832001f49Smrg      default:
32932001f49Smrg         return "";
33032001f49Smrg   }
33132001f49Smrg}
33232001f49Smrg
33332001f49Smrgstatic void
3347ec3b29aSmrgprint_visual_attribs_verbose(int iPixelFormat, const struct format_info *info)
33532001f49Smrg{
3367ec3b29aSmrg   printf("Visual ID: %x generic=%d drawToWindow=%d drawToBitmap=%d drawToPBuffer=%d GDI=%d\n",
33732001f49Smrg          iPixelFormat,
3387ec3b29aSmrg          info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
3397ec3b29aSmrg          info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0,
3407ec3b29aSmrg          info->draw_to_bitmap,
3417ec3b29aSmrg          info->draw_to_pbuffer,
3427ec3b29aSmrg          info->gdi_drawing);
34332001f49Smrg   printf("    bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
3447ec3b29aSmrg          0 /* info->pfd.bufferSize */, 0 /* info->pfd.level */,
3457ec3b29aSmrg	  visual_render_type_name(info->pfd.iPixelType),
3467ec3b29aSmrg          info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 1 : 0,
3477ec3b29aSmrg          info->pfd.dwFlags & PFD_STEREO ? 1 : 0);
3487ec3b29aSmrg   printf("    rgba: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d float=%c sRGB=%c\n",
3497ec3b29aSmrg          info->pfd.cRedBits, info->pfd.cGreenBits,
3507ec3b29aSmrg          info->pfd.cBlueBits, info->pfd.cAlphaBits,
3517ec3b29aSmrg          info->floatComponents ? 'Y' : 'N',
3527ec3b29aSmrg          info->srgb ? 'Y' : 'N');
35332001f49Smrg   printf("    cAuxBuffers=%d cDepthBits=%d cStencilBits=%d\n",
3547ec3b29aSmrg          info->pfd.cAuxBuffers, info->pfd.cDepthBits, info->pfd.cStencilBits);
35532001f49Smrg   printf("    accum: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d\n",
3567ec3b29aSmrg          info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits,
3577ec3b29aSmrg          info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits);
35832001f49Smrg   printf("    multiSample=%d  multiSampleBuffers=%d\n",
3597ec3b29aSmrg          info->numSamples, info->sampleBuffers);
3607ec3b29aSmrg   if (info->pfd.dwFlags & PFD_SWAP_EXCHANGE)
3617ec3b29aSmrg      printf("    swapMethod = Exchange\n");
3627ec3b29aSmrg   else if (info->pfd.dwFlags & PFD_SWAP_COPY)
3637ec3b29aSmrg      printf("    swapMethod = Copy\n");
3647ec3b29aSmrg   else
3657ec3b29aSmrg      printf("    swapMethod = Undefined\n");
36632001f49Smrg}
36732001f49Smrg
36832001f49Smrg
36932001f49Smrgstatic void
37032001f49Smrgprint_visual_attribs_short_header(void)
37132001f49Smrg{
3727ec3b29aSmrg   printf("    visual   x   bf lv rg d st colorbuffer   sr ax dp st accumbuffer  ms \n");
3737ec3b29aSmrg   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");
3747ec3b29aSmrg   printf("-------------------------------------------------------------------------\n");
37532001f49Smrg}
37632001f49Smrg
37732001f49Smrg
37832001f49Smrgstatic void
3797ec3b29aSmrgprint_visual_attribs_short(int iPixelFormat, const struct format_info *info)
38032001f49Smrg{
3817ec3b29aSmrg   printf("0x%03x %2d  %2d %2d %3d %2d %c%c %c  %c %2d %2d %2d %2d %c  %c %2d %2d %2d",
38232001f49Smrg          iPixelFormat,
3837ec3b29aSmrg          info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
3847ec3b29aSmrg          info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0,
3857ec3b29aSmrg          info->transparency,
3867ec3b29aSmrg          info->pfd.cColorBits,
3877ec3b29aSmrg          0 /* info->pfd.level */,
3887ec3b29aSmrg          info->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : ' ',
3897ec3b29aSmrg          info->pfd.iPixelType == PFD_TYPE_COLORINDEX ? 'c' : ' ',
3907ec3b29aSmrg          info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.',
3917ec3b29aSmrg          info->pfd.dwFlags & PFD_STEREO ? 'y' : '.',
3927ec3b29aSmrg          info->pfd.cRedBits, info->pfd.cGreenBits,
3937ec3b29aSmrg          info->pfd.cBlueBits, info->pfd.cAlphaBits,
3947ec3b29aSmrg          info->floatComponents ? 'f' : '.',
3957ec3b29aSmrg          info->srgb ? 's' : '.',
3967ec3b29aSmrg          info->pfd.cAuxBuffers,
3977ec3b29aSmrg          info->pfd.cDepthBits,
3987ec3b29aSmrg          info->pfd.cStencilBits
39932001f49Smrg          );
40032001f49Smrg
4017ec3b29aSmrg   printf(" %2d %2d %2d %2d %2d %1d\n",
4027ec3b29aSmrg          info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits,
4037ec3b29aSmrg          info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits,
4047ec3b29aSmrg          info->numSamples, info->sampleBuffers);
40532001f49Smrg}
40632001f49Smrg
40732001f49Smrg
40832001f49Smrgstatic void
40932001f49Smrgprint_visual_attribs_long_header(void)
41032001f49Smrg{
4117ec3b29aSmrg printf("Vis   Vis   Visual Trans  buff lev render DB ste  r   g   b   a      s  aux dep ste  accum buffers  MS   MS \n");
4127ec3b29aSmrg 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");
4137ec3b29aSmrg printf("------------------------------------------------------------------------------------------------------------\n");
41432001f49Smrg}
41532001f49Smrg
41632001f49Smrg
41732001f49Smrgstatic void
4187ec3b29aSmrgprint_visual_attribs_long(int iPixelFormat, const struct format_info *info)
41932001f49Smrg{
4207ec3b29aSmrg   printf("0x%3x %2d %11d %2d     %2d %2d  %4s %3d %3d %3d %3d %3d %3d",
42132001f49Smrg          iPixelFormat,
4227ec3b29aSmrg          info->pfd.dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
4237ec3b29aSmrg          info->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0,
42432001f49Smrg          0,
4257ec3b29aSmrg          0 /* info->pfd.bufferSize */,
4267ec3b29aSmrg          0 /* info->pfd.level */,
4277ec3b29aSmrg          visual_render_type_name(info->pfd.iPixelType),
4287ec3b29aSmrg          info->pfd.dwFlags & PFD_DOUBLEBUFFER ? 1 : 0,
4297ec3b29aSmrg          info->pfd.dwFlags & PFD_STEREO ? 1 : 0,
4307ec3b29aSmrg          info->pfd.cRedBits, info->pfd.cGreenBits,
4317ec3b29aSmrg          info->pfd.cBlueBits, info->pfd.cAlphaBits
43232001f49Smrg          );
43332001f49Smrg
4347ec3b29aSmrg   printf("  %c   %c %3d %4d %2d %3d %3d %3d %3d  %2d  %2d\n",
4357ec3b29aSmrg          info->floatComponents ? 'f' : '.',
4367ec3b29aSmrg          info->srgb ? 's' : '.',
4377ec3b29aSmrg          info->pfd.cAuxBuffers,
4387ec3b29aSmrg          info->pfd.cDepthBits,
4397ec3b29aSmrg          info->pfd.cStencilBits,
4407ec3b29aSmrg          info->pfd.cAccumRedBits, info->pfd.cAccumGreenBits,
4417ec3b29aSmrg          info->pfd.cAccumBlueBits, info->pfd.cAccumAlphaBits,
4427ec3b29aSmrg          info->sampleBuffers, info->numSamples
44332001f49Smrg          );
44432001f49Smrg}
44532001f49Smrg
44632001f49Smrg
4477ec3b29aSmrg/**
4487ec3b29aSmrg * Wrapper for wglGetPixelFormatAttribivARB()
4497ec3b29aSmrg * \param attrib  the WGL_* attribute to query
4507ec3b29aSmrg * \return value of the attribute, or 0 if failure
4517ec3b29aSmrg */
4527ec3b29aSmrgstatic int
4537ec3b29aSmrgget_pf_attrib(HDC hdc, int pf, int attrib)
4547ec3b29aSmrg{
4557ec3b29aSmrg   int layer = 0, value;
4567ec3b29aSmrg   assert(have_WGL_ARB_pixel_format);
4577ec3b29aSmrg   if (wglGetPixelFormatAttribivARB_func(hdc, pf, layer, 1, &attrib, &value)) {
4587ec3b29aSmrg      return value;
4597ec3b29aSmrg   }
4607ec3b29aSmrg   else {
4617ec3b29aSmrg      return 0;
4627ec3b29aSmrg   }
4637ec3b29aSmrg}
4647ec3b29aSmrg
4657ec3b29aSmrg
4667ec3b29aSmrg/**
4677ec3b29aSmrg * Fill in the format_info fields for the pixel format given by pf.
4687ec3b29aSmrg */
4697ec3b29aSmrgstatic GLboolean
4707ec3b29aSmrgget_format_info(HDC hdc, int pf, struct format_info *info)
4717ec3b29aSmrg{
4727ec3b29aSmrg   memset(info, 0, sizeof(*info));
4737ec3b29aSmrg
4747ec3b29aSmrg   if (have_WGL_ARB_pixel_format) {
4757ec3b29aSmrg      int swapMethod;
4767ec3b29aSmrg
4777ec3b29aSmrg      info->pfd.dwFlags = 0;
4787ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_DRAW_TO_WINDOW_ARB))
4797ec3b29aSmrg         info->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
4807ec3b29aSmrg      if (!get_pf_attrib(hdc, pf, WGL_ACCELERATION_ARB))
4817ec3b29aSmrg         info->pfd.dwFlags |= PFD_GENERIC_FORMAT;
4827ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_SUPPORT_OPENGL_ARB))
4837ec3b29aSmrg         info->pfd.dwFlags |= PFD_SUPPORT_OPENGL;
4847ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_DOUBLE_BUFFER_ARB))
4857ec3b29aSmrg         info->pfd.dwFlags |= PFD_DOUBLEBUFFER;
4867ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_STEREO_ARB))
4877ec3b29aSmrg         info->pfd.dwFlags |= PFD_STEREO;
4887ec3b29aSmrg
4897ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_DRAW_TO_BITMAP_ARB))
4907ec3b29aSmrg         info->draw_to_bitmap = true;
4917ec3b29aSmrg      if (have_WGL_ARB_pbuffer && get_pf_attrib(hdc, pf, WGL_DRAW_TO_PBUFFER_ARB))
4927ec3b29aSmrg         info->draw_to_pbuffer = true;
4937ec3b29aSmrg      if (get_pf_attrib(hdc, pf, WGL_SUPPORT_GDI_ARB))
4947ec3b29aSmrg         info->gdi_drawing = true;
4957ec3b29aSmrg
4967ec3b29aSmrg      swapMethod = get_pf_attrib(hdc, pf, WGL_SWAP_METHOD_ARB);
4977ec3b29aSmrg      if (swapMethod == WGL_SWAP_EXCHANGE_ARB)
4987ec3b29aSmrg         info->pfd.dwFlags |= PFD_SWAP_EXCHANGE;
4997ec3b29aSmrg      else if (swapMethod == WGL_SWAP_COPY_ARB)
5007ec3b29aSmrg         info->pfd.dwFlags |= PFD_SWAP_COPY;
5017ec3b29aSmrg
5027ec3b29aSmrg      int pixel_type = get_pf_attrib(hdc, pf, WGL_PIXEL_TYPE_ARB);
5037ec3b29aSmrg      if (pixel_type == WGL_TYPE_RGBA_ARB)
5047ec3b29aSmrg         info->pfd.iPixelType = PFD_TYPE_RGBA;
5057ec3b29aSmrg      else if (pixel_type == WGL_TYPE_COLORINDEX_ARB)
5067ec3b29aSmrg         info->pfd.iPixelType = PFD_TYPE_COLORINDEX;
5077ec3b29aSmrg      else if (pixel_type == WGL_TYPE_RGBA_FLOAT_ARB) {
5087ec3b29aSmrg         info->pfd.iPixelType = PFD_TYPE_RGBA;
5097ec3b29aSmrg         info->floatComponents = true;
5107ec3b29aSmrg      }
5117ec3b29aSmrg
5127ec3b29aSmrg      info->pfd.cColorBits = get_pf_attrib(hdc, pf, WGL_COLOR_BITS_ARB);
5137ec3b29aSmrg      info->pfd.cRedBits = get_pf_attrib(hdc, pf, WGL_RED_BITS_ARB);
5147ec3b29aSmrg      info->pfd.cGreenBits = get_pf_attrib(hdc, pf, WGL_GREEN_BITS_ARB);
5157ec3b29aSmrg      info->pfd.cBlueBits = get_pf_attrib(hdc, pf, WGL_BLUE_BITS_ARB);
5167ec3b29aSmrg      info->pfd.cAlphaBits = get_pf_attrib(hdc, pf, WGL_ALPHA_BITS_ARB);
5177ec3b29aSmrg
5187ec3b29aSmrg      info->pfd.cDepthBits = get_pf_attrib(hdc, pf, WGL_DEPTH_BITS_ARB);
5197ec3b29aSmrg      info->pfd.cStencilBits = get_pf_attrib(hdc, pf, WGL_STENCIL_BITS_ARB);
5207ec3b29aSmrg      info->pfd.cAuxBuffers = get_pf_attrib(hdc, pf, WGL_AUX_BUFFERS_ARB);
5217ec3b29aSmrg
5227ec3b29aSmrg      info->pfd.cAccumRedBits = get_pf_attrib(hdc, pf,
5237ec3b29aSmrg                                              WGL_ACCUM_RED_BITS_ARB);
5247ec3b29aSmrg      info->pfd.cAccumGreenBits = get_pf_attrib(hdc, pf,
5257ec3b29aSmrg                                                WGL_ACCUM_GREEN_BITS_ARB);
5267ec3b29aSmrg      info->pfd.cAccumBlueBits = get_pf_attrib(hdc, pf,
5277ec3b29aSmrg                                               WGL_ACCUM_BLUE_BITS_ARB);
5287ec3b29aSmrg      info->pfd.cAccumAlphaBits = get_pf_attrib(hdc, pf,
5297ec3b29aSmrg                                                WGL_ACCUM_ALPHA_BITS_ARB);
5307ec3b29aSmrg
5317ec3b29aSmrg      info->sampleBuffers = get_pf_attrib(hdc, pf, WGL_SAMPLE_BUFFERS_ARB);
5327ec3b29aSmrg      info->numSamples = get_pf_attrib(hdc, pf, WGL_SAMPLES_ARB);
5337ec3b29aSmrg
5347ec3b29aSmrg      info->transparency = get_pf_attrib(hdc, pf, WGL_TRANSPARENT_ARB);
5357ec3b29aSmrg
5367ec3b29aSmrg      if (have_WGL_ARB_framebuffer_sRGB) {
5377ec3b29aSmrg         info->srgb = get_pf_attrib(hdc, pf, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
5387ec3b29aSmrg      }
5397ec3b29aSmrg   }
5407ec3b29aSmrg   else {
5417ec3b29aSmrg      if (!DescribePixelFormat(hdc, pf,
5427ec3b29aSmrg                               sizeof(PIXELFORMATDESCRIPTOR), &info->pfd))
5437ec3b29aSmrg         return GL_FALSE;
5447ec3b29aSmrg   }
5457ec3b29aSmrg   return GL_TRUE;
5467ec3b29aSmrg}
5477ec3b29aSmrg
5487ec3b29aSmrg
5497ec3b29aSmrg
55032001f49Smrgstatic void
55132001f49Smrgprint_visual_info(HDC hdc, InfoMode mode)
55232001f49Smrg{
5537ec3b29aSmrg   struct format_info info;
55432001f49Smrg   int numVisuals, numWglVisuals;
55532001f49Smrg   int i;
55632001f49Smrg
5577ec3b29aSmrg   wglGetPixelFormatAttribivARB_func =
5587ec3b29aSmrg      (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
5597ec3b29aSmrg      wglGetProcAddress("wglGetPixelFormatAttribivARB");
5607ec3b29aSmrg
5617ec3b29aSmrg   /* Get number of visuals / pixel formats */
5627ec3b29aSmrg   numVisuals = DescribePixelFormat(hdc, 1,
5637ec3b29aSmrg                                    sizeof(PIXELFORMATDESCRIPTOR), NULL);
5647ec3b29aSmrg   printf("%d Regular pixel formats\n", numVisuals);
5657ec3b29aSmrg
5667ec3b29aSmrg   if (have_WGL_ARB_pixel_format) {
5677ec3b29aSmrg      int numExtVisuals = get_pf_attrib(hdc, 0, WGL_NUMBER_PIXEL_FORMATS_ARB);
5687ec3b29aSmrg      printf("%d Regular + Extended pixel formats\n", numExtVisuals);
5697ec3b29aSmrg      numVisuals = numExtVisuals;
5707ec3b29aSmrg   }
5717ec3b29aSmrg
57232001f49Smrg   if (numVisuals == 0)
57332001f49Smrg      return;
57432001f49Smrg
57532001f49Smrg   numWglVisuals = 0;
57632001f49Smrg   for (i = 0; i < numVisuals; i++) {
5777ec3b29aSmrg      if(!DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &info.pfd))
57832001f49Smrg	 continue;
57932001f49Smrg
5807ec3b29aSmrg      //if(!(info.pfd.dwFlags & PFD_SUPPORT_OPENGL))
58132001f49Smrg      //   continue;
58232001f49Smrg
58332001f49Smrg      ++numWglVisuals;
58432001f49Smrg   }
58532001f49Smrg
58632001f49Smrg   printf("%d WGL Visuals\n", numWglVisuals);
58732001f49Smrg
58832001f49Smrg   if (mode == Normal)
58932001f49Smrg      print_visual_attribs_short_header();
59032001f49Smrg   else if (mode == Wide)
59132001f49Smrg      print_visual_attribs_long_header();
59232001f49Smrg
59332001f49Smrg   for (i = 0; i < numVisuals; i++) {
5947ec3b29aSmrg      get_format_info(hdc, i, &info);
59532001f49Smrg
59632001f49Smrg      if (mode == Verbose)
5977ec3b29aSmrg	 print_visual_attribs_verbose(i, &info);
59832001f49Smrg      else if (mode == Normal)
5997ec3b29aSmrg         print_visual_attribs_short(i, &info);
60032001f49Smrg      else if (mode == Wide)
6017ec3b29aSmrg         print_visual_attribs_long(i, &info);
60232001f49Smrg   }
60332001f49Smrg   printf("\n");
60432001f49Smrg}
60532001f49Smrg
60632001f49Smrg
60732001f49Smrg/*
60832001f49Smrg * Examine all visuals to find the so-called best one.
60932001f49Smrg * We prefer deepest RGBA buffer with depth, stencil and accum
61032001f49Smrg * that has no caveats.
61132001f49Smrg */
61232001f49Smrgstatic int
61332001f49Smrgfind_best_visual(HDC hdc)
61432001f49Smrg{
61532001f49Smrg#if 0
61632001f49Smrg   XVisualInfo theTemplate;
61732001f49Smrg   XVisualInfo *visuals;
61832001f49Smrg   int numVisuals;
61932001f49Smrg   long mask;
62032001f49Smrg   int i;
62132001f49Smrg   struct visual_attribs bestVis;
62232001f49Smrg
62332001f49Smrg   /* get list of all visuals on this screen */
62432001f49Smrg   theTemplate.screen = scrnum;
62532001f49Smrg   mask = VisualScreenMask;
62632001f49Smrg   visuals = XGetVisualInfo(hdc, mask, &theTemplate, &numVisuals);
62732001f49Smrg
62832001f49Smrg   /* init bestVis with first visual info */
62932001f49Smrg   get_visual_attribs(hdc, &visuals[0], &bestVis);
63032001f49Smrg
63132001f49Smrg   /* try to find a "better" visual */
63232001f49Smrg   for (i = 1; i < numVisuals; i++) {
63332001f49Smrg      struct visual_attribs vis;
63432001f49Smrg
63532001f49Smrg      get_visual_attribs(hdc, &visuals[i], &vis);
63632001f49Smrg
63732001f49Smrg      /* always skip visuals with caveats */
63832001f49Smrg      if (vis.visualCaveat != GLX_NONE_EXT)
63932001f49Smrg         continue;
64032001f49Smrg
64132001f49Smrg      /* see if this vis is better than bestVis */
64232001f49Smrg      if ((!bestVis.supportsGL && vis.supportsGL) ||
64332001f49Smrg          (bestVis.visualCaveat != GLX_NONE_EXT) ||
64432001f49Smrg          (bestVis.iPixelType != vis.iPixelType) ||
64532001f49Smrg          (!bestVis.doubleBuffer && vis.doubleBuffer) ||
64632001f49Smrg          (bestVis.cRedBits < vis.cRedBits) ||
64732001f49Smrg          (bestVis.cGreenBits < vis.cGreenBits) ||
64832001f49Smrg          (bestVis.cBlueBits < vis.cBlueBits) ||
64932001f49Smrg          (bestVis.cAlphaBits < vis.cAlphaBits) ||
65032001f49Smrg          (bestVis.cDepthBits < vis.cDepthBits) ||
65132001f49Smrg          (bestVis.cStencilBits < vis.cStencilBits) ||
65232001f49Smrg          (bestVis.cAccumRedBits < vis.cAccumRedBits)) {
65332001f49Smrg         /* found a better visual */
65432001f49Smrg         bestVis = vis;
65532001f49Smrg      }
65632001f49Smrg   }
65732001f49Smrg
65832001f49Smrg   return bestVis.id;
65932001f49Smrg#else
66032001f49Smrg   return 0;
66132001f49Smrg#endif
66232001f49Smrg}
66332001f49Smrg
66432001f49Smrg
66532001f49Smrg
66632001f49Smrgint
66732001f49Smrgmain(int argc, char *argv[])
66832001f49Smrg{
66932001f49Smrg   HDC hdc;
6707ec3b29aSmrg   struct options opts;
67132001f49Smrg
6727ec3b29aSmrg   parse_args(argc, argv, &opts);
67332001f49Smrg
67432001f49Smrg   hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
67532001f49Smrg
6767ec3b29aSmrg   if (opts.findBest) {
67732001f49Smrg      int b;
67832001f49Smrg      b = find_best_visual(hdc);
67932001f49Smrg      printf("%d\n", b);
68032001f49Smrg   }
68132001f49Smrg   else {
6827ec3b29aSmrg      print_screen_info(hdc, &opts, GL_FALSE);
6837ec3b29aSmrg      printf("\n");
6847ec3b29aSmrg      print_screen_info(hdc, &opts, GL_TRUE);
68532001f49Smrg      printf("\n");
6867ec3b29aSmrg      if (opts.mode != Brief) {
6877ec3b29aSmrg         print_visual_info(hdc, opts.mode);
6887ec3b29aSmrg      }
68932001f49Smrg   }
69032001f49Smrg
69132001f49Smrg   return 0;
69232001f49Smrg}
693