• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // GLFW 3.2 WGL - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2016 Camilla Berglund <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 #include <stdio.h>
31 #include <stdlib.h>
32 #include <malloc.h>
33 #include <assert.h>
34 
35 
36 // Returns the specified attribute of the specified pixel format
37 //
getPixelFormatAttrib(_GLFWwindow * window,int pixelFormat,int attrib)38 static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
39 {
40     int value = 0;
41 
42     assert(_glfw.wgl.ARB_pixel_format);
43 
44     if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
45                                              pixelFormat,
46                                              0, 1, &attrib, &value))
47     {
48         _glfwInputError(GLFW_PLATFORM_ERROR,
49                         "WGL: Failed to retrieve pixel format attribute %i",
50                         attrib);
51         return 0;
52     }
53 
54     return value;
55 }
56 
57 // Return a list of available and usable framebuffer configs
58 //
choosePixelFormat(_GLFWwindow * window,const _GLFWfbconfig * desired)59 static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
60 {
61     _GLFWfbconfig* usableConfigs;
62     const _GLFWfbconfig* closest;
63     int i, pixelFormat, nativeCount, usableCount;
64 
65     if (_glfw.wgl.ARB_pixel_format)
66     {
67         nativeCount = getPixelFormatAttrib(window,
68                                            1,
69                                            WGL_NUMBER_PIXEL_FORMATS_ARB);
70     }
71     else
72     {
73         nativeCount = DescribePixelFormat(window->context.wgl.dc,
74                                           1,
75                                           sizeof(PIXELFORMATDESCRIPTOR),
76                                           NULL);
77     }
78 
79     usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
80     usableCount = 0;
81 
82     for (i = 0;  i < nativeCount;  i++)
83     {
84         const int n = i + 1;
85         _GLFWfbconfig* u = usableConfigs + usableCount;
86 
87         if (_glfw.wgl.ARB_pixel_format)
88         {
89             // Get pixel format attributes through "modern" extension
90 
91             if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
92                 !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
93             {
94                 continue;
95             }
96 
97             if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
98                 WGL_TYPE_RGBA_ARB)
99             {
100                 continue;
101             }
102 
103             if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
104                  WGL_NO_ACCELERATION_ARB)
105             {
106                 continue;
107             }
108 
109             u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
110             u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
111             u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
112             u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
113 
114             u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
115             u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
116 
117             u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
118             u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
119             u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
120             u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
121 
122             u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
123 
124             if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
125                 u->stereo = GLFW_TRUE;
126             if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
127                 u->doublebuffer = GLFW_TRUE;
128 
129             if (_glfw.wgl.ARB_multisample)
130                 u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
131 
132             if (_glfw.wgl.ARB_framebuffer_sRGB ||
133                 _glfw.wgl.EXT_framebuffer_sRGB)
134             {
135                 if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
136                     u->sRGB = GLFW_TRUE;
137             }
138         }
139         else
140         {
141             PIXELFORMATDESCRIPTOR pfd;
142 
143             // Get pixel format attributes through legacy PFDs
144 
145             if (!DescribePixelFormat(window->context.wgl.dc,
146                                      n,
147                                      sizeof(PIXELFORMATDESCRIPTOR),
148                                      &pfd))
149             {
150                 continue;
151             }
152 
153             if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
154                 !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
155             {
156                 continue;
157             }
158 
159             if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
160                 (pfd.dwFlags & PFD_GENERIC_FORMAT))
161             {
162                 continue;
163             }
164 
165             if (pfd.iPixelType != PFD_TYPE_RGBA)
166                 continue;
167 
168             u->redBits = pfd.cRedBits;
169             u->greenBits = pfd.cGreenBits;
170             u->blueBits = pfd.cBlueBits;
171             u->alphaBits = pfd.cAlphaBits;
172 
173             u->depthBits = pfd.cDepthBits;
174             u->stencilBits = pfd.cStencilBits;
175 
176             u->accumRedBits = pfd.cAccumRedBits;
177             u->accumGreenBits = pfd.cAccumGreenBits;
178             u->accumBlueBits = pfd.cAccumBlueBits;
179             u->accumAlphaBits = pfd.cAccumAlphaBits;
180 
181             u->auxBuffers = pfd.cAuxBuffers;
182 
183             if (pfd.dwFlags & PFD_STEREO)
184                 u->stereo = GLFW_TRUE;
185             if (pfd.dwFlags & PFD_DOUBLEBUFFER)
186                 u->doublebuffer = GLFW_TRUE;
187         }
188 
189         u->handle = n;
190         usableCount++;
191     }
192 
193     if (!usableCount)
194     {
195         _glfwInputError(GLFW_API_UNAVAILABLE,
196                         "WGL: The driver does not appear to support OpenGL");
197         fprintf(stderr, "[Engine Log] WGL: The driver does not appear to support OpenGL\n");
198 
199         free(usableConfigs);
200         return 0;
201     }
202 
203     closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
204     if (!closest)
205     {
206         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
207                         "WGL: Failed to find a suitable pixel format");
208 
209         free(usableConfigs);
210         return 0;
211     }
212 
213     pixelFormat = (int) closest->handle;
214     free(usableConfigs);
215 
216     return pixelFormat;
217 }
218 
219 // Returns whether desktop compositing is enabled
220 //
isCompositionEnabled(void)221 static GLFWbool isCompositionEnabled(void)
222 {
223     BOOL enabled;
224 
225     if (!_glfw_DwmIsCompositionEnabled)
226         return FALSE;
227 
228     if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
229         return FALSE;
230 
231     return enabled;
232 }
233 
makeContextCurrentWGL(_GLFWwindow * window)234 static void makeContextCurrentWGL(_GLFWwindow* window)
235 {
236     if (window)
237     {
238         if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
239             _glfwPlatformSetCurrentContext(window);
240         else
241         {
242             _glfwInputError(GLFW_PLATFORM_ERROR,
243                             "WGL: Failed to make context current");
244             _glfwPlatformSetCurrentContext(NULL);
245         }
246     }
247     else
248     {
249         if (!wglMakeCurrent(NULL, NULL))
250         {
251             _glfwInputError(GLFW_PLATFORM_ERROR,
252                             "WGL: Failed to clear current context");
253         }
254 
255         _glfwPlatformSetCurrentContext(NULL);
256     }
257 }
258 
swapBuffersWGL(_GLFWwindow * window)259 static void swapBuffersWGL(_GLFWwindow* window)
260 {
261     // HACK: Use DwmFlush when desktop composition is enabled
262     if (isCompositionEnabled() && !window->monitor)
263     {
264         int count = abs(window->context.wgl.interval);
265         while (count--)
266             _glfw_DwmFlush();
267     }
268 
269     SwapBuffers(window->context.wgl.dc);
270 }
271 
swapIntervalWGL(int interval)272 static void swapIntervalWGL(int interval)
273 {
274     _GLFWwindow* window = _glfwPlatformGetCurrentContext();
275 
276     window->context.wgl.interval = interval;
277 
278     // HACK: Disable WGL swap interval when desktop composition is enabled to
279     //       avoid interfering with DWM vsync
280     if (isCompositionEnabled() && !window->monitor)
281         interval = 0;
282 
283     if (_glfw.wgl.EXT_swap_control)
284         _glfw.wgl.SwapIntervalEXT(interval);
285 }
286 
extensionSupportedWGL(const char * extension)287 static int extensionSupportedWGL(const char* extension)
288 {
289     const char* extensions;
290 
291     if (_glfw.wgl.GetExtensionsStringEXT)
292     {
293         extensions = _glfw.wgl.GetExtensionsStringEXT();
294         if (extensions)
295         {
296             if (_glfwStringInExtensionString(extension, extensions))
297                 return GLFW_TRUE;
298         }
299     }
300 
301     if (_glfw.wgl.GetExtensionsStringARB)
302     {
303         extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
304         if (extensions)
305         {
306             if (_glfwStringInExtensionString(extension, extensions))
307                 return GLFW_TRUE;
308         }
309     }
310 
311     return GLFW_FALSE;
312 }
313 
getProcAddressWGL(const char * procname)314 static GLFWglproc getProcAddressWGL(const char* procname)
315 {
316     const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
317     if (proc)
318         return proc;
319 
320     return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
321 }
322 
323 // Destroy the OpenGL context
324 //
destroyContextWGL(_GLFWwindow * window)325 static void destroyContextWGL(_GLFWwindow* window)
326 {
327     if (window->context.wgl.handle)
328     {
329         wglDeleteContext(window->context.wgl.handle);
330         window->context.wgl.handle = NULL;
331     }
332 }
333 
334 // Initialize WGL-specific extensions
335 //
loadWGLExtensions(void)336 static void loadWGLExtensions(void)
337 {
338     PIXELFORMATDESCRIPTOR pfd;
339     HGLRC rc;
340     HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
341 
342     _glfw.wgl.extensionsLoaded = GLFW_TRUE;
343 
344     // NOTE: A dummy context has to be created for opengl32.dll to load the
345     //       OpenGL ICD, from which we can then query WGL extensions
346     // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
347     //       creation failure occurs during manual pixel format enumeration
348 
349     ZeroMemory(&pfd, sizeof(pfd));
350     pfd.nSize = sizeof(pfd);
351     pfd.nVersion = 1;
352     pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
353     pfd.iPixelType = PFD_TYPE_RGBA;
354     pfd.cColorBits = 24;
355 
356     if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
357     {
358         _glfwInputError(GLFW_PLATFORM_ERROR,
359                         "WGL: Failed to set pixel format for dummy context");
360         return;
361     }
362 
363     rc = wglCreateContext(dc);
364     if (!rc)
365     {
366         _glfwInputError(GLFW_PLATFORM_ERROR,
367                         "WGL: Failed to create dummy context");
368         return;
369     }
370 
371     if (!wglMakeCurrent(dc, rc))
372     {
373         wglDeleteContext(rc);
374 
375         _glfwInputError(GLFW_PLATFORM_ERROR,
376                         "WGL: Failed to make dummy context current");
377         return;
378     }
379 
380     // NOTE: Functions must be loaded first as they're needed to retrieve the
381     //       extension string that tells us whether the functions are supported
382     _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
383         wglGetProcAddress("wglGetExtensionsStringEXT");
384     _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
385         wglGetProcAddress("wglGetExtensionsStringARB");
386     _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
387         wglGetProcAddress("wglCreateContextAttribsARB");
388     _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
389         wglGetProcAddress("wglSwapIntervalEXT");
390     _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
391         wglGetProcAddress("wglGetPixelFormatAttribivARB");
392 
393     // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
394     //       checked below as we are already using them
395     _glfw.wgl.ARB_multisample =
396         extensionSupportedWGL("WGL_ARB_multisample");
397     _glfw.wgl.ARB_framebuffer_sRGB =
398         extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
399     _glfw.wgl.EXT_framebuffer_sRGB =
400         extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
401     _glfw.wgl.ARB_create_context =
402         extensionSupportedWGL("WGL_ARB_create_context");
403     _glfw.wgl.ARB_create_context_profile =
404         extensionSupportedWGL("WGL_ARB_create_context_profile");
405     _glfw.wgl.EXT_create_context_es2_profile =
406         extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
407     _glfw.wgl.ARB_create_context_robustness =
408         extensionSupportedWGL("WGL_ARB_create_context_robustness");
409     _glfw.wgl.EXT_swap_control =
410         extensionSupportedWGL("WGL_EXT_swap_control");
411     _glfw.wgl.ARB_pixel_format =
412         extensionSupportedWGL("WGL_ARB_pixel_format");
413     _glfw.wgl.ARB_context_flush_control =
414         extensionSupportedWGL("WGL_ARB_context_flush_control");
415 
416     wglMakeCurrent(dc, NULL);
417     wglDeleteContext(rc);
418 }
419 
420 
421 //////////////////////////////////////////////////////////////////////////
422 //////                       GLFW internal API                      //////
423 //////////////////////////////////////////////////////////////////////////
424 
425 // Initialize WGL
426 //
_glfwInitWGL(void)427 GLFWbool _glfwInitWGL(void)
428 {
429     if (_glfw.wgl.instance)
430         return GLFW_TRUE;
431 
432     _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
433     if (!_glfw.wgl.instance)
434     {
435         _glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
436         return GLFW_FALSE;
437     }
438 
439     _glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
440         GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
441     _glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
442         GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
443     _glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
444         GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
445     _glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T)
446         GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
447     _glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
448         GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
449     _glfw.wgl.ShareLists = (WGLSHARELISTS_T)
450         GetProcAddress(_glfw.wgl.instance, "wglShareLists");
451 
452     return GLFW_TRUE;
453 }
454 
455 // Terminate WGL
456 //
_glfwTerminateWGL(void)457 void _glfwTerminateWGL(void)
458 {
459     if (_glfw.wgl.instance)
460         FreeLibrary(_glfw.wgl.instance);
461 }
462 
463 #define setWGLattrib(attribName, attribValue) \
464 { \
465     attribs[index++] = attribName; \
466     attribs[index++] = attribValue; \
467     assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
468 }
469 
470 // Create the OpenGL or OpenGL ES context
471 //
_glfwCreateContextWGL(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)472 GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
473                                const _GLFWctxconfig* ctxconfig,
474                                const _GLFWfbconfig* fbconfig)
475 {
476     int attribs[40];
477     int pixelFormat;
478     PIXELFORMATDESCRIPTOR pfd;
479     HGLRC share = NULL;
480 
481     if (!_glfw.wgl.extensionsLoaded)
482         loadWGLExtensions();
483 
484     if (ctxconfig->share)
485         share = ctxconfig->share->context.wgl.handle;
486 
487     window->context.wgl.dc = GetDC(window->win32.handle);
488     if (!window->context.wgl.dc)
489     {
490         _glfwInputError(GLFW_PLATFORM_ERROR,
491                         "WGL: Failed to retrieve DC for window");
492         return GLFW_FALSE;
493     }
494 
495     pixelFormat = choosePixelFormat(window, fbconfig);
496     if (!pixelFormat)
497         return GLFW_FALSE;
498 
499     if (!DescribePixelFormat(window->context.wgl.dc,
500                              pixelFormat, sizeof(pfd), &pfd))
501     {
502         _glfwInputError(GLFW_PLATFORM_ERROR,
503                         "WGL: Failed to retrieve PFD for selected pixel format");
504         return GLFW_FALSE;
505     }
506 
507     if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
508     {
509         _glfwInputError(GLFW_PLATFORM_ERROR,
510                         "WGL: Failed to set selected pixel format");
511         return GLFW_FALSE;
512     }
513 
514     if (ctxconfig->client == GLFW_OPENGL_API)
515     {
516         if (ctxconfig->forward)
517         {
518             if (!_glfw.wgl.ARB_create_context)
519             {
520                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
521                                 "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
522                 return GLFW_FALSE;
523             }
524         }
525 
526         if (ctxconfig->profile)
527         {
528             if (!_glfw.wgl.ARB_create_context_profile)
529             {
530                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
531                                 "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
532                 return GLFW_FALSE;
533             }
534         }
535     }
536     else
537     {
538         if (!_glfw.wgl.ARB_create_context ||
539             !_glfw.wgl.ARB_create_context_profile ||
540             !_glfw.wgl.EXT_create_context_es2_profile)
541         {
542             _glfwInputError(GLFW_API_UNAVAILABLE,
543                             "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
544             return GLFW_FALSE;
545         }
546     }
547 
548     if (_glfw.wgl.ARB_create_context)
549     {
550         int index = 0, mask = 0, flags = 0;
551 
552         if (ctxconfig->client == GLFW_OPENGL_API)
553         {
554             if (ctxconfig->forward)
555                 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
556 
557             if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
558                 mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
559             else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
560                 mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
561         }
562         else
563             mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
564 
565         if (ctxconfig->debug)
566             flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
567         if (ctxconfig->noerror)
568             flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
569 
570         if (ctxconfig->robustness)
571         {
572             if (_glfw.wgl.ARB_create_context_robustness)
573             {
574                 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
575                 {
576                     setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
577                                  WGL_NO_RESET_NOTIFICATION_ARB);
578                 }
579                 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
580                 {
581                     setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
582                                  WGL_LOSE_CONTEXT_ON_RESET_ARB);
583                 }
584 
585                 flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
586             }
587         }
588 
589         if (ctxconfig->release)
590         {
591             if (_glfw.wgl.ARB_context_flush_control)
592             {
593                 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
594                 {
595                     setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
596                                  WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
597                 }
598                 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
599                 {
600                     setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
601                                  WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
602                 }
603             }
604         }
605 
606         // NOTE: Only request an explicitly versioned context when necessary, as
607         //       explicitly requesting version 1.0 does not always return the
608         //       highest version supported by the driver
609         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
610         {
611             setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
612             setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
613         }
614 
615         if (flags)
616             setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
617 
618         if (mask)
619             setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
620 
621         setWGLattrib(0, 0);
622 
623         window->context.wgl.handle =
624             _glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
625                                               share, attribs);
626         if (!window->context.wgl.handle)
627         {
628             const DWORD error = GetLastError();
629 
630             if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
631             {
632                 if (ctxconfig->client == GLFW_OPENGL_API)
633                 {
634                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
635                                     "WGL: Driver does not support OpenGL version %i.%i",
636                                     ctxconfig->major,
637                                     ctxconfig->minor);
638                     fprintf(stderr, "[Engine Log] WGL: Driver does not support OpenGL version %i.%i\n",
639                             ctxconfig->major,
640                             ctxconfig->minor);
641                 }
642                 else
643                 {
644                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
645                                     "WGL: Driver does not support OpenGL ES version %i.%i",
646                                     ctxconfig->major,
647                                     ctxconfig->minor);
648                 }
649             }
650             else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
651             {
652                 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
653                                 "WGL: Driver does not support the requested OpenGL profile");
654             }
655             else
656             {
657                 if (ctxconfig->client == GLFW_OPENGL_API)
658                 {
659                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
660                                     "WGL: Failed to create OpenGL context");
661                 }
662                 else
663                 {
664                     _glfwInputError(GLFW_VERSION_UNAVAILABLE,
665                                     "WGL: Failed to create OpenGL ES context");
666                 }
667             }
668 
669             return GLFW_FALSE;
670         }
671     }
672     else
673     {
674         window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
675         if (!window->context.wgl.handle)
676         {
677             _glfwInputError(GLFW_VERSION_UNAVAILABLE,
678                             "WGL: Failed to create OpenGL context");
679             return GLFW_FALSE;
680         }
681 
682         if (share)
683         {
684             if (!wglShareLists(share, window->context.wgl.handle))
685             {
686                 _glfwInputError(GLFW_PLATFORM_ERROR,
687                                 "WGL: Failed to enable sharing with specified OpenGL context");
688                 return GLFW_FALSE;
689             }
690         }
691     }
692 
693     window->context.makeCurrent = makeContextCurrentWGL;
694     window->context.swapBuffers = swapBuffersWGL;
695     window->context.swapInterval = swapIntervalWGL;
696     window->context.extensionSupported = extensionSupportedWGL;
697     window->context.getProcAddress = getProcAddressWGL;
698     window->context.destroy = destroyContextWGL;
699 
700     return GLFW_TRUE;
701 }
702 
703 #undef setWGLattrib
704 
705 
706 //////////////////////////////////////////////////////////////////////////
707 //////                        GLFW native API                       //////
708 //////////////////////////////////////////////////////////////////////////
709 
glfwGetWGLContext(GLFWwindow * handle)710 GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
711 {
712     _GLFWwindow* window = (_GLFWwindow*) handle;
713     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
714 
715     if (window->context.client == GLFW_NO_API)
716     {
717         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
718         return NULL;
719     }
720 
721     return window->context.wgl.handle;
722 }
723 
724