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