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