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