xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

indirect.c (83215B)


      1 /*
      2  * File: indirect.c
      3  * Purpose: A GLX implementation that uses Windows OpenGL library
      4  *
      5  * Authors: Alexander Gottwald
      6  *          Jon TURNEY
      7  *
      8  * Copyright (c) Jon TURNEY 2009
      9  * Copyright (c) Alexander Gottwald 2004
     10  *
     11  * Portions of this file are copied from GL/apple/indirect.c,
     12  * which contains the following copyright:
     13  *
     14  * Copyright (c) 2007, 2008, 2009 Apple Inc.
     15  * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
     16  * Copyright (c) 2002 Greg Parker. All Rights Reserved.
     17  *
     18  * Portions of this file are copied from Mesa's xf86glx.c,
     19  * which contains the following copyright:
     20  *
     21  * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
     22  * All Rights Reserved.
     23  *
     24  *
     25  * Permission is hereby granted, free of charge, to any person obtaining a
     26  * copy of this software and associated documentation files (the "Software"),
     27  * to deal in the Software without restriction, including without limitation
     28  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     29  * and/or sell copies of the Software, and to permit persons to whom the
     30  * Software is furnished to do so, subject to the following conditions:
     31  *
     32  * The above copyright notice and this permission notice shall be included in
     33  * all copies or substantial portions of the Software.
     34  *
     35  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     36  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     37  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     38  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     39  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     40  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     41  * DEALINGS IN THE SOFTWARE.
     42  */
     43 
     44 /*
     45   TODO:
     46   - hook up remaining unimplemented extensions
     47   - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then
     48     using GdiFlush and/or glFinish
     49   - pbuffer clobbering: we don't get async notification, but can we arrange to emit the
     50     event when we notice it's been clobbered? at the very least, check if it's been clobbered
     51     before using it?
     52   - XGetImage() doesn't work on pixmaps; need to do more work to make the format and location
     53     of the native pixmap compatible
     54   - implement GLX_EXT_texture_from_pixmap in terms of WGL_ARB_render_texture
     55     (not quite straightforward as we will have to create a pbuffer and copy the pixmap texture
     56      into it)
     57 */
     58 
     59 /*
     60   Assumptions:
     61   - the __GLXConfig * we get handed back ones we are made (so we can extend the structure
     62     with privates) and never get created inside the GLX core
     63 */
     64 
     65 /*
     66   MSDN clarifications:
     67 
     68   It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect
     69   except on metafiles, this seems to mean that as it's ok to supply NULL if the DC
     70   is not for a metafile
     71 
     72   wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL)
     73   is used to make no context current
     74 
     75 */
     76 
     77 #ifdef HAVE_XWIN_CONFIG_H
     78 #include <xwin-config.h>
     79 #endif
     80 
     81 #include "glwindows.h"
     82 #include <glx/glxserver.h>
     83 #include <glx/glxutil.h>
     84 #include <GL/glxtokens.h>
     85 
     86 #include <winpriv.h>
     87 #include <wgl_ext_api.h>
     88 #include <winglobals.h>
     89 #include <indirect.h>
     90 
     91 /* Not yet in w32api */
     92 #ifndef PFD_SUPPORT_DIRECTDRAW
     93 #define PFD_SUPPORT_DIRECTDRAW   0x00002000
     94 #endif
     95 #ifndef PFD_DIRECT3D_ACCELERATED
     96 #define PFD_DIRECT3D_ACCELERATED 0x00004000
     97 #endif
     98 #ifndef PFD_SUPPORT_COMPOSITION
     99 #define PFD_SUPPORT_COMPOSITION  0x00008000
    100 #endif
    101 
    102 
    103 typedef struct  {
    104     int notOpenGL;
    105     int unknownPixelType;
    106     int unaccelerated;
    107 } PixelFormatRejectStats;
    108 
    109 /* ---------------------------------------------------------------------- */
    110 /*
    111  * Various debug helpers
    112  */
    113 
    114 #define GLWIN_DEBUG_HWND(hwnd)  \
    115     if (glxWinDebugSettings.dumpHWND) { \
    116         char buffer[1024]; \
    117         if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
    118         GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
    119     }
    120 
    121 glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0 };
    122 
    123 static void
    124 glxWinInitDebugSettings(void)
    125 {
    126     char *envptr;
    127 
    128     envptr = getenv("GLWIN_ENABLE_DEBUG");
    129     if (envptr != NULL)
    130         glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
    131 
    132     envptr = getenv("GLWIN_ENABLE_TRACE");
    133     if (envptr != NULL)
    134         glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
    135 
    136     envptr = getenv("GLWIN_DUMP_PFD");
    137     if (envptr != NULL)
    138         glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
    139 
    140     envptr = getenv("GLWIN_DUMP_HWND");
    141     if (envptr != NULL)
    142         glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
    143 
    144     envptr = getenv("GLWIN_DUMP_DC");
    145     if (envptr != NULL)
    146         glxWinDebugSettings.dumpDC = (atoi(envptr) == 1);
    147 
    148     envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE");
    149     if (envptr != NULL)
    150         glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1);
    151 
    152     envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE");
    153     if (envptr != NULL)
    154         glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1);
    155 
    156     envptr = getenv("GLWIN_DEBUG_ALL");
    157     if (envptr != NULL) {
    158         glxWinDebugSettings.enableDebug = 1;
    159         glxWinDebugSettings.enableTrace = 1;
    160         glxWinDebugSettings.dumpPFD = 1;
    161         glxWinDebugSettings.dumpHWND = 1;
    162         glxWinDebugSettings.dumpDC = 1;
    163         glxWinDebugSettings.enableGLcallTrace = 1;
    164         glxWinDebugSettings.enableWGLcallTrace = 1;
    165     }
    166 }
    167 
    168 static
    169 const char *
    170 glxWinErrorMessage(void)
    171 {
    172     static char errorbuffer[1024];
    173     unsigned int last_error = GetLastError();
    174 
    175     if (!FormatMessage
    176         (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
    177          FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, last_error, 0,
    178          (LPTSTR) &errorbuffer, sizeof(errorbuffer), NULL)) {
    179         snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error");
    180     }
    181 
    182     if ((errorbuffer[strlen(errorbuffer) - 1] == '\n') ||
    183         (errorbuffer[strlen(errorbuffer) - 1] == '\r'))
    184         errorbuffer[strlen(errorbuffer) - 1] = 0;
    185 
    186     sprintf(errorbuffer + strlen(errorbuffer), " (%08x)", last_error);
    187 
    188     return errorbuffer;
    189 }
    190 
    191 static void pfdOut(const PIXELFORMATDESCRIPTOR * pfd);
    192 
    193 #define DUMP_PFD_FLAG(flag) \
    194     if (pfd->dwFlags & flag) { \
    195         ErrorF("%s%s", pipesym, #flag); \
    196         pipesym = " | "; \
    197     }
    198 
    199 static void
    200 pfdOut(const PIXELFORMATDESCRIPTOR * pfd)
    201 {
    202     const char *pipesym = "";   /* will be set after first flag dump */
    203 
    204     ErrorF("PIXELFORMATDESCRIPTOR:\n");
    205     ErrorF("nSize = %u\n", pfd->nSize);
    206     ErrorF("nVersion = %u\n", pfd->nVersion);
    207     ErrorF("dwFlags = %u = {", (unsigned int)pfd->dwFlags);
    208     DUMP_PFD_FLAG(PFD_DOUBLEBUFFER);
    209     DUMP_PFD_FLAG(PFD_STEREO);
    210     DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW);
    211     DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP);
    212     DUMP_PFD_FLAG(PFD_SUPPORT_GDI);
    213     DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL);
    214     DUMP_PFD_FLAG(PFD_GENERIC_FORMAT);
    215     DUMP_PFD_FLAG(PFD_NEED_PALETTE);
    216     DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE);
    217     DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE);
    218     DUMP_PFD_FLAG(PFD_SWAP_COPY);
    219     DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS);
    220     DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED);
    221     DUMP_PFD_FLAG(PFD_SUPPORT_DIRECTDRAW);
    222     DUMP_PFD_FLAG(PFD_DIRECT3D_ACCELERATED);
    223     DUMP_PFD_FLAG(PFD_SUPPORT_COMPOSITION);
    224     DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE);
    225     DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE);
    226     DUMP_PFD_FLAG(PFD_STEREO_DONTCARE);
    227     ErrorF("}\n");
    228 
    229     ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType,
    230            (pfd->iPixelType ==
    231             PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX"));
    232     ErrorF("cColorBits = %hhu\n", pfd->cColorBits);
    233     ErrorF("cRedBits = %hhu\n", pfd->cRedBits);
    234     ErrorF("cRedShift = %hhu\n", pfd->cRedShift);
    235     ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits);
    236     ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift);
    237     ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits);
    238     ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift);
    239     ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits);
    240     ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift);
    241     ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits);
    242     ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits);
    243     ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits);
    244     ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits);
    245     ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits);
    246     ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits);
    247     ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits);
    248     ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers);
    249     ErrorF("iLayerType = %hhu\n", pfd->iLayerType);
    250     ErrorF("bReserved = %hhu\n", pfd->bReserved);
    251     ErrorF("dwLayerMask = %u\n", (unsigned int)pfd->dwLayerMask);
    252     ErrorF("dwVisibleMask = %u\n", (unsigned int)pfd->dwVisibleMask);
    253     ErrorF("dwDamageMask = %u\n", (unsigned int)pfd->dwDamageMask);
    254     ErrorF("\n");
    255 }
    256 
    257 static const char *
    258 visual_class_name(int cls)
    259 {
    260     switch (cls) {
    261     case GLX_STATIC_COLOR:
    262         return "StaticColor";
    263     case GLX_PSEUDO_COLOR:
    264         return "PseudoColor";
    265     case GLX_STATIC_GRAY:
    266         return "StaticGray";
    267     case GLX_GRAY_SCALE:
    268         return "GrayScale";
    269     case GLX_TRUE_COLOR:
    270         return "TrueColor";
    271     case GLX_DIRECT_COLOR:
    272         return "DirectColor";
    273     default:
    274         return "-none-";
    275     }
    276 }
    277 
    278 static const char *
    279 swap_method_name(int mthd)
    280 {
    281     switch (mthd) {
    282     case GLX_SWAP_EXCHANGE_OML:
    283         return "xchg";
    284     case GLX_SWAP_COPY_OML:
    285         return "copy";
    286     case GLX_SWAP_UNDEFINED_OML:
    287         return "    ";
    288     default:
    289         return "????";
    290     }
    291 }
    292 
    293 static void
    294 fbConfigsDump(unsigned int n, __GLXconfig * c, PixelFormatRejectStats *rejects)
    295 {
    296     LogMessage(X_INFO, "%d fbConfigs\n", n);
    297     LogMessage(X_INFO, "ignored pixel formats: %d not OpenGL, %d unknown pixel type, %d unaccelerated\n",
    298                rejects->notOpenGL, rejects->unknownPixelType, rejects->unaccelerated);
    299 
    300     if (g_iLogVerbose < 3)
    301         return;
    302 
    303     ErrorF
    304         ("pxf vis  fb                      render         Ste                     aux    accum        MS    drawable             Group/ sRGB\n");
    305     ErrorF
    306         ("idx  ID  ID VisualType Depth Lvl RGB CI DB Swap reo  R  G  B  A   Z  S  buf AR AG AB AA  bufs num  W P Pb  Float Trans Caveat cap \n");
    307     ErrorF
    308         ("----------------------------------------------------------------------------------------------------------------------------------\n");
    309 
    310     while (c != NULL) {
    311         unsigned int i = ((GLXWinConfig *) c)->pixelFormatIndex;
    312 
    313         const char *float_col = ".";
    314         if (c->renderType & GLX_RGBA_FLOAT_BIT_ARB) float_col = "s";
    315         if (c->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) float_col = "u";
    316 
    317         ErrorF("%3d %3x %3x "
    318                "%-11s"
    319                " %3d %3d   %s   %s  %s %s  %s  "
    320                "%2d %2d %2d %2d  "
    321                "%2d %2d  "
    322                "%2d  "
    323                "%2d %2d %2d %2d"
    324                "   %2d   %2d"
    325                "  %s %s %s "
    326                "    %s   "
    327                "  %s   "
    328                "  %d %s "
    329                "  %s"
    330                "\n",
    331                i, c->visualID, c->fbconfigID,
    332                visual_class_name(c->visualType),
    333                c->rgbBits ? c->rgbBits : c->indexBits,
    334                c->level,
    335                (c->renderType & GLX_RGBA_BIT) ? "y" : ".",
    336                (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".",
    337                c->doubleBufferMode ? "y" : ".",
    338                swap_method_name(c->swapMethod),
    339                c->stereoMode ? "y" : ".",
    340                c->redBits, c->greenBits, c->blueBits, c->alphaBits,
    341                c->depthBits, c->stencilBits,
    342                c->numAuxBuffers,
    343                c->accumRedBits, c->accumGreenBits, c->accumBlueBits,
    344                c->accumAlphaBits, c->sampleBuffers, c->samples,
    345                (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".",
    346                (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".",
    347                (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".",
    348                float_col,
    349                (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".",
    350                c->visualSelectGroup,
    351                (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " ",
    352                c->sRGBCapable ? "y" : ".");
    353 
    354         c = c->next;
    355     }
    356 }
    357 
    358 /* ---------------------------------------------------------------------- */
    359 /*
    360  * Forward declarations
    361  */
    362 
    363 static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen);
    364 static __GLXcontext *glxWinCreateContext(__GLXscreen * screen,
    365                                          __GLXconfig * modes,
    366                                          __GLXcontext * baseShareContext,
    367                                          unsigned num_attribs,
    368                                          const uint32_t * attribs, int *error);
    369 static __GLXdrawable *glxWinCreateDrawable(ClientPtr client,
    370                                            __GLXscreen * screen,
    371                                            DrawablePtr pDraw,
    372                                            XID drawId,
    373                                            int type,
    374                                            XID glxDrawId, __GLXconfig * conf);
    375 
    376 static Bool glxWinRealizeWindow(WindowPtr pWin);
    377 static Bool glxWinUnrealizeWindow(WindowPtr pWin);
    378 static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
    379                              RegionPtr prgnSrc);
    380 static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
    381                                  __GLXscreen *screen, __GLXconfig *config);
    382 static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
    383                         HDC * hdc, HWND * hwnd);
    384 static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
    385 
    386 static void glxWinCreateConfigs(HDC dc, glxWinScreen * screen);
    387 static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen,
    388                                    PixelFormatRejectStats * rejects);
    389 static int fbConfigToPixelFormat(__GLXconfig * mode,
    390                                  PIXELFORMATDESCRIPTOR * pfdret,
    391                                  int drawableTypeOverride);
    392 static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode,
    393                                       int drawableTypeOverride,
    394                                       glxWinScreen * winScreen);
    395 
    396 /* ---------------------------------------------------------------------- */
    397 /*
    398  * The GLX provider
    399  */
    400 
    401 __GLXprovider __glXWGLProvider = {
    402     glxWinScreenProbe,
    403     "Win32 native WGL",
    404     NULL
    405 };
    406 
    407 void
    408 glxWinPushNativeProvider(void)
    409 {
    410     GlxPushProvider(&__glXWGLProvider);
    411 }
    412 
    413 /* ---------------------------------------------------------------------- */
    414 /*
    415  * Screen functions
    416  */
    417 
    418 static void
    419 glxWinScreenDestroy(__GLXscreen * screen)
    420 {
    421     GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen);
    422     __glXScreenDestroy(screen);
    423     free(screen);
    424 }
    425 
    426 static int
    427 glxWinScreenSwapInterval(__GLXdrawable * drawable, int interval)
    428 {
    429     BOOL ret = wglSwapIntervalEXTWrapper(interval);
    430 
    431     if (!ret) {
    432         ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval,
    433                glxWinErrorMessage());
    434     }
    435     return ret;
    436 }
    437 
    438 /*
    439   Report the extensions split and formatted to avoid overflowing a line
    440  */
    441 static void
    442 glxLogExtensions(const char *prefix, const char *extensions)
    443 {
    444     int length = 0;
    445     const char *strl;
    446     char *str = strdup(extensions);
    447 
    448     if (str == NULL) {
    449         ErrorF("glxLogExtensions: xalloc error\n");
    450         return;
    451     }
    452 
    453     strl = strtok(str, " ");
    454     if (strl == NULL)
    455         strl = "";
    456     ErrorF("%s%s", prefix, strl);
    457     length = strlen(prefix) + strlen(strl);
    458 
    459     while (1) {
    460         strl = strtok(NULL, " ");
    461         if (strl == NULL)
    462             break;
    463 
    464         if (length + strlen(strl) + 1 > 120) {
    465             ErrorF("\n");
    466             ErrorF("%s", prefix);
    467             length = strlen(prefix);
    468         }
    469         else {
    470             ErrorF(" ");
    471             length++;
    472         }
    473 
    474         ErrorF("%s", strl);
    475         length = length + strlen(strl);
    476     }
    477 
    478     ErrorF("\n");
    479 
    480     free(str);
    481 }
    482 
    483 /* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
    484 static __GLXscreen *
    485 glxWinScreenProbe(ScreenPtr pScreen)
    486 {
    487     glxWinScreen *screen;
    488     const char *gl_extensions;
    489     const char *gl_renderer;
    490     const char *wgl_extensions;
    491     HWND hwnd;
    492     HDC hdc;
    493     HGLRC hglrc;
    494     PixelFormatRejectStats rejects;
    495 
    496     GLWIN_DEBUG_MSG("glxWinScreenProbe");
    497 
    498     glxWinInitDebugSettings();
    499 
    500     if (pScreen == NULL)
    501         return NULL;
    502 
    503     if (!winCheckScreenAiglxIsSupported(pScreen)) {
    504         LogMessage(X_ERROR,
    505                    "AIGLX: No native OpenGL in modes with a root window\n");
    506         return NULL;
    507     }
    508 
    509     screen = calloc(1, sizeof(glxWinScreen));
    510 
    511     if (NULL == screen)
    512         return NULL;
    513 
    514     // Select the native GL implementation (WGL)
    515     if (glWinSelectImplementation(1)) {
    516         free(screen);
    517         return NULL;
    518     }
    519 
    520     // create window class
    521 #define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
    522     {
    523         static wATOM glTestWndClass = 0;
    524 
    525         if (glTestWndClass == 0) {
    526             WNDCLASSEX wc;
    527 
    528             wc.cbSize = sizeof(WNDCLASSEX);
    529             wc.style = CS_HREDRAW | CS_VREDRAW;
    530             wc.lpfnWndProc = DefWindowProc;
    531             wc.cbClsExtra = 0;
    532             wc.cbWndExtra = 0;
    533             wc.hInstance = GetModuleHandle(NULL);
    534             wc.hIcon = 0;
    535             wc.hCursor = 0;
    536             wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    537             wc.lpszMenuName = NULL;
    538             wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS;
    539             wc.hIconSm = 0;
    540             RegisterClassEx(&wc);
    541         }
    542     }
    543 
    544     // create an invisible window for a scratch DC
    545     hwnd = CreateWindowExA(0,
    546                            WIN_GL_TEST_WINDOW_CLASS,
    547                            "XWin GL Renderer Capabilities Test Window",
    548                            0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL),
    549                            NULL);
    550     if (hwnd == NULL)
    551         LogMessage(X_ERROR,
    552                    "AIGLX: Couldn't create a window for render capabilities testing\n");
    553 
    554     hdc = GetDC(hwnd);
    555 
    556     // we must set a pixel format before we can create a context, just use the first one...
    557     SetPixelFormat(hdc, 1, NULL);
    558     hglrc = wglCreateContext(hdc);
    559     wglMakeCurrent(hdc, hglrc);
    560 
    561     // initialize wgl extension proc pointers (don't call them before here...)
    562     // (but we need to have a current context for them to be resolvable)
    563     wglResolveExtensionProcs();
    564 
    565     /* Dump out some useful information about the native renderer */
    566     ErrorF("GL_VERSION:     %s\n", glGetString(GL_VERSION));
    567     ErrorF("GL_VENDOR:      %s\n", glGetString(GL_VENDOR));
    568     gl_renderer = (const char *) glGetString(GL_RENDERER);
    569     ErrorF("GL_RENDERER:    %s\n", gl_renderer);
    570     gl_extensions = (const char *) glGetString(GL_EXTENSIONS);
    571     wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
    572     if (!wgl_extensions)
    573         wgl_extensions = "";
    574 
    575     if (g_iLogVerbose >= 3) {
    576         glxLogExtensions("GL_EXTENSIONS:  ", gl_extensions);
    577         glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions);
    578     }
    579 
    580     if (strcasecmp(gl_renderer, "GDI Generic") == 0) {
    581         free(screen);
    582         LogMessage(X_ERROR,
    583                    "AIGLX: Won't use generic native renderer as it is not accelerated\n");
    584         goto error;
    585     }
    586 
    587     // Can you see the problem here?  The extensions string is DC specific
    588     // Different DCs for windows on a multimonitor system driven by multiple cards
    589     // might have completely different capabilities.  Of course, good luck getting
    590     // those screens to be accelerated in XP and earlier...
    591 
    592 
    593     {
    594         int i;
    595 
    596         const struct
    597         {
    598             const char *wglext;
    599             const char *glxext;
    600             Bool mandatory;
    601         } extensionMap[] = {
    602             { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 1 },
    603             { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
    604             { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
    605             //      { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
    606             // Sufficiently different that it's not obvious if this can be done...
    607             { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
    608             { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
    609             { "WGL_ARB_multisample", "GLX_SGIS_multisample", 0 },
    610             { "WGL_ARB_pixel_format_float", "GLX_ARB_fbconfig_float", 0 },
    611             { "WGL_EXT_pixel_format_packed_float", "GLX_EXT_fbconfig_packed_float", 0 },
    612             { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
    613             { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
    614             { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
    615             { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
    616             { "WGL_ARB_framebuffer_sRGB", "GLX_ARB_framebuffer_sRGB", 0 },
    617         };
    618 
    619         //
    620         // Based on the WGL extensions available, enable various GLX extensions
    621         //
    622         __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
    623 
    624         for (i = 0; i < sizeof(extensionMap)/sizeof(extensionMap[0]); i++) {
    625             if (strstr(wgl_extensions, extensionMap[i].wglext)) {
    626                 __glXEnableExtension(screen->base.glx_enable_bits, extensionMap[i].glxext);
    627                 LogMessage(X_INFO, "GLX: enabled %s\n", extensionMap[i].glxext);
    628             }
    629             else if (extensionMap[i].mandatory) {
    630                 LogMessage(X_ERROR, "required WGL extension %s is missing\n", extensionMap[i].wglext);
    631             }
    632         }
    633 
    634         // Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
    635         // only be in GL_EXTENSIONS
    636         if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
    637             __glXEnableExtension(screen->base.glx_enable_bits,
    638                                  "GLX_MESA_copy_sub_buffer");
    639             LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
    640         }
    641 
    642         if (strstr(wgl_extensions, "WGL_ARB_make_current_read"))
    643             screen->has_WGL_ARB_make_current_read = TRUE;
    644 
    645         if (strstr(wgl_extensions, "WGL_ARB_pbuffer"))
    646             screen->has_WGL_ARB_pbuffer = TRUE;
    647 
    648         if (strstr(wgl_extensions, "WGL_ARB_multisample"))
    649             screen->has_WGL_ARB_multisample = TRUE;
    650 
    651         if (strstr(wgl_extensions, "WGL_ARB_framebuffer_sRGB")) {
    652             screen->has_WGL_ARB_framebuffer_sRGB = TRUE;
    653         }
    654 
    655         screen->base.destroy = glxWinScreenDestroy;
    656         screen->base.createContext = glxWinCreateContext;
    657         screen->base.createDrawable = glxWinCreateDrawable;
    658         screen->base.swapInterval = glxWinScreenSwapInterval;
    659         screen->base.pScreen = pScreen;
    660 
    661         // Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs
    662         memset(&rejects, 0, sizeof(rejects));
    663         if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) {
    664             glxWinCreateConfigsExt(hdc, screen, &rejects);
    665 
    666             /*
    667                Some graphics drivers appear to advertise WGL_ARB_pixel_format,
    668                but it doesn't work usefully, so we have to be prepared for it
    669                to fail and fall back to using DescribePixelFormat()
    670              */
    671             if (screen->base.numFBConfigs > 0) {
    672                 screen->has_WGL_ARB_pixel_format = TRUE;
    673             }
    674         }
    675 
    676         if (screen->base.numFBConfigs <= 0) {
    677             memset(&rejects, 0, sizeof(rejects));
    678             glxWinCreateConfigs(hdc, screen);
    679             screen->has_WGL_ARB_pixel_format = FALSE;
    680         }
    681 
    682         /*
    683            If we still didn't get any fbConfigs, we can't provide GLX for this screen
    684          */
    685         if (screen->base.numFBConfigs <= 0) {
    686             free(screen);
    687             LogMessage(X_ERROR,
    688                        "AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
    689             goto error;
    690         }
    691 
    692         /* These will be set by __glXScreenInit */
    693         screen->base.visuals = NULL;
    694         screen->base.numVisuals = 0;
    695 
    696         __glXScreenInit(&screen->base, pScreen);
    697     }
    698 
    699     wglMakeCurrent(NULL, NULL);
    700     wglDeleteContext(hglrc);
    701     ReleaseDC(hwnd, hdc);
    702     DestroyWindow(hwnd);
    703 
    704     // dump out fbConfigs now fbConfigIds and visualIDs have been assigned
    705     fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs, &rejects);
    706 
    707     /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
    708     screen->RealizeWindow = pScreen->RealizeWindow;
    709     pScreen->RealizeWindow = glxWinRealizeWindow;
    710     screen->UnrealizeWindow = pScreen->UnrealizeWindow;
    711     pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
    712     screen->CopyWindow = pScreen->CopyWindow;
    713     pScreen->CopyWindow = glxWinCopyWindow;
    714 
    715     // Note that WGL is active on this screen
    716     winSetScreenAiglxIsActive(pScreen);
    717 
    718     return &screen->base;
    719 
    720  error:
    721     // Something went wrong and we can't use the native GL implementation
    722     // so make sure the mesa GL implementation is selected instead
    723     glWinSelectImplementation(0);
    724 
    725     return NULL;
    726 }
    727 
    728 /* ---------------------------------------------------------------------- */
    729 /*
    730  * Window functions
    731  */
    732 
    733 static Bool
    734 glxWinRealizeWindow(WindowPtr pWin)
    735 {
    736     Bool result;
    737     ScreenPtr pScreen = pWin->drawable.pScreen;
    738     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
    739 
    740     GLWIN_DEBUG_MSG("glxWinRealizeWindow");
    741 
    742     /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
    743     pScreen->RealizeWindow = screenPriv->RealizeWindow;
    744     result = pScreen->RealizeWindow(pWin);
    745     pScreen->RealizeWindow = glxWinRealizeWindow;
    746 
    747     return result;
    748 }
    749 
    750 static void
    751 glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    752 {
    753     __GLXWinDrawable *pGlxDraw;
    754     ScreenPtr pScreen = pWindow->drawable.pScreen;
    755     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
    756 
    757     GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
    758 
    759     dixLookupResourceByType((void *) &pGlxDraw, pWindow->drawable.id,
    760                             __glXDrawableRes, NullClient, DixUnknownAccess);
    761 
    762     /*
    763        Discard any CopyWindow requests if a GL drawing context is pointing at the window
    764 
    765        For regions which are being drawn by GL, the shadow framebuffer doesn't have the
    766        correct bits, so we wish to avoid shadow framebuffer damage occurring, which will
    767        cause those incorrect bits to be transferred to the display....
    768      */
    769     if (pGlxDraw && pGlxDraw->drawContext) {
    770         GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding");
    771         return;
    772     }
    773 
    774     GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
    775 
    776     pScreen->CopyWindow = screenPriv->CopyWindow;
    777     pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
    778     pScreen->CopyWindow = glxWinCopyWindow;
    779 }
    780 
    781 static Bool
    782 glxWinUnrealizeWindow(WindowPtr pWin)
    783 {
    784     Bool result;
    785     ScreenPtr pScreen = pWin->drawable.pScreen;
    786     glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
    787 
    788     GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
    789 
    790     pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
    791     result = pScreen->UnrealizeWindow(pWin);
    792     pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
    793 
    794     return result;
    795 }
    796 
    797 /* ---------------------------------------------------------------------- */
    798 /*
    799  * Drawable functions
    800  */
    801 
    802 static GLboolean
    803 glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable * base)
    804 {
    805     HDC dc;
    806     HWND hwnd;
    807     BOOL ret;
    808     __GLXWinDrawable *draw = (__GLXWinDrawable *) base;
    809 
    810     /* Swap buffers on the last active context for drawing on the drawable */
    811     if (draw->drawContext == NULL) {
    812         GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable");
    813         return GL_FALSE;
    814     }
    815 
    816     GLWIN_TRACE_MSG
    817         ("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)",
    818          base, draw->drawContext, draw->drawContext->ctx);
    819 
    820     dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd);
    821     if (dc == NULL)
    822         return GL_FALSE;
    823 
    824     ret = wglSwapLayerBuffers(dc, WGL_SWAP_MAIN_PLANE);
    825 
    826     glxWinReleaseDC(hwnd, dc, draw);
    827 
    828     if (!ret) {
    829         ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage());
    830         return GL_FALSE;
    831     }
    832 
    833     return GL_TRUE;
    834 }
    835 
    836 static void
    837 glxWinDrawableCopySubBuffer(__GLXdrawable * drawable,
    838                             int x, int y, int w, int h)
    839 {
    840     glAddSwapHintRectWINWrapper(x, y, w, h);
    841     glxWinDrawableSwapBuffers(NULL, drawable);
    842 }
    843 
    844 static void
    845 glxWinDrawableDestroy(__GLXdrawable * base)
    846 {
    847     __GLXWinDrawable *glxPriv = (__GLXWinDrawable *) base;
    848 
    849     if (glxPriv->hPbuffer)
    850         if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer)) {
    851             ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
    852         }
    853 
    854     if (glxPriv->dibDC) {
    855         // restore the default DIB
    856         SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
    857 
    858         if (!DeleteDC(glxPriv->dibDC)) {
    859             ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
    860         }
    861     }
    862 
    863     if (glxPriv->hDIB) {
    864         if (!CloseHandle(glxPriv->hSection)) {
    865             ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage());
    866         }
    867 
    868         if (!DeleteObject(glxPriv->hDIB)) {
    869             ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
    870         }
    871 
    872         ((PixmapPtr) glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
    873     }
    874 
    875     GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
    876     free(glxPriv);
    877 }
    878 
    879 static __GLXdrawable *
    880 glxWinCreateDrawable(ClientPtr client,
    881                      __GLXscreen * screen,
    882                      DrawablePtr pDraw,
    883                      XID drawId, int type, XID glxDrawId, __GLXconfig * conf)
    884 {
    885     __GLXWinDrawable *glxPriv;
    886 
    887     glxPriv = malloc(sizeof *glxPriv);
    888 
    889     if (glxPriv == NULL)
    890         return NULL;
    891 
    892     memset(glxPriv, 0, sizeof *glxPriv);
    893 
    894     if (!__glXDrawableInit
    895         (&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) {
    896         free(glxPriv);
    897         return NULL;
    898     }
    899 
    900     glxPriv->base.destroy = glxWinDrawableDestroy;
    901     glxPriv->base.swapBuffers = glxWinDrawableSwapBuffers;
    902     glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer;
    903     // glxPriv->base.waitX  what are these for?
    904     // glxPriv->base.waitGL
    905 
    906     GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv);
    907 
    908     return &glxPriv->base;
    909 }
    910 
    911 void
    912 glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config)
    913 {
    914     switch (draw->base.type) {
    915     case GLX_DRAWABLE_WINDOW:
    916     {
    917         WindowPtr pWin = (WindowPtr) draw->base.pDraw;
    918 
    919         if (!(config->drawableType & GLX_WINDOW_BIT)) {
    920             ErrorF
    921                 ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_WINDOW drawable with a fbConfig which doesn't have drawableType GLX_WINDOW_BIT\n");
    922         }
    923 
    924         if (pWin == NULL) {
    925             GLWIN_DEBUG_MSG("Deferring until X window is created");
    926             return;
    927         }
    928 
    929         GLWIN_DEBUG_MSG("glxWinDeferredCreateDrawable: pWin %p", pWin);
    930 
    931         if (winGetWindowInfo(pWin) == NULL) {
    932             GLWIN_DEBUG_MSG("Deferring until native window is created");
    933             return;
    934         }
    935     }
    936     break;
    937 
    938     case GLX_DRAWABLE_PBUFFER:
    939     {
    940         if (draw->hPbuffer == NULL) {
    941             __GLXscreen *screen;
    942             glxWinScreen *winScreen;
    943             int pixelFormat;
    944 
    945             // XXX: which DC are we supposed to use???
    946             HDC screenDC = GetDC(NULL);
    947 
    948             if (!(config->drawableType & GLX_PBUFFER_BIT)) {
    949                 ErrorF
    950                     ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PBUFFER drawable with a fbConfig which doesn't have drawableType GLX_PBUFFER_BIT\n");
    951             }
    952 
    953             screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
    954             winScreen = (glxWinScreen *) screen;
    955 
    956             pixelFormat =
    957                 fbConfigToPixelFormatIndex(screenDC, config,
    958                                            GLX_PBUFFER_BIT, winScreen);
    959             if (pixelFormat == 0) {
    960                 return;
    961             }
    962 
    963             draw->hPbuffer =
    964                 wglCreatePbufferARBWrapper(screenDC, pixelFormat,
    965                                            draw->base.pDraw->width,
    966                                            draw->base.pDraw->height, NULL);
    967             ReleaseDC(NULL, screenDC);
    968 
    969             if (draw->hPbuffer == NULL) {
    970                 ErrorF("wglCreatePbufferARBWrapper error: %s\n",
    971                        glxWinErrorMessage());
    972                 return;
    973             }
    974 
    975             GLWIN_DEBUG_MSG
    976                 ("glxWinDeferredCreateDrawable: pBuffer %p created for drawable %p",
    977                  draw->hPbuffer, draw);
    978         }
    979     }
    980     break;
    981 
    982     case GLX_DRAWABLE_PIXMAP:
    983     {
    984         if (draw->dibDC == NULL) {
    985             BITMAPINFOHEADER bmpHeader;
    986             void *pBits;
    987             __GLXscreen *screen;
    988             DWORD size;
    989             char name[MAX_PATH];
    990 
    991             memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
    992             bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
    993             bmpHeader.biWidth = draw->base.pDraw->width;
    994             bmpHeader.biHeight = draw->base.pDraw->height;
    995             bmpHeader.biPlanes = 1;
    996             bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
    997             bmpHeader.biCompression = BI_RGB;
    998 
    999             if (!(config->drawableType & GLX_PIXMAP_BIT)) {
   1000                 ErrorF
   1001                     ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PIXMAP drawable with a fbConfig which doesn't have drawableType GLX_PIXMAP_BIT\n");
   1002             }
   1003 
   1004             draw->dibDC = CreateCompatibleDC(NULL);
   1005             if (draw->dibDC == NULL) {
   1006                 ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
   1007                 return;
   1008             }
   1009 
   1010 #define RASTERWIDTHBYTES(bmi) (((((bmi)->biWidth*(bmi)->biBitCount)+31)&~31)>>3)
   1011             size = bmpHeader.biHeight * RASTERWIDTHBYTES(&bmpHeader);
   1012             GLWIN_DEBUG_MSG("shared memory region size %zu + %u\n", sizeof(BITMAPINFOHEADER), (unsigned int)size);
   1013 
   1014             // Create unique name for mapping based on XID
   1015             //
   1016             // XXX: not quite unique as potentially this name could be used in
   1017             // another server instance.  Not sure how to deal with that.
   1018             snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", (unsigned int)draw->base.pDraw->id);
   1019             GLWIN_DEBUG_MSG("shared memory region name %s\n", name);
   1020 
   1021             // Create a file mapping backed by the pagefile
   1022             draw->hSection = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
   1023                                                PAGE_READWRITE, 0, sizeof(BITMAPINFOHEADER) + size, name);
   1024             if (draw->hSection == NULL) {
   1025                 ErrorF("CreateFileMapping error: %s\n", glxWinErrorMessage());
   1026                 return;
   1027                 }
   1028 
   1029             draw->hDIB =
   1030                 CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader,
   1031                                  DIB_RGB_COLORS, &pBits, draw->hSection, sizeof(BITMAPINFOHEADER));
   1032             if (draw->dibDC == NULL) {
   1033                 ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
   1034                 return;
   1035             }
   1036 
   1037             // Store a copy of the BITMAPINFOHEADER at the start of the shared
   1038             // memory for the information of the receiving process
   1039             {
   1040                 LPVOID pData = MapViewOfFile(draw->hSection, FILE_MAP_WRITE, 0, 0, 0);
   1041                 memcpy(pData, (void *)&bmpHeader, sizeof(BITMAPINFOHEADER));
   1042                 UnmapViewOfFile(pData);
   1043             }
   1044 
   1045             // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
   1046             // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
   1047             // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
   1048             // even compatible ...
   1049             draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr;
   1050             ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits;
   1051 
   1052             // Select the DIB into the DC
   1053             draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
   1054             if (!draw->hOldDIB) {
   1055                 ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
   1056             }
   1057 
   1058             screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]);
   1059 
   1060             // Set the pixel format of the bitmap
   1061             glxWinSetPixelFormat(draw->dibDC,
   1062                                  draw->base.pDraw->bitsPerPixel,
   1063                                  GLX_PIXMAP_BIT,
   1064                                  screen,
   1065                                  config);
   1066 
   1067             GLWIN_DEBUG_MSG
   1068                 ("glxWinDeferredCreateDrawable: DIB bitmap %p created for drawable %p",
   1069                  draw->hDIB, draw);
   1070         }
   1071     }
   1072     break;
   1073 
   1074     default:
   1075     {
   1076         ErrorF
   1077             ("glxWinDeferredCreateDrawable: tried to attach unhandled drawable type %d\n",
   1078              draw->base.type);
   1079         return;
   1080     }
   1081     }
   1082 }
   1083 
   1084 /* ---------------------------------------------------------------------- */
   1085 /*
   1086  * Texture functions
   1087  */
   1088 
   1089 static
   1090     int
   1091 glxWinBindTexImage(__GLXcontext * baseContext,
   1092                    int buffer, __GLXdrawable * pixmap)
   1093 {
   1094     ErrorF("glxWinBindTexImage: not implemented\n");
   1095     return FALSE;
   1096 }
   1097 
   1098 static
   1099     int
   1100 glxWinReleaseTexImage(__GLXcontext * baseContext,
   1101                       int buffer, __GLXdrawable * pixmap)
   1102 {
   1103     ErrorF(" glxWinReleaseTexImage: not implemented\n");
   1104     return FALSE;
   1105 }
   1106 
   1107 /* ---------------------------------------------------------------------- */
   1108 /*
   1109  * Lazy update context implementation
   1110  *
   1111  * WGL contexts are created for a specific HDC, so we cannot create the WGL
   1112  * context in glxWinCreateContext(), we must defer creation until the context
   1113  * is actually used on a specific drawable which is connected to a native window,
   1114  * pbuffer or DIB
   1115  *
   1116  * The WGL context may be used on other, compatible HDCs, so we don't need to
   1117  * recreate it for every new native window
   1118  *
   1119  * XXX: I wonder why we can't create the WGL context on the screen HDC ?
   1120  * Basically we assume all HDCs are compatible at the moment: if they are not
   1121  * we are in a muddle, there was some code in the old implementation to attempt
   1122  * to transparently migrate a context to a new DC by copying state and sharing
   1123  * lists with the old one...
   1124  */
   1125 
   1126 static Bool
   1127 glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
   1128                      __GLXscreen *screen, __GLXconfig *config)
   1129 {
   1130     glxWinScreen *winScreen = (glxWinScreen *) screen;
   1131     GLXWinConfig *winConfig = (GLXWinConfig *) config;
   1132 
   1133     GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
   1134                     winConfig->pixelFormatIndex);
   1135 
   1136     /*
   1137        Normally, we can just use the the pixelFormatIndex corresponding
   1138        to the fbconfig which has been specified by the client
   1139      */
   1140 
   1141     if (!
   1142         ((bppOverride &&
   1143           (bppOverride !=
   1144            (config->redBits + config->greenBits + config->blueBits)))
   1145          || ((config->drawableType & drawableTypeOverride) == 0))) {
   1146         if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL)) {
   1147             ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
   1148             return FALSE;
   1149         }
   1150 
   1151         return TRUE;
   1152     }
   1153 
   1154     /*
   1155        However, in certain special cases this pixel format will be incompatible with the
   1156        use we are going to put it to, so we need to re-evaluate the pixel format to use:
   1157 
   1158        1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with
   1159        the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap
   1160 
   1161        2) Applications may assume that visuals selected with glXChooseVisual() work with
   1162        pixmap drawables (there is no attribute to explicitly query for pixmap drawable
   1163        support as there is for glXChooseFBConfig())
   1164        (it's arguable this is an error in the application, but we try to make it work)
   1165 
   1166        pixmap rendering is always slow for us, so we don't want to choose those visuals
   1167        by default, but if the actual drawable type we're trying to select the context
   1168        on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider
   1169        and see if we can find a suitable one...
   1170      */
   1171     ErrorF
   1172         ("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n",
   1173          (config->redBits + config->greenBits + config->blueBits), bppOverride,
   1174          config->drawableType, drawableTypeOverride);
   1175 
   1176     if (winScreen->has_WGL_ARB_pixel_format) {
   1177         int pixelFormat =
   1178             fbConfigToPixelFormatIndex(hdc, config,
   1179                                        drawableTypeOverride, winScreen);
   1180         if (pixelFormat != 0) {
   1181             GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d",
   1182                             pixelFormat);
   1183             ErrorF
   1184                 ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
   1185                  pixelFormat, winConfig->pixelFormatIndex);
   1186 
   1187             if (!SetPixelFormat(hdc, pixelFormat, NULL)) {
   1188                 ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
   1189                 return FALSE;
   1190             }
   1191         }
   1192     }
   1193 
   1194     /*
   1195       For some drivers, wglChoosePixelFormatARB() can fail when the provided
   1196       DC doesn't belong to the driver (e.g. it's a compatible DC for a bitmap,
   1197       so allow fallback to ChoosePixelFormat()
   1198      */
   1199     {
   1200         PIXELFORMATDESCRIPTOR pfd;
   1201         int pixelFormat;
   1202 
   1203         /* convert fbConfig to PFD */
   1204         if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) {
   1205             ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
   1206             return FALSE;
   1207         }
   1208 
   1209         if (glxWinDebugSettings.dumpPFD)
   1210             pfdOut(&pfd);
   1211 
   1212         if (bppOverride) {
   1213             GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n",
   1214                             pfd.cColorBits, bppOverride);
   1215             pfd.cColorBits = bppOverride;
   1216         }
   1217 
   1218         pixelFormat = ChoosePixelFormat(hdc, &pfd);
   1219         if (pixelFormat == 0) {
   1220             ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage());
   1221             return FALSE;
   1222         }
   1223 
   1224         GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d",
   1225                         pixelFormat);
   1226         ErrorF
   1227             ("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n",
   1228              pixelFormat, winConfig->pixelFormatIndex);
   1229 
   1230         if (!SetPixelFormat(hdc, pixelFormat, &pfd)) {
   1231             ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
   1232             return FALSE;
   1233         }
   1234     }
   1235 
   1236     return TRUE;
   1237 }
   1238 
   1239 static HDC
   1240 glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc,
   1241              HWND * hwnd)
   1242 {
   1243     *hdc = NULL;
   1244     *hwnd = NULL;
   1245 
   1246     if (draw == NULL) {
   1247         GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc,
   1248                         gc->ctx);
   1249         return NULL;
   1250     }
   1251 
   1252     switch (draw->base.type) {
   1253     case GLX_DRAWABLE_WINDOW:
   1254     {
   1255         WindowPtr pWin;
   1256 
   1257         pWin = (WindowPtr) draw->base.pDraw;
   1258         if (pWin == NULL) {
   1259             GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
   1260             return NULL;
   1261         }
   1262 
   1263         *hwnd = winGetWindowInfo(pWin);
   1264 
   1265         if (*hwnd == NULL) {
   1266             ErrorF("No HWND error: %s\n", glxWinErrorMessage());
   1267             return NULL;
   1268         }
   1269 
   1270         *hdc = GetDC(*hwnd);
   1271 
   1272         if (*hdc == NULL)
   1273             ErrorF("GetDC error: %s\n", glxWinErrorMessage());
   1274 
   1275         /* Check if the hwnd has changed... */
   1276         if (*hwnd != gc->hwnd) {
   1277             if (glxWinDebugSettings.enableTrace)
   1278                 GLWIN_DEBUG_HWND(*hwnd);
   1279 
   1280             GLWIN_TRACE_MSG
   1281                 ("for context %p (native ctx %p), hWnd changed from %p to %p",
   1282                  gc, gc->ctx, gc->hwnd, *hwnd);
   1283             gc->hwnd = *hwnd;
   1284 
   1285             /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
   1286             if (!glxWinSetPixelFormat(*hdc, 0, GLX_WINDOW_BIT, gc->base.pGlxScreen, gc->base.config)) {
   1287                 ErrorF("glxWinSetPixelFormat error: %s\n",
   1288                        glxWinErrorMessage());
   1289                 ReleaseDC(*hwnd, *hdc);
   1290                 *hdc = NULL;
   1291                 return NULL;
   1292             }
   1293         }
   1294     }
   1295         break;
   1296 
   1297     case GLX_DRAWABLE_PBUFFER:
   1298     {
   1299         *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
   1300 
   1301         if (*hdc == NULL)
   1302             ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
   1303     }
   1304         break;
   1305 
   1306     case GLX_DRAWABLE_PIXMAP:
   1307     {
   1308         *hdc = draw->dibDC;
   1309     }
   1310         break;
   1311 
   1312     default:
   1313     {
   1314         ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n",
   1315                draw->base.type);
   1316     }
   1317     }
   1318 
   1319     if (glxWinDebugSettings.dumpDC)
   1320         GLWIN_DEBUG_MSG("Got HDC %p", *hdc);
   1321 
   1322     return *hdc;
   1323 }
   1324 
   1325 static void
   1326 glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw)
   1327 {
   1328     switch (draw->base.type) {
   1329     case GLX_DRAWABLE_WINDOW:
   1330     {
   1331         ReleaseDC(hwnd, hdc);
   1332     }
   1333         break;
   1334 
   1335     case GLX_DRAWABLE_PBUFFER:
   1336     {
   1337         if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc)) {
   1338             ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
   1339         }
   1340     }
   1341         break;
   1342 
   1343     case GLX_DRAWABLE_PIXMAP:
   1344     {
   1345         // don't release DC, the memory DC lives as long as the bitmap
   1346 
   1347         // We must ensure that all GDI drawing into the bitmap has completed
   1348         // in case we subsequently access the bits from it
   1349         GdiFlush();
   1350     }
   1351         break;
   1352 
   1353     default:
   1354     {
   1355         ErrorF
   1356             ("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n",
   1357              draw->base.type);
   1358     }
   1359     }
   1360 }
   1361 
   1362 static void
   1363 glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
   1364 {
   1365     HDC dc;
   1366     HWND hwnd;
   1367 
   1368     GLWIN_DEBUG_MSG
   1369         ("glxWinDeferredCreateContext: attach context %p to drawable %p", gc,
   1370          draw);
   1371 
   1372     glxWinDeferredCreateDrawable(draw, gc->base.config);
   1373 
   1374     dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
   1375     gc->ctx = wglCreateContext(dc);
   1376     glxWinReleaseDC(hwnd, dc, draw);
   1377 
   1378     if (gc->ctx == NULL) {
   1379         ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
   1380         return;
   1381     }
   1382 
   1383     GLWIN_DEBUG_MSG
   1384         ("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p",
   1385          gc, gc->ctx, draw);
   1386 
   1387     // if the native context was created successfully, shareLists if needed
   1388     if (gc->ctx && gc->shareContext) {
   1389         GLWIN_DEBUG_MSG
   1390             ("glxWinCreateContextReal shareLists with context %p (native ctx %p)",
   1391              gc->shareContext, gc->shareContext->ctx);
   1392 
   1393         if (!wglShareLists(gc->shareContext->ctx, gc->ctx)) {
   1394             ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
   1395         }
   1396     }
   1397 }
   1398 
   1399 /* ---------------------------------------------------------------------- */
   1400 /*
   1401  * Context functions
   1402  */
   1403 
   1404 /* Context manipulation routines should return TRUE on success, FALSE on failure */
   1405 static int
   1406 glxWinContextMakeCurrent(__GLXcontext * base)
   1407 {
   1408     __GLXWinContext *gc = (__GLXWinContext *) base;
   1409     glxWinScreen *scr = (glxWinScreen *)base->pGlxScreen;
   1410     BOOL ret;
   1411     HDC drawDC;
   1412     HDC readDC = NULL;
   1413     __GLXdrawable *drawPriv;
   1414     __GLXdrawable *readPriv = NULL;
   1415     HWND hDrawWnd;
   1416     HWND hReadWnd;
   1417 
   1418     GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc,
   1419                     gc->ctx);
   1420 
   1421     /* Keep a note of the last active context in the drawable */
   1422     drawPriv = gc->base.drawPriv;
   1423     ((__GLXWinDrawable *) drawPriv)->drawContext = gc;
   1424 
   1425     if (gc->ctx == NULL) {
   1426         glxWinDeferredCreateContext(gc, (__GLXWinDrawable *) drawPriv);
   1427     }
   1428 
   1429     if (gc->ctx == NULL) {
   1430         ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
   1431         return FALSE;
   1432     }
   1433 
   1434     drawDC =
   1435         glxWinMakeDC(gc, (__GLXWinDrawable *) drawPriv, &drawDC, &hDrawWnd);
   1436     if (drawDC == NULL) {
   1437         ErrorF("glxWinMakeDC failed for drawDC\n");
   1438         return FALSE;
   1439     }
   1440 
   1441     if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv)) {
   1442         /*
   1443          * We enable GLX_SGI_make_current_read unconditionally, but the
   1444          * renderer might not support it. It's fairly rare to use this
   1445          * feature so just error out if it can't work.
   1446          */
   1447         if (!scr->has_WGL_ARB_make_current_read)
   1448             return FALSE;
   1449 
   1450         /*
   1451            If there is a separate read drawable, create a separate read DC, and
   1452            use the wglMakeContextCurrent extension to make the context current drawing
   1453            to one DC and reading from the other
   1454          */
   1455         readPriv = gc->base.readPriv;
   1456         readDC =
   1457             glxWinMakeDC(gc, (__GLXWinDrawable *) readPriv, &readDC, &hReadWnd);
   1458         if (readDC == NULL) {
   1459             ErrorF("glxWinMakeDC failed for readDC\n");
   1460             glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *) drawPriv);
   1461             return FALSE;
   1462         }
   1463 
   1464         ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
   1465         if (!ret) {
   1466             ErrorF("wglMakeContextCurrentARBWrapper error: %s\n",
   1467                    glxWinErrorMessage());
   1468         }
   1469     }
   1470     else {
   1471         /* Otherwise, just use wglMakeCurrent */
   1472         ret = wglMakeCurrent(drawDC, gc->ctx);
   1473         if (!ret) {
   1474             ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
   1475         }
   1476     }
   1477 
   1478     // apparently make current could fail if the context is current in a different thread,
   1479     // but that shouldn't be able to happen in the current server...
   1480 
   1481     glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *) drawPriv);
   1482     if (readDC)
   1483         glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *) readPriv);
   1484 
   1485     return ret;
   1486 }
   1487 
   1488 static int
   1489 glxWinContextLoseCurrent(__GLXcontext * base)
   1490 {
   1491     BOOL ret;
   1492     __GLXWinContext *gc = (__GLXWinContext *) base;
   1493 
   1494     GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc,
   1495                     gc->ctx);
   1496 
   1497     /*
   1498        An error seems to be reported if we try to make no context current
   1499        if there is already no current context, so avoid doing that...
   1500      */
   1501     if (wglGetCurrentContext() != NULL) {
   1502         ret = wglMakeCurrent(NULL, NULL);       /* We don't need a DC when setting no current context */
   1503         if (!ret)
   1504             ErrorF("glxWinContextLoseCurrent error: %s\n",
   1505                    glxWinErrorMessage());
   1506     }
   1507 
   1508     return TRUE;
   1509 }
   1510 
   1511 static int
   1512 glxWinContextCopy(__GLXcontext * dst_base, __GLXcontext * src_base,
   1513                   unsigned long mask)
   1514 {
   1515     __GLXWinContext *dst = (__GLXWinContext *) dst_base;
   1516     __GLXWinContext *src = (__GLXWinContext *) src_base;
   1517     BOOL ret;
   1518 
   1519     GLWIN_DEBUG_MSG("glxWinContextCopy");
   1520 
   1521     ret = wglCopyContext(src->ctx, dst->ctx, mask);
   1522     if (!ret) {
   1523         ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage());
   1524     }
   1525 
   1526     return ret;
   1527 }
   1528 
   1529 static void
   1530 glxWinContextDestroy(__GLXcontext * base)
   1531 {
   1532     __GLXWinContext *gc = (__GLXWinContext *) base;
   1533 
   1534     if (gc != NULL) {
   1535         GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base,
   1536                         gc->ctx);
   1537 
   1538         if (gc->ctx) {
   1539             /* It's bad style to delete the context while it's still current */
   1540             if (wglGetCurrentContext() == gc->ctx) {
   1541                 wglMakeCurrent(NULL, NULL);
   1542             }
   1543 
   1544             {
   1545                 BOOL ret = wglDeleteContext(gc->ctx);
   1546 
   1547                 if (!ret)
   1548                     ErrorF("wglDeleteContext error: %s\n",
   1549                            glxWinErrorMessage());
   1550             }
   1551 
   1552             gc->ctx = NULL;
   1553         }
   1554 
   1555         free(gc);
   1556     }
   1557 }
   1558 
   1559 static __GLXcontext *
   1560 glxWinCreateContext(__GLXscreen * screen,
   1561                     __GLXconfig * modes, __GLXcontext * baseShareContext,
   1562                     unsigned num_attribs, const uint32_t * attribs, int *error)
   1563 {
   1564     __GLXWinContext *context;
   1565     __GLXWinContext *shareContext = (__GLXWinContext *) baseShareContext;
   1566 
   1567     context = calloc(1, sizeof(__GLXWinContext));
   1568 
   1569     if (!context)
   1570         return NULL;
   1571 
   1572     memset(context, 0, sizeof *context);
   1573     context->base.destroy = glxWinContextDestroy;
   1574     context->base.makeCurrent = glxWinContextMakeCurrent;
   1575     context->base.loseCurrent = glxWinContextLoseCurrent;
   1576     context->base.copy = glxWinContextCopy;
   1577     context->base.bindTexImage = glxWinBindTexImage;
   1578     context->base.releaseTexImage = glxWinReleaseTexImage;
   1579     context->base.config = modes;
   1580     context->base.pGlxScreen = screen;
   1581 
   1582     // actual native GL context creation is deferred until attach()
   1583     context->ctx = NULL;
   1584     context->shareContext = shareContext;
   1585 
   1586     GLWIN_DEBUG_MSG("GLXcontext %p created", context);
   1587 
   1588     return &(context->base);
   1589 }
   1590 
   1591 /* ---------------------------------------------------------------------- */
   1592 /*
   1593  * Utility functions
   1594  */
   1595 
   1596 static int
   1597 GetShift(int mask)
   1598 {
   1599     int shift = 0;
   1600     while (mask > 1) {
   1601         shift++;
   1602         mask >>=1;
   1603     }
   1604     return shift;
   1605 }
   1606 
   1607 static int
   1608 fbConfigToPixelFormat(__GLXconfig * mode, PIXELFORMATDESCRIPTOR * pfdret,
   1609                       int drawableTypeOverride)
   1610 {
   1611     PIXELFORMATDESCRIPTOR pfd = {
   1612         sizeof(PIXELFORMATDESCRIPTOR),  /* size of this pfd */
   1613         1,                      /* version number */
   1614         PFD_SUPPORT_OPENGL,     /* support OpenGL */
   1615         PFD_TYPE_RGBA,          /* RGBA type */
   1616         24,                     /* 24-bit color depth */
   1617         0, 0, 0, 0, 0, 0,       /* color bits ignored */
   1618         0,                      /* no alpha buffer */
   1619         0,                      /* shift bit ignored */
   1620         0,                      /* no accumulation buffer */
   1621         0, 0, 0, 0,             /* accum bits ignored */
   1622         32,                     /* 32-bit z-buffer */
   1623         0,                      /* no stencil buffer */
   1624         0,                      /* no auxiliary buffer */
   1625         PFD_MAIN_PLANE,         /* main layer */
   1626         0,                      /* reserved */
   1627         0, 0, 0                 /* layer masks ignored */
   1628     };
   1629 
   1630     if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
   1631         pfd.dwFlags |= PFD_DRAW_TO_WINDOW;      /* support window */
   1632 
   1633     if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
   1634         pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);  /* supports software rendering to bitmap */
   1635 
   1636     if (mode->stereoMode) {
   1637         pfd.dwFlags |= PFD_STEREO;
   1638     }
   1639     if (mode->doubleBufferMode) {
   1640         pfd.dwFlags |= PFD_DOUBLEBUFFER;
   1641     }
   1642 
   1643     pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
   1644     pfd.cRedBits = mode->redBits;
   1645     pfd.cRedShift = GetShift(mode->redMask);
   1646     pfd.cGreenBits = mode->greenBits;
   1647     pfd.cGreenShift = GetShift(mode->greenMask);
   1648     pfd.cBlueBits = mode->blueBits;
   1649     pfd.cBlueShift = GetShift(mode->blueMask);
   1650     pfd.cAlphaBits = mode->alphaBits;
   1651     pfd.cAlphaShift = GetShift(mode->alphaMask);
   1652 
   1653     if (mode->visualType == GLX_TRUE_COLOR) {
   1654         pfd.iPixelType = PFD_TYPE_RGBA;
   1655         pfd.dwVisibleMask =
   1656             (pfd.cRedBits << pfd.cRedShift) | (pfd.cGreenBits << pfd.cGreenShift) |
   1657             (pfd.cBlueBits << pfd.cBlueShift) | (pfd.cAlphaBits << pfd.cAlphaShift);
   1658     }
   1659     else {
   1660         pfd.iPixelType = PFD_TYPE_COLORINDEX;
   1661         pfd.dwVisibleMask = mode->transparentIndex;
   1662     }
   1663 
   1664     pfd.cAccumBits =
   1665         mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits +
   1666         mode->accumAlphaBits;
   1667     pfd.cAccumRedBits = mode->accumRedBits;
   1668     pfd.cAccumGreenBits = mode->accumGreenBits;
   1669     pfd.cAccumBlueBits = mode->accumBlueBits;
   1670     pfd.cAccumAlphaBits = mode->accumAlphaBits;
   1671 
   1672     pfd.cDepthBits = mode->depthBits;
   1673     pfd.cStencilBits = mode->stencilBits;
   1674     pfd.cAuxBuffers = mode->numAuxBuffers;
   1675 
   1676     /* mode->level ? */
   1677 
   1678     *pfdret = pfd;
   1679 
   1680     return 0;
   1681 }
   1682 
   1683 #define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < ARRAY_SIZE(attribList)); }
   1684 
   1685 static int
   1686 fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode,
   1687                            int drawableTypeOverride, glxWinScreen * winScreen)
   1688 {
   1689     UINT numFormats;
   1690     unsigned int i = 0;
   1691 
   1692     /* convert fbConfig to attr-value list  */
   1693     int attribList[60];
   1694 
   1695     SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE);
   1696 
   1697     switch (mode->renderType)
   1698         {
   1699         case GLX_COLOR_INDEX_BIT:
   1700         case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
   1701             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_COLORINDEX_ARB);
   1702             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->indexBits);
   1703             break;
   1704 
   1705         default:
   1706             ErrorF("unexpected renderType %x\n", mode->renderType);
   1707             /* fall-through */
   1708         case GLX_RGBA_BIT:
   1709             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
   1710             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
   1711             break;
   1712 
   1713         case GLX_RGBA_FLOAT_BIT_ARB:
   1714             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ARB);
   1715             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
   1716             break;
   1717 
   1718         case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT:
   1719             SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT);
   1720             SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits);
   1721             break;
   1722         }
   1723 
   1724     SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits);
   1725     SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits);
   1726     SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits);
   1727     SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits);
   1728     SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits);
   1729     SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits);
   1730     SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits);
   1731     SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits);
   1732     SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits);
   1733     SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits);
   1734     SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers);
   1735 
   1736     if (mode->doubleBufferMode)
   1737         SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE);
   1738 
   1739     if (mode->stereoMode)
   1740         SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE);
   1741 
   1742     // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft..
   1743     if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML)
   1744         SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
   1745 
   1746     if (mode->swapMethod == GLX_SWAP_COPY_OML)
   1747         SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_COPY_ARB);
   1748 
   1749     // XXX: this should probably be the other way around, but that messes up drawableTypeOverride
   1750     if (mode->visualRating == GLX_SLOW_VISUAL_EXT)
   1751         SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
   1752 
   1753     if (winScreen->has_WGL_ARB_multisample) {
   1754         SET_ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, mode->sampleBuffers);
   1755         SET_ATTR_VALUE(WGL_SAMPLES_ARB, mode->samples);
   1756     }
   1757 
   1758     // must support all the drawable types the mode supports
   1759     if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
   1760         SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, TRUE);
   1761 
   1762     // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea
   1763     // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride)
   1764     if (drawableTypeOverride == GLX_WINDOW_BIT) {
   1765         if (mode->drawableType & GLX_PIXMAP_BIT)
   1766             SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
   1767 
   1768         if (mode->drawableType & GLX_PBUFFER_BIT)
   1769             if (winScreen->has_WGL_ARB_pbuffer)
   1770                 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
   1771     }
   1772     else {
   1773         if (drawableTypeOverride & GLX_PIXMAP_BIT)
   1774             SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
   1775 
   1776         if (drawableTypeOverride & GLX_PBUFFER_BIT)
   1777             if (winScreen->has_WGL_ARB_pbuffer)
   1778                 SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
   1779     }
   1780 
   1781     if (winScreen->has_WGL_ARB_framebuffer_sRGB)
   1782         SET_ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE);
   1783 
   1784     SET_ATTR_VALUE(0, 0);       // terminator
   1785 
   1786     /* choose the first match */
   1787     {
   1788         int pixelFormatIndex;
   1789 
   1790         if (!wglChoosePixelFormatARBWrapper
   1791             (hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats)) {
   1792             ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
   1793         }
   1794         else {
   1795             if (numFormats > 0) {
   1796                 GLWIN_DEBUG_MSG
   1797                     ("wglChoosePixelFormat: chose pixelFormatIndex %d)",
   1798                      pixelFormatIndex);
   1799                 return pixelFormatIndex;
   1800             }
   1801             else
   1802                 ErrorF("wglChoosePixelFormat couldn't decide\n");
   1803         }
   1804     }
   1805 
   1806     return 0;
   1807 }
   1808 
   1809 /* ---------------------------------------------------------------------- */
   1810 
   1811 #define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
   1812 
   1813 //
   1814 // Create the GLXconfigs using DescribePixelFormat()
   1815 //
   1816 static void
   1817 glxWinCreateConfigs(HDC hdc, glxWinScreen * screen)
   1818 {
   1819     GLXWinConfig *first = NULL, *prev = NULL;
   1820     int numConfigs = 0;
   1821     int i = 0;
   1822     int n = 0;
   1823     PIXELFORMATDESCRIPTOR pfd;
   1824 
   1825     GLWIN_DEBUG_MSG("glxWinCreateConfigs");
   1826 
   1827     screen->base.numFBConfigs = 0;
   1828     screen->base.fbconfigs = NULL;
   1829 
   1830     // get the number of pixelformats
   1831     numConfigs =
   1832         DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
   1833     LogMessage(X_INFO, "%d pixel formats reported by DescribePixelFormat\n",
   1834                numConfigs);
   1835 
   1836     n = 0;
   1837 
   1838     /* fill in configs */
   1839     for (i = 0; i < numConfigs; i++) {
   1840         int rc;
   1841         GLXWinConfig temp;
   1842         GLXWinConfig *c = &temp;
   1843         GLXWinConfig *work;
   1844         memset(c, 0, sizeof(GLXWinConfig));
   1845 
   1846         c->pixelFormatIndex = i + 1;
   1847 
   1848         rc = DescribePixelFormat(hdc, i + 1, sizeof(PIXELFORMATDESCRIPTOR),
   1849                                  &pfd);
   1850 
   1851         if (!rc) {
   1852             ErrorF("DescribePixelFormat failed for index %d, error %s\n", i + 1,
   1853                    glxWinErrorMessage());
   1854             break;
   1855         }
   1856 
   1857         if (glxWinDebugSettings.dumpPFD)
   1858             pfdOut(&pfd);
   1859 
   1860         if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) ||
   1861             !(pfd.dwFlags & PFD_SUPPORT_OPENGL)) {
   1862             GLWIN_DEBUG_MSG
   1863                 ("pixelFormat %d has unsuitable flags 0x%08x, skipping", i + 1,
   1864                  (unsigned int)pfd.dwFlags);
   1865             continue;
   1866         }
   1867 
   1868         c->base.doubleBufferMode =
   1869             (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
   1870         c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
   1871 
   1872         c->base.redBits = pfd.cRedBits;
   1873         c->base.greenBits = pfd.cGreenBits;
   1874         c->base.blueBits = pfd.cBlueBits;
   1875         c->base.alphaBits = pfd.cAlphaBits;
   1876 
   1877         c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift);
   1878         c->base.greenMask =
   1879             BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift);
   1880         c->base.blueMask =
   1881             BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift);
   1882         c->base.alphaMask =
   1883             BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift);
   1884 
   1885         c->base.rgbBits = pfd.cColorBits;
   1886 
   1887         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
   1888             c->base.indexBits = pfd.cColorBits;
   1889         }
   1890         else {
   1891             c->base.indexBits = 0;
   1892         }
   1893 
   1894         c->base.accumRedBits = pfd.cAccumRedBits;
   1895         c->base.accumGreenBits = pfd.cAccumGreenBits;
   1896         c->base.accumBlueBits = pfd.cAccumBlueBits;
   1897         c->base.accumAlphaBits = pfd.cAccumAlphaBits;
   1898         //  pfd.cAccumBits;
   1899 
   1900         c->base.depthBits = pfd.cDepthBits;
   1901         c->base.stencilBits = pfd.cStencilBits;
   1902         c->base.numAuxBuffers = pfd.cAuxBuffers;
   1903 
   1904         // pfd.iLayerType; // ignored
   1905         c->base.level = 0;
   1906         // pfd.dwLayerMask; // ignored
   1907         // pfd.dwDamageMask;  // ignored
   1908 
   1909         c->base.visualID = -1;  // will be set by __glXScreenInit()
   1910 
   1911         /* EXT_visual_rating / GLX 1.2 */
   1912         if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
   1913             c->base.visualRating = GLX_SLOW_VISUAL_EXT;
   1914             GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
   1915             continue;
   1916         }
   1917         else {
   1918             // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD accelerated...
   1919             c->base.visualRating = GLX_NONE_EXT;
   1920         }
   1921 
   1922         /* EXT_visual_info / GLX 1.2 */
   1923         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
   1924             c->base.visualType = GLX_STATIC_COLOR;
   1925             c->base.transparentRed = GLX_NONE;
   1926             c->base.transparentGreen = GLX_NONE;
   1927             c->base.transparentBlue = GLX_NONE;
   1928             c->base.transparentAlpha = GLX_NONE;
   1929             c->base.transparentIndex = pfd.dwVisibleMask;
   1930             c->base.transparentPixel = GLX_TRANSPARENT_INDEX;
   1931         }
   1932         else {
   1933             c->base.visualType = GLX_TRUE_COLOR;
   1934             c->base.transparentRed =
   1935                 (pfd.dwVisibleMask & c->base.redMask) >> pfd.cRedShift;
   1936             c->base.transparentGreen =
   1937                 (pfd.dwVisibleMask & c->base.greenMask) >> pfd.cGreenShift;
   1938             c->base.transparentBlue =
   1939                 (pfd.dwVisibleMask & c->base.blueMask) >> pfd.cBlueShift;
   1940             c->base.transparentAlpha =
   1941                 (pfd.dwVisibleMask & c->base.alphaMask) >> pfd.cAlphaShift;
   1942             c->base.transparentIndex = GLX_NONE;
   1943             c->base.transparentPixel = GLX_TRANSPARENT_RGB;
   1944         }
   1945 
   1946         /* ARB_multisample / SGIS_multisample */
   1947         c->base.sampleBuffers = 0;
   1948         c->base.samples = 0;
   1949 
   1950         /* SGIX_fbconfig / GLX 1.3 */
   1951         c->base.drawableType =
   1952             (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0)
   1953              | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0));
   1954 
   1955         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
   1956             c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
   1957         }
   1958         else {
   1959             c->base.renderType = GLX_RGBA_BIT;
   1960         }
   1961 
   1962         c->base.fbconfigID = -1;        // will be set by __glXScreenInit()
   1963 
   1964         /* SGIX_pbuffer / GLX 1.3 */
   1965         // XXX: How can we find these values out ???
   1966         c->base.maxPbufferWidth = -1;
   1967         c->base.maxPbufferHeight = -1;
   1968         c->base.maxPbufferPixels = -1;
   1969         c->base.optimalPbufferWidth = 0;        // there is no optimal value
   1970         c->base.optimalPbufferHeight = 0;
   1971 
   1972         /* SGIX_visual_select_group */
   1973         // arrange for visuals with the best acceleration to be preferred in selection
   1974         switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) {
   1975         case 0:
   1976             c->base.visualSelectGroup = 2;
   1977             break;
   1978 
   1979         case PFD_GENERIC_ACCELERATED:
   1980             c->base.visualSelectGroup = 1;
   1981             break;
   1982 
   1983         case PFD_GENERIC_FORMAT:
   1984             c->base.visualSelectGroup = 0;
   1985             break;
   1986 
   1987         default:
   1988             ;
   1989             // "can't happen"
   1990         }
   1991 
   1992         /* OML_swap_method */
   1993         if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
   1994             c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
   1995         else if (pfd.dwFlags & PFD_SWAP_COPY)
   1996             c->base.swapMethod = GLX_SWAP_COPY_OML;
   1997         else
   1998             c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
   1999 
   2000         /* EXT_texture_from_pixmap */
   2001         c->base.bindToTextureRgb = -1;
   2002         c->base.bindToTextureRgba = -1;
   2003         c->base.bindToMipmapTexture = -1;
   2004         c->base.bindToTextureTargets = -1;
   2005         c->base.yInverted = -1;
   2006         c->base.sRGBCapable = 0;
   2007 
   2008         n++;
   2009 
   2010         // allocate and save
   2011         work = malloc(sizeof(GLXWinConfig));
   2012         if (NULL == work) {
   2013             ErrorF("Failed to allocate GLXWinConfig\n");
   2014             break;
   2015         }
   2016         *work = temp;
   2017 
   2018         // note the first config
   2019         if (!first)
   2020             first = work;
   2021 
   2022         // update previous config to point to this config
   2023         if (prev)
   2024             prev->base.next = &(work->base);
   2025         prev = work;
   2026     }
   2027 
   2028     GLWIN_DEBUG_MSG
   2029         ("found %d pixelFormats suitable for conversion to fbConfigs", n);
   2030 
   2031     screen->base.numFBConfigs = n;
   2032     screen->base.fbconfigs = first ? &(first->base) : NULL;
   2033 }
   2034 
   2035 // helper function to access an attribute value from an attribute value array by attribute
   2036 static
   2037     int
   2038 getAttrValue(const int attrs[], int values[], unsigned int num, int attr,
   2039              int fallback)
   2040 {
   2041     unsigned int i;
   2042 
   2043     for (i = 0; i < num; i++) {
   2044         if (attrs[i] == attr) {
   2045             GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr,
   2046                             values[i]);
   2047             return values[i];
   2048         }
   2049     }
   2050 
   2051     ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n",
   2052            attr, fallback);
   2053     return fallback;
   2054 }
   2055 
   2056 //
   2057 // Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
   2058 //
   2059 static void
   2060 glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, PixelFormatRejectStats * rejects)
   2061 {
   2062     GLXWinConfig *first = NULL, *prev = NULL;
   2063     int i = 0;
   2064     int n = 0;
   2065 
   2066     const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
   2067     int numConfigs;
   2068 
   2069     int attrs[50];
   2070     unsigned int num_attrs = 0;
   2071 
   2072     GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
   2073 
   2074     screen->base.numFBConfigs = 0;
   2075     screen->base.fbconfigs = NULL;
   2076 
   2077     if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs)) {
   2078         ErrorF
   2079             ("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n",
   2080              glxWinErrorMessage());
   2081         return;
   2082     }
   2083 
   2084     LogMessage(X_INFO,
   2085                "%d pixel formats reported by wglGetPixelFormatAttribivARB\n",
   2086                numConfigs);
   2087 
   2088     n = 0;
   2089 
   2090 #define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < ARRAY_SIZE(attrs)); }
   2091 
   2092     ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB);
   2093     ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB);
   2094     ADD_ATTR(WGL_ACCELERATION_ARB);
   2095     ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB);
   2096     ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB);
   2097     ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB);
   2098     ADD_ATTR(WGL_TRANSPARENT_ARB);
   2099     ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB);
   2100     ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
   2101     ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
   2102     ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB);
   2103     ADD_ATTR(WGL_SUPPORT_OPENGL_ARB);
   2104     ADD_ATTR(WGL_DOUBLE_BUFFER_ARB);
   2105     ADD_ATTR(WGL_STEREO_ARB);
   2106     ADD_ATTR(WGL_PIXEL_TYPE_ARB);
   2107     ADD_ATTR(WGL_COLOR_BITS_ARB);
   2108     ADD_ATTR(WGL_RED_BITS_ARB);
   2109     ADD_ATTR(WGL_RED_SHIFT_ARB);
   2110     ADD_ATTR(WGL_GREEN_BITS_ARB);
   2111     ADD_ATTR(WGL_GREEN_SHIFT_ARB);
   2112     ADD_ATTR(WGL_BLUE_BITS_ARB);
   2113     ADD_ATTR(WGL_BLUE_SHIFT_ARB);
   2114     ADD_ATTR(WGL_ALPHA_BITS_ARB);
   2115     ADD_ATTR(WGL_ALPHA_SHIFT_ARB);
   2116     ADD_ATTR(WGL_ACCUM_RED_BITS_ARB);
   2117     ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB);
   2118     ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB);
   2119     ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB);
   2120     ADD_ATTR(WGL_DEPTH_BITS_ARB);
   2121     ADD_ATTR(WGL_STENCIL_BITS_ARB);
   2122     ADD_ATTR(WGL_AUX_BUFFERS_ARB);
   2123     ADD_ATTR(WGL_SWAP_METHOD_ARB);
   2124 
   2125     if (screen->has_WGL_ARB_multisample) {
   2126         // we may not query these attrs if WGL_ARB_multisample is not offered
   2127         ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB);
   2128         ADD_ATTR(WGL_SAMPLES_ARB);
   2129     }
   2130 
   2131     if (screen->has_WGL_ARB_render_texture) {
   2132         // we may not query these attrs if WGL_ARB_render_texture is not offered
   2133         ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB);
   2134         ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB);
   2135     }
   2136 
   2137     if (screen->has_WGL_ARB_pbuffer) {
   2138         // we may not query these attrs if WGL_ARB_pbuffer is not offered
   2139         ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB);
   2140         ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB);
   2141         ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB);
   2142         ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB);
   2143     }
   2144 
   2145     if (screen->has_WGL_ARB_framebuffer_sRGB) {
   2146         // we may not query these attrs if WGL_ARB_framebuffer_sRGB is not offered
   2147         ADD_ATTR(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
   2148     }
   2149 
   2150     /* fill in configs */
   2151     for (i = 0; i < numConfigs; i++) {
   2152         int values[num_attrs];
   2153         GLXWinConfig temp;
   2154         GLXWinConfig *c = &temp;
   2155         GLXWinConfig *work;
   2156         memset(c, 0, sizeof(GLXWinConfig));
   2157 
   2158         c->pixelFormatIndex = i + 1;
   2159 
   2160         if (!wglGetPixelFormatAttribivARBWrapper
   2161             (hdc, i + 1, 0, num_attrs, attrs, values)) {
   2162             ErrorF
   2163                 ("wglGetPixelFormatAttribivARB failed for index %d, error %s\n",
   2164                  i + 1, glxWinErrorMessage());
   2165             break;
   2166         }
   2167 
   2168 #define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
   2169 
   2170         if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) {
   2171             rejects->notOpenGL++;
   2172             GLWIN_DEBUG_MSG
   2173                 ("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping",
   2174                  i + 1);
   2175             continue;
   2176         }
   2177 
   2178         c->base.doubleBufferMode =
   2179             ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE;
   2180         c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE;
   2181 
   2182         c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0);
   2183         c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0);
   2184         c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0);
   2185         c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0);
   2186 
   2187         c->base.redMask =
   2188             BITS_AND_SHIFT_TO_MASK(c->base.redBits,
   2189                                    ATTR_VALUE(WGL_RED_SHIFT_ARB, 0));
   2190         c->base.greenMask =
   2191             BITS_AND_SHIFT_TO_MASK(c->base.greenBits,
   2192                                    ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0));
   2193         c->base.blueMask =
   2194             BITS_AND_SHIFT_TO_MASK(c->base.blueBits,
   2195                                    ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0));
   2196         c->base.alphaMask =
   2197             BITS_AND_SHIFT_TO_MASK(c->base.alphaBits,
   2198                                    ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0));
   2199 
   2200         switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)) {
   2201         case WGL_TYPE_COLORINDEX_ARB:
   2202             c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
   2203             c->base.rgbBits = 0;
   2204             c->base.visualType = GLX_STATIC_COLOR;
   2205             c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
   2206 
   2207             /*
   2208               Assume RGBA rendering is available on all single-channel visuals
   2209               (it is specified to render to red component in single-channel
   2210               visuals, if supported, but there doesn't seem to be any mechanism
   2211               to check if it is supported)
   2212 
   2213               Color index rendering is only supported on single-channel visuals
   2214             */
   2215 
   2216             break;
   2217 
   2218         case WGL_TYPE_RGBA_ARB:
   2219             c->base.indexBits = 0;
   2220             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
   2221             c->base.visualType = GLX_TRUE_COLOR;
   2222             c->base.renderType = GLX_RGBA_BIT;
   2223             break;
   2224 
   2225         case WGL_TYPE_RGBA_FLOAT_ARB:
   2226             c->base.indexBits = 0;
   2227             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
   2228             c->base.visualType = GLX_TRUE_COLOR;
   2229             c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB;
   2230             // assert pbuffer drawable
   2231             // assert WGL_ARB_pixel_format_float
   2232             break;
   2233 
   2234         case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
   2235             c->base.indexBits = 0;
   2236             c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
   2237             c->base.visualType = GLX_TRUE_COLOR;
   2238             c->base.renderType = GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
   2239             // assert pbuffer drawable
   2240             // assert WGL_EXT_pixel_format_packed_float
   2241             break;
   2242 
   2243         default:
   2244             rejects->unknownPixelType++;
   2245             ErrorF
   2246                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n",
   2247                  ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
   2248             continue;
   2249         }
   2250 
   2251         c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0);
   2252         c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0);
   2253         c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0);
   2254         c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0);
   2255 
   2256         c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0);
   2257         c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0);
   2258         c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0);
   2259 
   2260         {
   2261             int layers =
   2262                 ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,
   2263                            0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
   2264 
   2265             if (layers > 0) {
   2266                 ErrorF
   2267                     ("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled\n",
   2268                      i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB, 0),
   2269                      ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0));
   2270                 // XXX: need to iterate over layers?
   2271             }
   2272         }
   2273         c->base.level = 0;
   2274 
   2275         c->base.visualID = -1;  // will be set by __glXScreenInit()
   2276 
   2277         /* EXT_visual_rating / GLX 1.2 */
   2278         switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) {
   2279         default:
   2280             ErrorF
   2281                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n",
   2282                  ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
   2283 
   2284         case WGL_NO_ACCELERATION_ARB:
   2285             rejects->unaccelerated++;
   2286             c->base.visualRating = GLX_SLOW_VISUAL_EXT;
   2287             GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1);
   2288             continue;
   2289             break;
   2290 
   2291         case WGL_GENERIC_ACCELERATION_ARB:
   2292         case WGL_FULL_ACCELERATION_ARB:
   2293             c->base.visualRating = GLX_NONE_EXT;
   2294             break;
   2295         }
   2296 
   2297         /* EXT_visual_info / GLX 1.2 */
   2298         // c->base.visualType is set above
   2299         if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0)) {
   2300             c->base.transparentPixel =
   2301                 (c->base.visualType ==
   2302                  GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT :
   2303                 GLX_TRANSPARENT_INDEX_EXT;
   2304             c->base.transparentRed =
   2305                 ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0);
   2306             c->base.transparentGreen =
   2307                 ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0);
   2308             c->base.transparentBlue =
   2309                 ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0);
   2310             c->base.transparentAlpha =
   2311                 ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0);
   2312             c->base.transparentIndex =
   2313                 ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0);
   2314         }
   2315         else {
   2316             c->base.transparentPixel = GLX_NONE_EXT;
   2317             c->base.transparentRed = GLX_NONE;
   2318             c->base.transparentGreen = GLX_NONE;
   2319             c->base.transparentBlue = GLX_NONE;
   2320             c->base.transparentAlpha = GLX_NONE;
   2321             c->base.transparentIndex = GLX_NONE;
   2322         }
   2323 
   2324         /* ARB_multisample / SGIS_multisample */
   2325         if (screen->has_WGL_ARB_multisample) {
   2326             c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0);
   2327             c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0);
   2328         }
   2329         else {
   2330             c->base.sampleBuffers = 0;
   2331             c->base.samples = 0;
   2332         }
   2333 
   2334         /* SGIX_fbconfig / GLX 1.3 */
   2335         c->base.drawableType =
   2336             ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0)
   2337              | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0)
   2338              | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0));
   2339 
   2340         c->base.fbconfigID = -1;        // will be set by __glXScreenInit()
   2341 
   2342         /* SGIX_pbuffer / GLX 1.3 */
   2343         if (screen->has_WGL_ARB_pbuffer) {
   2344             c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
   2345             c->base.maxPbufferHeight =
   2346                 ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
   2347             c->base.maxPbufferPixels =
   2348                 ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
   2349         }
   2350         else {
   2351             c->base.maxPbufferWidth = -1;
   2352             c->base.maxPbufferHeight = -1;
   2353             c->base.maxPbufferPixels = -1;
   2354         }
   2355         c->base.optimalPbufferWidth = 0;        // there is no optimal value
   2356         c->base.optimalPbufferHeight = 0;
   2357 
   2358         /* SGIX_visual_select_group */
   2359         // arrange for visuals with the best acceleration to be preferred in selection
   2360         switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) {
   2361         case WGL_FULL_ACCELERATION_ARB:
   2362             c->base.visualSelectGroup = 2;
   2363             break;
   2364 
   2365         case WGL_GENERIC_ACCELERATION_ARB:
   2366             c->base.visualSelectGroup = 1;
   2367             break;
   2368 
   2369         default:
   2370         case WGL_NO_ACCELERATION_ARB:
   2371             c->base.visualSelectGroup = 0;
   2372             break;
   2373         }
   2374 
   2375         /* OML_swap_method */
   2376         switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)) {
   2377         case WGL_SWAP_EXCHANGE_ARB:
   2378             c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
   2379             break;
   2380 
   2381         case WGL_SWAP_COPY_ARB:
   2382             c->base.swapMethod = GLX_SWAP_COPY_OML;
   2383             break;
   2384 
   2385         default:
   2386             ErrorF
   2387                 ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n",
   2388                  ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
   2389 
   2390         case WGL_SWAP_UNDEFINED_ARB:
   2391             c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
   2392         }
   2393 
   2394         /* EXT_texture_from_pixmap */
   2395         /*
   2396            Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting
   2397            bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use,
   2398            so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea...
   2399          */
   2400         if (screen->has_WGL_ARB_render_texture) {
   2401             c->base.bindToTextureRgb =
   2402                 ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1);
   2403             c->base.bindToTextureRgba =
   2404                 ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1);
   2405         }
   2406         else {
   2407             c->base.bindToTextureRgb = -1;
   2408             c->base.bindToTextureRgba = -1;
   2409         }
   2410         c->base.bindToMipmapTexture = -1;
   2411         c->base.bindToTextureTargets =
   2412             GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT |
   2413             GLX_TEXTURE_RECTANGLE_BIT_EXT;
   2414         c->base.yInverted = -1;
   2415 
   2416         /* WGL_ARB_framebuffer_sRGB */
   2417         if (screen->has_WGL_ARB_framebuffer_sRGB)
   2418             c->base.sRGBCapable = ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, 0);
   2419         else
   2420             c->base.sRGBCapable = 0;
   2421 
   2422         n++;
   2423 
   2424         // allocate and save
   2425         work = malloc(sizeof(GLXWinConfig));
   2426         if (NULL == work) {
   2427             ErrorF("Failed to allocate GLXWinConfig\n");
   2428             break;
   2429         }
   2430         *work = temp;
   2431 
   2432         // note the first config
   2433         if (!first)
   2434             first = work;
   2435 
   2436         // update previous config to point to this config
   2437         if (prev)
   2438             prev->base.next = &(work->base);
   2439         prev = work;
   2440     }
   2441 
   2442     screen->base.numFBConfigs = n;
   2443     screen->base.fbconfigs = first ? &(first->base) : NULL;
   2444 }