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