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