wgl_context.cc (24689B)
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 // 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 // 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 PIXELFORMATDESCRIPTOR pfd; 156 157 // Get pixel format attributes through legacy PFDs 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 232 // Returns whether desktop compositing is enabled 233 // 234 static GLFWbool isCompositionEnabled(void) 235 { 236 BOOL enabled; 237 238 if (!_glfw_DwmIsCompositionEnabled) 239 return FALSE; 240 241 if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK) 242 return FALSE; 243 244 return enabled; 245 } 246 247 static void makeContextCurrentWGL(_GLFWwindow* window) 248 { 249 if (window) 250 { 251 if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle)) 252 _glfwPlatformSetTls(&_glfw.contextSlot, window); 253 else 254 { 255 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 256 "WGL: Failed to make context current"); 257 _glfwPlatformSetTls(&_glfw.contextSlot, NULL); 258 } 259 } 260 else 261 { 262 if (!wglMakeCurrent(NULL, NULL)) 263 { 264 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 265 "WGL: Failed to clear current context"); 266 } 267 268 _glfwPlatformSetTls(&_glfw.contextSlot, NULL); 269 } 270 } 271 272 static void swapBuffersWGL(_GLFWwindow* window) 273 { 274 // HACK: Use DwmFlush when desktop composition is enabled 275 if (isCompositionEnabled() && !window->monitor) 276 { 277 int count = abs(window->context.wgl.interval); 278 while (count--) 279 _glfw_DwmFlush(); 280 } 281 282 SwapBuffers(window->context.wgl.dc); 283 } 284 285 static void swapIntervalWGL(int interval) 286 { 287 _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); 288 289 window->context.wgl.interval = interval; 290 291 // HACK: Disable WGL swap interval when desktop composition is enabled to 292 // avoid interfering with DWM vsync 293 if (isCompositionEnabled() && !window->monitor) 294 interval = 0; 295 296 if (_glfw.wgl.EXT_swap_control) 297 _glfw.wgl.SwapIntervalEXT(interval); 298 } 299 300 static int extensionSupportedWGL(const char* extension) 301 { 302 const char* extensions; 303 304 if (_glfw.wgl.GetExtensionsStringEXT) 305 { 306 extensions = _glfw.wgl.GetExtensionsStringEXT(); 307 if (extensions) 308 { 309 if (_glfwStringInExtensionString(extension, extensions)) 310 return GLFW_TRUE; 311 } 312 } 313 314 if (_glfw.wgl.GetExtensionsStringARB) 315 { 316 extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC()); 317 if (extensions) 318 { 319 if (_glfwStringInExtensionString(extension, extensions)) 320 return GLFW_TRUE; 321 } 322 } 323 324 return GLFW_FALSE; 325 } 326 327 static GLFWglproc getProcAddressWGL(const char* procname) 328 { 329 const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname); 330 if (proc) 331 return proc; 332 333 return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname); 334 } 335 336 // Destroy the OpenGL context 337 // 338 static void destroyContextWGL(_GLFWwindow* window) 339 { 340 if (window->context.wgl.handle) 341 { 342 wglDeleteContext(window->context.wgl.handle); 343 window->context.wgl.handle = NULL; 344 } 345 } 346 347 // Initialize WGL-specific extensions 348 // 349 static void loadWGLExtensions(void) 350 { 351 PIXELFORMATDESCRIPTOR pfd; 352 HGLRC rc; 353 HDC dc = GetDC(_glfw.win32.helperWindowHandle);; 354 355 _glfw.wgl.extensionsLoaded = GLFW_TRUE; 356 357 // NOTE: A dummy context has to be created for opengl32.dll to load the 358 // OpenGL ICD, from which we can then query WGL extensions 359 // NOTE: This code will accept the Microsoft GDI ICD; accelerated context 360 // creation failure occurs during manual pixel format enumeration 361 362 ZeroMemory(&pfd, sizeof(pfd)); 363 pfd.nSize = sizeof(pfd); 364 pfd.nVersion = 1; 365 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 366 pfd.iPixelType = PFD_TYPE_RGBA; 367 pfd.cColorBits = 24; 368 369 if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd)) 370 { 371 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 372 "WGL: Failed to set pixel format for dummy context"); 373 return; 374 } 375 376 rc = wglCreateContext(dc); 377 if (!rc) 378 { 379 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 380 "WGL: Failed to create dummy context"); 381 return; 382 } 383 384 if (!wglMakeCurrent(dc, rc)) 385 { 386 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 387 "WGL: Failed to make dummy context current"); 388 wglDeleteContext(rc); 389 return; 390 } 391 392 // NOTE: Functions must be loaded first as they're needed to retrieve the 393 // extension string that tells us whether the functions are supported 394 _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) 395 wglGetProcAddress("wglGetExtensionsStringEXT"); 396 _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) 397 wglGetProcAddress("wglGetExtensionsStringARB"); 398 _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) 399 wglGetProcAddress("wglCreateContextAttribsARB"); 400 _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) 401 wglGetProcAddress("wglSwapIntervalEXT"); 402 _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) 403 wglGetProcAddress("wglGetPixelFormatAttribivARB"); 404 405 // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not 406 // checked below as we are already using them 407 _glfw.wgl.ARB_multisample = 408 extensionSupportedWGL("WGL_ARB_multisample"); 409 _glfw.wgl.ARB_framebuffer_sRGB = 410 extensionSupportedWGL("WGL_ARB_framebuffer_sRGB"); 411 _glfw.wgl.EXT_framebuffer_sRGB = 412 extensionSupportedWGL("WGL_EXT_framebuffer_sRGB"); 413 _glfw.wgl.ARB_create_context = 414 extensionSupportedWGL("WGL_ARB_create_context"); 415 _glfw.wgl.ARB_create_context_profile = 416 extensionSupportedWGL("WGL_ARB_create_context_profile"); 417 _glfw.wgl.EXT_create_context_es2_profile = 418 extensionSupportedWGL("WGL_EXT_create_context_es2_profile"); 419 _glfw.wgl.ARB_create_context_robustness = 420 extensionSupportedWGL("WGL_ARB_create_context_robustness"); 421 _glfw.wgl.ARB_create_context_no_error = 422 extensionSupportedWGL("WGL_ARB_create_context_no_error"); 423 _glfw.wgl.EXT_swap_control = 424 extensionSupportedWGL("WGL_EXT_swap_control"); 425 _glfw.wgl.EXT_colorspace = 426 extensionSupportedWGL("WGL_EXT_colorspace"); 427 _glfw.wgl.ARB_pixel_format = 428 extensionSupportedWGL("WGL_ARB_pixel_format"); 429 _glfw.wgl.ARB_context_flush_control = 430 extensionSupportedWGL("WGL_ARB_context_flush_control"); 431 432 wglMakeCurrent(dc, NULL); 433 wglDeleteContext(rc); 434 } 435 436 437 ////////////////////////////////////////////////////////////////////////// 438 ////// GLFW internal API ////// 439 ////////////////////////////////////////////////////////////////////////// 440 441 // Initialize WGL 442 // 443 GLFWbool _glfwInitWGL(void) 444 { 445 if (_glfw.wgl.instance) 446 return GLFW_TRUE; 447 448 _glfw.wgl.instance = LoadLibraryA("opengl32.dll"); 449 if (!_glfw.wgl.instance) 450 { 451 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 452 "WGL: Failed to load opengl32.dll"); 453 return GLFW_FALSE; 454 } 455 456 _glfw.wgl.CreateContext = (PFN_wglCreateContext) 457 GetProcAddress(_glfw.wgl.instance, "wglCreateContext"); 458 _glfw.wgl.DeleteContext = (PFN_wglDeleteContext) 459 GetProcAddress(_glfw.wgl.instance, "wglDeleteContext"); 460 _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress) 461 GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress"); 462 _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC) 463 GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC"); 464 _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent) 465 GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent"); 466 _glfw.wgl.ShareLists = (PFN_wglShareLists) 467 GetProcAddress(_glfw.wgl.instance, "wglShareLists"); 468 469 return GLFW_TRUE; 470 } 471 472 // Terminate WGL 473 // 474 void _glfwTerminateWGL(void) 475 { 476 if (_glfw.wgl.instance) 477 FreeLibrary(_glfw.wgl.instance); 478 } 479 480 #define setAttrib(a, v) \ 481 { \ 482 assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ 483 attribs[index++] = a; \ 484 attribs[index++] = v; \ 485 } 486 487 // Create the OpenGL or OpenGL ES context 488 // 489 GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, 490 const _GLFWctxconfig* ctxconfig, 491 const _GLFWfbconfig* fbconfig) 492 { 493 int attribs[40]; 494 int pixelFormat; 495 PIXELFORMATDESCRIPTOR pfd; 496 HGLRC share = NULL; 497 498 if (!_glfw.wgl.extensionsLoaded) 499 loadWGLExtensions(); 500 501 if (ctxconfig->share) 502 share = ctxconfig->share->context.wgl.handle; 503 504 window->context.wgl.dc = GetDC(window->win32.handle); 505 if (!window->context.wgl.dc) 506 { 507 _glfwInputError(GLFW_PLATFORM_ERROR, 508 "WGL: Failed to retrieve DC for window"); 509 return GLFW_FALSE; 510 } 511 512 pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig); 513 if (!pixelFormat) 514 return GLFW_FALSE; 515 516 if (!DescribePixelFormat(window->context.wgl.dc, 517 pixelFormat, sizeof(pfd), &pfd)) 518 { 519 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 520 "WGL: Failed to retrieve PFD for selected pixel format"); 521 return GLFW_FALSE; 522 } 523 524 if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd)) 525 { 526 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 527 "WGL: Failed to set selected pixel format"); 528 return GLFW_FALSE; 529 } 530 531 if (ctxconfig->client == GLFW_OPENGL_API) 532 { 533 if (ctxconfig->forward) 534 { 535 if (!_glfw.wgl.ARB_create_context) 536 { 537 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 538 "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable"); 539 return GLFW_FALSE; 540 } 541 } 542 543 if (ctxconfig->profile) 544 { 545 if (!_glfw.wgl.ARB_create_context_profile) 546 { 547 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 548 "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable"); 549 return GLFW_FALSE; 550 } 551 } 552 } 553 else 554 { 555 if (!_glfw.wgl.ARB_create_context || 556 !_glfw.wgl.ARB_create_context_profile || 557 !_glfw.wgl.EXT_create_context_es2_profile) 558 { 559 _glfwInputError(GLFW_API_UNAVAILABLE, 560 "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable"); 561 return GLFW_FALSE; 562 } 563 } 564 565 if (_glfw.wgl.ARB_create_context) 566 { 567 int index = 0, mask = 0, flags = 0; 568 569 if (ctxconfig->client == GLFW_OPENGL_API) 570 { 571 if (ctxconfig->forward) 572 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 573 574 if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) 575 mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; 576 else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) 577 mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 578 } 579 else 580 mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT; 581 582 if (ctxconfig->debug) 583 flags |= WGL_CONTEXT_DEBUG_BIT_ARB; 584 585 if (ctxconfig->robustness) 586 { 587 if (_glfw.wgl.ARB_create_context_robustness) 588 { 589 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) 590 { 591 setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, 592 WGL_NO_RESET_NOTIFICATION_ARB); 593 } 594 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) 595 { 596 setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, 597 WGL_LOSE_CONTEXT_ON_RESET_ARB); 598 } 599 600 flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; 601 } 602 } 603 604 if (ctxconfig->release) 605 { 606 if (_glfw.wgl.ARB_context_flush_control) 607 { 608 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) 609 { 610 setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, 611 WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); 612 } 613 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) 614 { 615 setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, 616 WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); 617 } 618 } 619 } 620 621 if (ctxconfig->noerror) 622 { 623 if (_glfw.wgl.ARB_create_context_no_error) 624 setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); 625 } 626 627 // NOTE: Only request an explicitly versioned context when necessary, as 628 // explicitly requesting version 1.0 does not always return the 629 // highest version supported by the driver 630 if (ctxconfig->major != 1 || ctxconfig->minor != 0) 631 { 632 setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); 633 setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); 634 } 635 636 if (flags) 637 setAttrib(WGL_CONTEXT_FLAGS_ARB, flags); 638 639 if (mask) 640 setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask); 641 642 setAttrib(0, 0); 643 644 window->context.wgl.handle = 645 _glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc, 646 share, attribs); 647 if (!window->context.wgl.handle) 648 { 649 const DWORD error = GetLastError(); 650 651 if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB)) 652 { 653 if (ctxconfig->client == GLFW_OPENGL_API) 654 { 655 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 656 "WGL: Driver does not support OpenGL version %i.%i", 657 ctxconfig->major, 658 ctxconfig->minor); 659 } 660 else 661 { 662 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 663 "WGL: Driver does not support OpenGL ES version %i.%i", 664 ctxconfig->major, 665 ctxconfig->minor); 666 } 667 } 668 else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB)) 669 { 670 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 671 "WGL: Driver does not support the requested OpenGL profile"); 672 } 673 else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB)) 674 { 675 _glfwInputError(GLFW_INVALID_VALUE, 676 "WGL: The share context is not compatible with the requested context"); 677 } 678 else 679 { 680 if (ctxconfig->client == GLFW_OPENGL_API) 681 { 682 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 683 "WGL: Failed to create OpenGL context"); 684 } 685 else 686 { 687 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 688 "WGL: Failed to create OpenGL ES context"); 689 } 690 } 691 692 return GLFW_FALSE; 693 } 694 } 695 else 696 { 697 window->context.wgl.handle = wglCreateContext(window->context.wgl.dc); 698 if (!window->context.wgl.handle) 699 { 700 _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE, 701 "WGL: Failed to create OpenGL context"); 702 return GLFW_FALSE; 703 } 704 705 if (share) 706 { 707 if (!wglShareLists(share, window->context.wgl.handle)) 708 { 709 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 710 "WGL: Failed to enable sharing with specified OpenGL context"); 711 return GLFW_FALSE; 712 } 713 } 714 } 715 716 window->context.makeCurrent = makeContextCurrentWGL; 717 window->context.swapBuffers = swapBuffersWGL; 718 window->context.swapInterval = swapIntervalWGL; 719 window->context.extensionSupported = extensionSupportedWGL; 720 window->context.getProcAddress = getProcAddressWGL; 721 window->context.destroy = destroyContextWGL; 722 723 return GLFW_TRUE; 724 } 725 726 #undef setAttrib 727 728 729 ////////////////////////////////////////////////////////////////////////// 730 ////// GLFW native API ////// 731 ////////////////////////////////////////////////////////////////////////// 732 733 GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) 734 { 735 _GLFWwindow* window = (_GLFWwindow*) handle; 736 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 737 738 if (window->context.client == GLFW_NO_API) 739 { 740 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 741 return NULL; 742 } 743 744 return window->context.wgl.handle; 745 } 746