• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // GLFW 3.5 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 //
findPixelFormatAttribValueWGL(const int * attribs,int attribCount,const int * values,int attrib)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 //
choosePixelFormatWGL(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)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 
makeContextCurrentWGL(_GLFWwindow * window)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 
swapBuffersWGL(_GLFWwindow * window)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 
swapIntervalWGL(int interval)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 
extensionSupportedWGL(const char * extension)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 
getProcAddressWGL(const char * procname)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 
destroyContextWGL(_GLFWwindow * window)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 //
_glfwInitWGL(void)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 //
_glfwTerminateWGL(void)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 //
_glfwCreateContextWGL(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)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 
glfwGetWGLContext(GLFWwindow * handle)776 GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
777 {
778     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
779 
780     if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
781     {
782         _glfwInputError(GLFW_PLATFORM_UNAVAILABLE,
783                         "WGL: Platform not initialized");
784         return NULL;
785     }
786 
787     _GLFWwindow* window = (_GLFWwindow*) handle;
788     assert(window != NULL);
789 
790     if (window->context.source != GLFW_NATIVE_CONTEXT_API)
791     {
792         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
793         return NULL;
794     }
795 
796     return window->context.wgl.handle;
797 }
798 
799 #endif // _GLFW_WIN32
800 
801