volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

wgl_context.c (27071B)


      1 //========================================================================
      2 // GLFW 3.4 WGL - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
      6 //
      7 // This software is provided 'as-is', without any express or implied
      8 // warranty. In no event will the authors be held liable for any damages
      9 // arising from the use of this software.
     10 //
     11 // Permission is granted to anyone to use this software for any purpose,
     12 // including commercial applications, and to alter it and redistribute it
     13 // freely, subject to the following restrictions:
     14 //
     15 // 1. The origin of this software must not be misrepresented; you must not
     16 //    claim that you wrote the original software. If you use this software
     17 //    in a product, an acknowledgment in the product documentation would
     18 //    be appreciated but is not required.
     19 //
     20 // 2. Altered source versions must be plainly marked as such, and must not
     21 //    be misrepresented as being the original software.
     22 //
     23 // 3. This notice may not be removed or altered from any source
     24 //    distribution.
     25 //
     26 //========================================================================
     27 
     28 #include "internal.h"
     29 
     30 #if defined(_GLFW_WIN32)
     31 
     32 #include <stdlib.h>
     33 #include <assert.h>
     34 
     35 // Return the value corresponding to the specified attribute
     36 //
     37 static int findPixelFormatAttribValueWGL(const int* attribs,
     38                                          int attribCount,
     39                                          const int* values,
     40                                          int attrib)
     41 {
     42     int i;
     43 
     44     for (i = 0;  i < attribCount;  i++)
     45     {
     46         if (attribs[i] == attrib)
     47             return values[i];
     48     }
     49 
     50     _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
     51                          "WGL: Unknown pixel format attribute requested");
     52     return 0;
     53 }
     54 
     55 #define ADD_ATTRIB(a) \
     56 { \
     57     assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
     58     attribs[attribCount++] = a; \
     59 }
     60 #define FIND_ATTRIB_VALUE(a) \
     61     findPixelFormatAttribValueWGL(attribs, attribCount, values, a)
     62 
     63 // Return a list of available and usable framebuffer configs
     64 //
     65 static int choosePixelFormatWGL(_GLFWwindow* window,
     66                                 const _GLFWctxconfig* ctxconfig,
     67                                 const _GLFWfbconfig* fbconfig)
     68 {
     69     _GLFWfbconfig* usableConfigs;
     70     const _GLFWfbconfig* closest;
     71     int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
     72     int attribs[40];
     73     int values[sizeof(attribs) / sizeof(attribs[0])];
     74 
     75     nativeCount = DescribePixelFormat(window->context.wgl.dc,
     76                                       1,
     77                                       sizeof(PIXELFORMATDESCRIPTOR),
     78                                       NULL);
     79 
     80     if (_glfw.wgl.ARB_pixel_format)
     81     {
     82         ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB);
     83         ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB);
     84         ADD_ATTRIB(WGL_PIXEL_TYPE_ARB);
     85         ADD_ATTRIB(WGL_ACCELERATION_ARB);
     86         ADD_ATTRIB(WGL_RED_BITS_ARB);
     87         ADD_ATTRIB(WGL_RED_SHIFT_ARB);
     88         ADD_ATTRIB(WGL_GREEN_BITS_ARB);
     89         ADD_ATTRIB(WGL_GREEN_SHIFT_ARB);
     90         ADD_ATTRIB(WGL_BLUE_BITS_ARB);
     91         ADD_ATTRIB(WGL_BLUE_SHIFT_ARB);
     92         ADD_ATTRIB(WGL_ALPHA_BITS_ARB);
     93         ADD_ATTRIB(WGL_ALPHA_SHIFT_ARB);
     94         ADD_ATTRIB(WGL_DEPTH_BITS_ARB);
     95         ADD_ATTRIB(WGL_STENCIL_BITS_ARB);
     96         ADD_ATTRIB(WGL_ACCUM_BITS_ARB);
     97         ADD_ATTRIB(WGL_ACCUM_RED_BITS_ARB);
     98         ADD_ATTRIB(WGL_ACCUM_GREEN_BITS_ARB);
     99         ADD_ATTRIB(WGL_ACCUM_BLUE_BITS_ARB);
    100         ADD_ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB);
    101         ADD_ATTRIB(WGL_AUX_BUFFERS_ARB);
    102         ADD_ATTRIB(WGL_STEREO_ARB);
    103         ADD_ATTRIB(WGL_DOUBLE_BUFFER_ARB);
    104 
    105         if (_glfw.wgl.ARB_multisample)
    106             ADD_ATTRIB(WGL_SAMPLES_ARB);
    107 
    108         if (ctxconfig->client == GLFW_OPENGL_API)
    109         {
    110             if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
    111                 ADD_ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
    112         }
    113         else
    114         {
    115             if (_glfw.wgl.EXT_colorspace)
    116                 ADD_ATTRIB(WGL_COLORSPACE_EXT);
    117         }
    118 
    119         // NOTE: In a Parallels VM WGL_ARB_pixel_format returns fewer pixel formats than
    120         //       DescribePixelFormat, violating the guarantees of the extension spec
    121         // HACK: Iterate through the minimum of both counts
    122 
    123         const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
    124         int extensionCount;
    125 
    126         if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
    127                                           1, 0, 1, &attrib, &extensionCount))
    128         {
    129             _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    130                                  "WGL: Failed to retrieve pixel format attribute");
    131             return 0;
    132         }
    133 
    134         nativeCount = _glfw_min(nativeCount, extensionCount);
    135     }
    136 
    137     usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig));
    138 
    139     for (i = 0;  i < nativeCount;  i++)
    140     {
    141         _GLFWfbconfig* u = usableConfigs + usableCount;
    142         pixelFormat = i + 1;
    143 
    144         if (_glfw.wgl.ARB_pixel_format)
    145         {
    146             // Get pixel format attributes through "modern" extension
    147 
    148             if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
    149                                               pixelFormat, 0,
    150                                               attribCount,
    151                                               attribs, values))
    152             {
    153                 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    154                                     "WGL: Failed to retrieve pixel format attributes");
    155 
    156                 _glfw_free(usableConfigs);
    157                 return 0;
    158             }
    159 
    160             if (!FIND_ATTRIB_VALUE(WGL_SUPPORT_OPENGL_ARB) ||
    161                 !FIND_ATTRIB_VALUE(WGL_DRAW_TO_WINDOW_ARB))
    162             {
    163                 continue;
    164             }
    165 
    166             if (FIND_ATTRIB_VALUE(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
    167                 continue;
    168 
    169             if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
    170                 continue;
    171 
    172             if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
    173                 continue;
    174 
    175             u->redBits = FIND_ATTRIB_VALUE(WGL_RED_BITS_ARB);
    176             u->greenBits = FIND_ATTRIB_VALUE(WGL_GREEN_BITS_ARB);
    177             u->blueBits = FIND_ATTRIB_VALUE(WGL_BLUE_BITS_ARB);
    178             u->alphaBits = FIND_ATTRIB_VALUE(WGL_ALPHA_BITS_ARB);
    179 
    180             u->depthBits = FIND_ATTRIB_VALUE(WGL_DEPTH_BITS_ARB);
    181             u->stencilBits = FIND_ATTRIB_VALUE(WGL_STENCIL_BITS_ARB);
    182 
    183             u->accumRedBits = FIND_ATTRIB_VALUE(WGL_ACCUM_RED_BITS_ARB);
    184             u->accumGreenBits = FIND_ATTRIB_VALUE(WGL_ACCUM_GREEN_BITS_ARB);
    185             u->accumBlueBits = FIND_ATTRIB_VALUE(WGL_ACCUM_BLUE_BITS_ARB);
    186             u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
    187 
    188             u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
    189 
    190             if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
    191                 u->stereo = GLFW_TRUE;
    192 
    193             if (_glfw.wgl.ARB_multisample)
    194                 u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
    195 
    196             if (ctxconfig->client == GLFW_OPENGL_API)
    197             {
    198                 if (_glfw.wgl.ARB_framebuffer_sRGB ||
    199                     _glfw.wgl.EXT_framebuffer_sRGB)
    200                 {
    201                     if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
    202                         u->sRGB = GLFW_TRUE;
    203                 }
    204             }
    205             else
    206             {
    207                 if (_glfw.wgl.EXT_colorspace)
    208                 {
    209                     if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
    210                         u->sRGB = GLFW_TRUE;
    211                 }
    212             }
    213         }
    214         else
    215         {
    216             // Get pixel format attributes through legacy PFDs
    217 
    218             PIXELFORMATDESCRIPTOR pfd;
    219 
    220             if (!DescribePixelFormat(window->context.wgl.dc,
    221                                      pixelFormat,
    222                                      sizeof(PIXELFORMATDESCRIPTOR),
    223                                      &pfd))
    224             {
    225                 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    226                                     "WGL: Failed to describe pixel format");
    227 
    228                 _glfw_free(usableConfigs);
    229                 return 0;
    230             }
    231 
    232             if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
    233                 !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
    234             {
    235                 continue;
    236             }
    237 
    238             if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
    239                 (pfd.dwFlags & PFD_GENERIC_FORMAT))
    240             {
    241                 continue;
    242             }
    243 
    244             if (pfd.iPixelType != PFD_TYPE_RGBA)
    245                 continue;
    246 
    247             if (!!(pfd.dwFlags & PFD_DOUBLEBUFFER) != fbconfig->doublebuffer)
    248                 continue;
    249 
    250             u->redBits = pfd.cRedBits;
    251             u->greenBits = pfd.cGreenBits;
    252             u->blueBits = pfd.cBlueBits;
    253             u->alphaBits = pfd.cAlphaBits;
    254 
    255             u->depthBits = pfd.cDepthBits;
    256             u->stencilBits = pfd.cStencilBits;
    257 
    258             u->accumRedBits = pfd.cAccumRedBits;
    259             u->accumGreenBits = pfd.cAccumGreenBits;
    260             u->accumBlueBits = pfd.cAccumBlueBits;
    261             u->accumAlphaBits = pfd.cAccumAlphaBits;
    262 
    263             u->auxBuffers = pfd.cAuxBuffers;
    264 
    265             if (pfd.dwFlags & PFD_STEREO)
    266                 u->stereo = GLFW_TRUE;
    267         }
    268 
    269         u->handle = pixelFormat;
    270         usableCount++;
    271     }
    272 
    273     if (!usableCount)
    274     {
    275         _glfwInputError(GLFW_API_UNAVAILABLE,
    276                         "WGL: The driver does not appear to support OpenGL");
    277 
    278         _glfw_free(usableConfigs);
    279         return 0;
    280     }
    281 
    282     closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
    283     if (!closest)
    284     {
    285         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
    286                         "WGL: Failed to find a suitable pixel format");
    287 
    288         _glfw_free(usableConfigs);
    289         return 0;
    290     }
    291 
    292     pixelFormat = (int) closest->handle;
    293     _glfw_free(usableConfigs);
    294 
    295     return pixelFormat;
    296 }
    297 
    298 #undef ADD_ATTRIB
    299 #undef FIND_ATTRIB_VALUE
    300 
    301 static void makeContextCurrentWGL(_GLFWwindow* window)
    302 {
    303     if (window)
    304     {
    305         if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
    306             _glfwPlatformSetTls(&_glfw.contextSlot, window);
    307         else
    308         {
    309             _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    310                                  "WGL: Failed to make context current");
    311             _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
    312         }
    313     }
    314     else
    315     {
    316         if (!wglMakeCurrent(NULL, NULL))
    317         {
    318             _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    319                                  "WGL: Failed to clear current context");
    320         }
    321 
    322         _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
    323     }
    324 }
    325 
    326 static void swapBuffersWGL(_GLFWwindow* window)
    327 {
    328     if (!window->monitor)
    329     {
    330         // HACK: Use DwmFlush when desktop composition is enabled on Windows Vista and 7
    331         if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater())
    332         {
    333             BOOL enabled = FALSE;
    334 
    335             if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
    336             {
    337                 int count = abs(window->context.wgl.interval);
    338                 while (count--)
    339                     DwmFlush();
    340             }
    341         }
    342     }
    343 
    344     SwapBuffers(window->context.wgl.dc);
    345 }
    346 
    347 static void swapIntervalWGL(int interval)
    348 {
    349     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
    350     assert(window != NULL);
    351 
    352     window->context.wgl.interval = interval;
    353 
    354     if (!window->monitor)
    355     {
    356         // HACK: Disable WGL swap interval when desktop composition is enabled on Windows
    357         //       Vista and 7 to avoid interfering with DWM vsync
    358         if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater())
    359         {
    360             BOOL enabled = FALSE;
    361 
    362             if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
    363                 interval = 0;
    364         }
    365     }
    366 
    367     if (_glfw.wgl.EXT_swap_control)
    368         wglSwapIntervalEXT(interval);
    369 }
    370 
    371 static int extensionSupportedWGL(const char* extension)
    372 {
    373     const char* extensions = NULL;
    374 
    375     if (_glfw.wgl.GetExtensionsStringARB)
    376         extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
    377     else if (_glfw.wgl.GetExtensionsStringEXT)
    378         extensions = wglGetExtensionsStringEXT();
    379 
    380     if (!extensions)
    381         return GLFW_FALSE;
    382 
    383     return _glfwStringInExtensionString(extension, extensions);
    384 }
    385 
    386 static GLFWglproc getProcAddressWGL(const char* procname)
    387 {
    388     const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
    389     if (proc)
    390         return proc;
    391 
    392     return (GLFWglproc) _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, procname);
    393 }
    394 
    395 static void destroyContextWGL(_GLFWwindow* window)
    396 {
    397     if (window->context.wgl.handle)
    398     {
    399         wglDeleteContext(window->context.wgl.handle);
    400         window->context.wgl.handle = NULL;
    401     }
    402 }
    403 
    404 // Initialize WGL
    405 //
    406 GLFWbool _glfwInitWGL(void)
    407 {
    408     PIXELFORMATDESCRIPTOR pfd;
    409     HGLRC prc, rc;
    410     HDC pdc, dc;
    411 
    412     if (_glfw.wgl.instance)
    413         return GLFW_TRUE;
    414 
    415     _glfw.wgl.instance = _glfwPlatformLoadModule("opengl32.dll");
    416     if (!_glfw.wgl.instance)
    417     {
    418         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    419                              "WGL: Failed to load opengl32.dll");
    420         return GLFW_FALSE;
    421     }
    422 
    423     _glfw.wgl.CreateContext = (PFN_wglCreateContext)
    424         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglCreateContext");
    425     _glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
    426         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglDeleteContext");
    427     _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
    428         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetProcAddress");
    429     _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
    430         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetCurrentDC");
    431     _glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
    432         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetCurrentContext");
    433     _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
    434         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglMakeCurrent");
    435     _glfw.wgl.ShareLists = (PFN_wglShareLists)
    436         _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglShareLists");
    437 
    438     // NOTE: A dummy context has to be created for opengl32.dll to load the
    439     //       OpenGL ICD, from which we can then query WGL extensions
    440     // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
    441     //       creation failure occurs during manual pixel format enumeration
    442 
    443     dc = GetDC(_glfw.win32.helperWindowHandle);
    444 
    445     ZeroMemory(&pfd, sizeof(pfd));
    446     pfd.nSize = sizeof(pfd);
    447     pfd.nVersion = 1;
    448     pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    449     pfd.iPixelType = PFD_TYPE_RGBA;
    450     pfd.cColorBits = 24;
    451 
    452     if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
    453     {
    454         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    455                              "WGL: Failed to set pixel format for dummy context");
    456         return GLFW_FALSE;
    457     }
    458 
    459     rc = wglCreateContext(dc);
    460     if (!rc)
    461     {
    462         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    463                              "WGL: Failed to create dummy context");
    464         return GLFW_FALSE;
    465     }
    466 
    467     pdc = wglGetCurrentDC();
    468     prc = wglGetCurrentContext();
    469 
    470     if (!wglMakeCurrent(dc, rc))
    471     {
    472         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    473                              "WGL: Failed to make dummy context current");
    474         wglMakeCurrent(pdc, prc);
    475         wglDeleteContext(rc);
    476         return GLFW_FALSE;
    477     }
    478 
    479     // NOTE: Functions must be loaded first as they're needed to retrieve the
    480     //       extension string that tells us whether the functions are supported
    481     _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
    482         wglGetProcAddress("wglGetExtensionsStringEXT");
    483     _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
    484         wglGetProcAddress("wglGetExtensionsStringARB");
    485     _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
    486         wglGetProcAddress("wglCreateContextAttribsARB");
    487     _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
    488         wglGetProcAddress("wglSwapIntervalEXT");
    489     _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
    490         wglGetProcAddress("wglGetPixelFormatAttribivARB");
    491 
    492     // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
    493     //       checked below as we are already using them
    494     _glfw.wgl.ARB_multisample =
    495         extensionSupportedWGL("WGL_ARB_multisample");
    496     _glfw.wgl.ARB_framebuffer_sRGB =
    497         extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
    498     _glfw.wgl.EXT_framebuffer_sRGB =
    499         extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
    500     _glfw.wgl.ARB_create_context =
    501         extensionSupportedWGL("WGL_ARB_create_context");
    502     _glfw.wgl.ARB_create_context_profile =
    503         extensionSupportedWGL("WGL_ARB_create_context_profile");
    504     _glfw.wgl.EXT_create_context_es2_profile =
    505         extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
    506     _glfw.wgl.ARB_create_context_robustness =
    507         extensionSupportedWGL("WGL_ARB_create_context_robustness");
    508     _glfw.wgl.ARB_create_context_no_error =
    509         extensionSupportedWGL("WGL_ARB_create_context_no_error");
    510     _glfw.wgl.EXT_swap_control =
    511         extensionSupportedWGL("WGL_EXT_swap_control");
    512     _glfw.wgl.EXT_colorspace =
    513         extensionSupportedWGL("WGL_EXT_colorspace");
    514     _glfw.wgl.ARB_pixel_format =
    515         extensionSupportedWGL("WGL_ARB_pixel_format");
    516     _glfw.wgl.ARB_context_flush_control =
    517         extensionSupportedWGL("WGL_ARB_context_flush_control");
    518 
    519     wglMakeCurrent(pdc, prc);
    520     wglDeleteContext(rc);
    521     return GLFW_TRUE;
    522 }
    523 
    524 // Terminate WGL
    525 //
    526 void _glfwTerminateWGL(void)
    527 {
    528     if (_glfw.wgl.instance)
    529         _glfwPlatformFreeModule(_glfw.wgl.instance);
    530 }
    531 
    532 #define SET_ATTRIB(a, v) \
    533 { \
    534     assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
    535     attribs[index++] = a; \
    536     attribs[index++] = v; \
    537 }
    538 
    539 // Create the OpenGL or OpenGL ES context
    540 //
    541 GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
    542                                const _GLFWctxconfig* ctxconfig,
    543                                const _GLFWfbconfig* fbconfig)
    544 {
    545     int attribs[40];
    546     int pixelFormat;
    547     PIXELFORMATDESCRIPTOR pfd;
    548     HGLRC share = NULL;
    549 
    550     if (ctxconfig->share)
    551         share = ctxconfig->share->context.wgl.handle;
    552 
    553     window->context.wgl.dc = GetDC(window->win32.handle);
    554     if (!window->context.wgl.dc)
    555     {
    556         _glfwInputError(GLFW_PLATFORM_ERROR,
    557                         "WGL: Failed to retrieve DC for window");
    558         return GLFW_FALSE;
    559     }
    560 
    561     pixelFormat = choosePixelFormatWGL(window, ctxconfig, fbconfig);
    562     if (!pixelFormat)
    563         return GLFW_FALSE;
    564 
    565     if (!DescribePixelFormat(window->context.wgl.dc,
    566                              pixelFormat, sizeof(pfd), &pfd))
    567     {
    568         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    569                              "WGL: Failed to retrieve PFD for selected pixel format");
    570         return GLFW_FALSE;
    571     }
    572 
    573     if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
    574     {
    575         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    576                              "WGL: Failed to set selected pixel format");
    577         return GLFW_FALSE;
    578     }
    579 
    580     if (ctxconfig->client == GLFW_OPENGL_API)
    581     {
    582         if (ctxconfig->forward)
    583         {
    584             if (!_glfw.wgl.ARB_create_context)
    585             {
    586                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    587                                 "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
    588                 return GLFW_FALSE;
    589             }
    590         }
    591 
    592         if (ctxconfig->profile)
    593         {
    594             if (!_glfw.wgl.ARB_create_context_profile)
    595             {
    596                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    597                                 "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
    598                 return GLFW_FALSE;
    599             }
    600         }
    601     }
    602     else
    603     {
    604         if (!_glfw.wgl.ARB_create_context ||
    605             !_glfw.wgl.ARB_create_context_profile ||
    606             !_glfw.wgl.EXT_create_context_es2_profile)
    607         {
    608             _glfwInputError(GLFW_API_UNAVAILABLE,
    609                             "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
    610             return GLFW_FALSE;
    611         }
    612     }
    613 
    614     if (_glfw.wgl.ARB_create_context)
    615     {
    616         int index = 0, mask = 0, flags = 0;
    617 
    618         if (ctxconfig->client == GLFW_OPENGL_API)
    619         {
    620             if (ctxconfig->forward)
    621                 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
    622 
    623             if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
    624                 mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
    625             else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
    626                 mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
    627         }
    628         else
    629             mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
    630 
    631         if (ctxconfig->debug)
    632             flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
    633 
    634         if (ctxconfig->robustness)
    635         {
    636             if (_glfw.wgl.ARB_create_context_robustness)
    637             {
    638                 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
    639                 {
    640                     SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
    641                                WGL_NO_RESET_NOTIFICATION_ARB);
    642                 }
    643                 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
    644                 {
    645                     SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
    646                                WGL_LOSE_CONTEXT_ON_RESET_ARB);
    647                 }
    648 
    649                 flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
    650             }
    651         }
    652 
    653         if (ctxconfig->release)
    654         {
    655             if (_glfw.wgl.ARB_context_flush_control)
    656             {
    657                 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
    658                 {
    659                     SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
    660                                WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
    661                 }
    662                 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
    663                 {
    664                     SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
    665                                WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
    666                 }
    667             }
    668         }
    669 
    670         if (ctxconfig->noerror)
    671         {
    672             if (_glfw.wgl.ARB_create_context_no_error)
    673                 SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
    674         }
    675 
    676         // NOTE: Only request an explicitly versioned context when necessary, as
    677         //       explicitly requesting version 1.0 does not always return the
    678         //       highest version supported by the driver
    679         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
    680         {
    681             SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
    682             SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
    683         }
    684 
    685         if (flags)
    686             SET_ATTRIB(WGL_CONTEXT_FLAGS_ARB, flags);
    687 
    688         if (mask)
    689             SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
    690 
    691         SET_ATTRIB(0, 0);
    692 
    693         window->context.wgl.handle =
    694             wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
    695         if (!window->context.wgl.handle)
    696         {
    697             const DWORD error = GetLastError();
    698 
    699             if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
    700             {
    701                 if (ctxconfig->client == GLFW_OPENGL_API)
    702                 {
    703                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    704                                     "WGL: Driver does not support OpenGL version %i.%i",
    705                                     ctxconfig->major,
    706                                     ctxconfig->minor);
    707                 }
    708                 else
    709                 {
    710                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    711                                     "WGL: Driver does not support OpenGL ES version %i.%i",
    712                                     ctxconfig->major,
    713                                     ctxconfig->minor);
    714                 }
    715             }
    716             else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
    717             {
    718                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    719                                 "WGL: Driver does not support the requested OpenGL profile");
    720             }
    721             else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
    722             {
    723                 _glfwInputError(GLFW_INVALID_VALUE,
    724                                 "WGL: The share context is not compatible with the requested context");
    725             }
    726             else
    727             {
    728                 if (ctxconfig->client == GLFW_OPENGL_API)
    729                 {
    730                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    731                                     "WGL: Failed to create OpenGL context");
    732                 }
    733                 else
    734                 {
    735                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    736                                     "WGL: Failed to create OpenGL ES context");
    737                 }
    738             }
    739 
    740             return GLFW_FALSE;
    741         }
    742     }
    743     else
    744     {
    745         window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
    746         if (!window->context.wgl.handle)
    747         {
    748             _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
    749                                  "WGL: Failed to create OpenGL context");
    750             return GLFW_FALSE;
    751         }
    752 
    753         if (share)
    754         {
    755             if (!wglShareLists(share, window->context.wgl.handle))
    756             {
    757                 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    758                                      "WGL: Failed to enable sharing with specified OpenGL context");
    759                 return GLFW_FALSE;
    760             }
    761         }
    762     }
    763 
    764     window->context.makeCurrent = makeContextCurrentWGL;
    765     window->context.swapBuffers = swapBuffersWGL;
    766     window->context.swapInterval = swapIntervalWGL;
    767     window->context.extensionSupported = extensionSupportedWGL;
    768     window->context.getProcAddress = getProcAddressWGL;
    769     window->context.destroy = destroyContextWGL;
    770 
    771     return GLFW_TRUE;
    772 }
    773 
    774 #undef SET_ATTRIB
    775 
    776 GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
    777 {
    778     _GLFWwindow* window = (_GLFWwindow*) handle;
    779     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    780 
    781     if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
    782     {
    783         _glfwInputError(GLFW_PLATFORM_UNAVAILABLE,
    784                         "WGL: Platform not initialized");
    785         return NULL;
    786     }
    787 
    788     if (window->context.source != GLFW_NATIVE_CONTEXT_API)
    789     {
    790         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
    791         return NULL;
    792     }
    793 
    794     return window->context.wgl.handle;
    795 }
    796 
    797 #endif // _GLFW_WIN32
    798