1 /// Translated from C to D 2 module glfw3.glx_context; 3 4 extern(C): @nogc: nothrow: __gshared: 5 //======================================================================== 6 // GLFW 3.3 GLX - 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 // It is fine to use C99 in this file because it will not be built with VS 32 //======================================================================== 33 34 // HEADER 35 36 enum GLX_VENDOR = 1; 37 enum GLX_RGBA_BIT = 0x00000001; 38 enum GLX_WINDOW_BIT = 0x00000001; 39 enum GLX_DRAWABLE_TYPE = 0x8010; 40 enum GLX_RENDER_TYPE = 0x8011; 41 enum GLX_RGBA_TYPE = 0x8014; 42 enum GLX_DOUBLEBUFFER = 5; 43 enum GLX_STEREO = 6; 44 enum GLX_AUX_BUFFERS = 7; 45 enum GLX_RED_SIZE = 8; 46 enum GLX_GREEN_SIZE = 9; 47 enum GLX_BLUE_SIZE = 10; 48 enum GLX_ALPHA_SIZE = 11; 49 enum GLX_DEPTH_SIZE = 12; 50 enum GLX_STENCIL_SIZE = 13; 51 enum GLX_ACCUM_RED_SIZE = 14; 52 enum GLX_ACCUM_GREEN_SIZE = 15; 53 enum GLX_ACCUM_BLUE_SIZE = 16; 54 enum GLX_ACCUM_ALPHA_SIZE = 17; 55 enum GLX_SAMPLES = 0x186a1; 56 enum GLX_VISUAL_ID = 0x800b; 57 58 enum GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB = 0x20b2; 59 enum GLX_CONTEXT_DEBUG_BIT_ARB = 0x00000001; 60 enum GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002; 61 enum GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001; 62 enum GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126; 63 enum GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x00000002; 64 enum GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091; 65 enum GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092; 66 enum GLX_CONTEXT_FLAGS_ARB = 0x2094; 67 enum GLX_CONTEXT_ES2_PROFILE_BIT_EXT = 0x00000004; 68 enum GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB = 0x00000004; 69 enum GLX_LOSE_CONTEXT_ON_RESET_ARB = 0x8252; 70 enum GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB = 0x8256; 71 enum GLX_NO_RESET_NOTIFICATION_ARB = 0x8261; 72 enum GLX_CONTEXT_RELEASE_BEHAVIOR_ARB = 0x2097; 73 enum GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB = 0; 74 enum GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB = 0x2098; 75 enum GLX_CONTEXT_OPENGL_NO_ERROR_ARB = 0x31b3; 76 77 alias XID GLXWindow; 78 alias XID GLXDrawable; 79 struct __GLXFBConfig ;alias const(__GLXFBConfig)* GLXFBConfig; 80 struct __GLXcontext ; alias const(__GLXcontext)* GLXContext; 81 alias void function() __GLXextproc; 82 83 alias int function(Display*, GLXFBConfig, int, int*) PFNGLXGETFBCONFIGATTRIBPROC; 84 alias const(char)* function(Display*, int) PFNGLXGETCLIENTSTRINGPROC; 85 alias Bool function(Display*, int*, int*) PFNGLXQUERYEXTENSIONPROC; 86 alias Bool function(Display*, int*, int*) PFNGLXQUERYVERSIONPROC; 87 alias void function(Display*, GLXContext) PFNGLXDESTROYCONTEXTPROC; 88 alias Bool function(Display*, GLXDrawable, GLXContext) PFNGLXMAKECURRENTPROC; 89 alias void function(Display*, GLXDrawable) PFNGLXSWAPBUFFERSPROC; 90 alias const(char)* function(Display*, int) PFNGLXQUERYEXTENSIONSSTRINGPROC; 91 alias GLXFBConfig* function(Display*, int, int*) PFNGLXGETFBCONFIGSPROC; 92 alias GLXContext function(Display*, GLXFBConfig, int, GLXContext, Bool) PFNGLXCREATENEWCONTEXTPROC; 93 alias __GLXextproc function(const(GLubyte)* procName) PFNGLXGETPROCADDRESSPROC; 94 alias void function(Display*, GLXDrawable, int) PFNGLXSWAPINTERVALEXTPROC; 95 alias XVisualInfo* function(Display*, GLXFBConfig) PFNGLXGETVISUALFROMFBCONFIGPROC; 96 alias GLXWindow function(Display*, GLXFBConfig, Window, const(int)*) PFNGLXCREATEWINDOWPROC; 97 alias void function(Display*, GLXWindow) PFNGLXDESTROYWINDOWPROC; 98 99 alias int function(int) PFNGLXSWAPINTERVALMESAPROC; 100 alias int function(int) PFNGLXSWAPINTERVALSGIPROC; 101 alias GLXContext function(Display*, GLXFBConfig, GLXContext, Bool, const(int)*) PFNGLXCREATECONTEXTATTRIBSARBPROC; 102 103 // libGL.so function pointer typedefs 104 alias glXGetFBConfigs = _glfw.glx.GetFBConfigs; 105 alias glXGetFBConfigAttrib = _glfw.glx.GetFBConfigAttrib; 106 alias glXGetClientString = _glfw.glx.GetClientString; 107 alias glXQueryExtension = _glfw.glx.QueryExtension; 108 alias glXQueryVersion = _glfw.glx.QueryVersion; 109 alias glXDestroyContext = _glfw.glx.DestroyContext; 110 alias glXMakeCurrent = _glfw.glx.MakeCurrent; 111 alias glXSwapBuffers = _glfw.glx.SwapBuffers; 112 alias glXQueryExtensionsString = _glfw.glx.QueryExtensionsString; 113 alias glXCreateNewContext = _glfw.glx.CreateNewContext; 114 alias glXGetVisualFromFBConfig = _glfw.glx.GetVisualFromFBConfig; 115 alias glXCreateWindow = _glfw.glx.CreateWindow; 116 alias glXDestroyWindow = _glfw.glx.DestroyWindow; 117 118 mixin template _GLFW_PLATFORM_CONTEXT_STATE() { _GLFWcontextGLX glx;} 119 mixin template _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE() {_GLFWlibraryGLX glx;} 120 121 // GLX-specific per-context data 122 // 123 struct _GLFWcontextGLX { 124 GLXContext handle; 125 GLXWindow window; 126 127 }/+alias _GLFWcontextGLX _GLFWcontextGLX;+/ 128 129 // GLX-specific global data 130 // 131 struct _GLFWlibraryGLX { 132 int major;int minor; 133 int eventBase; 134 int errorBase; 135 136 // dlopen handle for libGL.so.1 137 void* handle; 138 139 // GLX 1.3 functions 140 PFNGLXGETFBCONFIGSPROC GetFBConfigs; 141 PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib; 142 PFNGLXGETCLIENTSTRINGPROC GetClientString; 143 PFNGLXQUERYEXTENSIONPROC QueryExtension; 144 PFNGLXQUERYVERSIONPROC QueryVersion; 145 PFNGLXDESTROYCONTEXTPROC DestroyContext; 146 PFNGLXMAKECURRENTPROC MakeCurrent; 147 PFNGLXSWAPBUFFERSPROC SwapBuffers; 148 PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString; 149 PFNGLXCREATENEWCONTEXTPROC CreateNewContext; 150 PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig; 151 PFNGLXCREATEWINDOWPROC CreateWindow; 152 PFNGLXDESTROYWINDOWPROC DestroyWindow; 153 154 // GLX 1.4 and extension functions 155 PFNGLXGETPROCADDRESSPROC GetProcAddress; 156 PFNGLXGETPROCADDRESSPROC GetProcAddressARB; 157 PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; 158 PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; 159 PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; 160 PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; 161 GLFWbool SGI_swap_control; 162 GLFWbool EXT_swap_control; 163 GLFWbool MESA_swap_control; 164 GLFWbool ARB_multisample; 165 GLFWbool ARB_framebuffer_sRGB; 166 GLFWbool EXT_framebuffer_sRGB; 167 GLFWbool ARB_create_context; 168 GLFWbool ARB_create_context_profile; 169 GLFWbool ARB_create_context_robustness; 170 GLFWbool EXT_create_context_es2_profile; 171 GLFWbool ARB_create_context_no_error; 172 GLFWbool ARB_context_flush_control; 173 174 }/+alias _GLFWlibraryGLX _GLFWlibraryGLX;+/ 175 176 GLFWbool _glfwInitGLX(); 177 void _glfwTerminateGLX(); 178 GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig); 179 void _glfwDestroyContextGLX(_GLFWwindow* window); 180 GLFWbool _glfwChooseVisualGLX(const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth); 181 182 ///////////////////////////////// 183 184 import glfw3.internal; 185 186 import core.stdc.string; 187 import core.stdc.stdlib; 188 import core.stdc.assert_; 189 import core.stdc.stdint; 190 191 enum GLXBadProfileARB = 13; 192 193 // Returns the specified attribute of the specified GLXFBConfig 194 // 195 static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib) { 196 int value; 197 _glfw.glx.GetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); 198 return value; 199 } 200 201 // Return the GLXFBConfig most closely matching the specified hints 202 // 203 static GLFWbool chooseGLXFBConfig(const(_GLFWfbconfig)* desired, GLXFBConfig* result) { 204 GLXFBConfig* nativeConfigs; 205 _GLFWfbconfig* usableConfigs; 206 const(_GLFWfbconfig)* closest; 207 int i;int nativeCount;int usableCount; 208 const(char)* vendor; 209 GLFWbool trustWindowBit = GLFW_TRUE; 210 211 // HACK: This is a (hopefully temporary) workaround for Chromium 212 // (VirtualBox GL) not setting the window bit on any GLXFBConfigs 213 vendor = _glfw.glx.GetClientString(_glfw.x11.display, GLX_VENDOR); 214 if (vendor && strcmp(vendor, "Chromium") == 0) 215 trustWindowBit = GLFW_FALSE; 216 217 nativeConfigs = 218 _glfw.glx.GetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount); 219 if (!nativeConfigs || !nativeCount) 220 { 221 _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); 222 return GLFW_FALSE; 223 } 224 225 usableConfigs = cast(typeof(usableConfigs)) calloc(nativeCount, _GLFWfbconfig.sizeof); 226 usableCount = 0; 227 228 for (i = 0; i < nativeCount; i++) 229 { 230 GLXFBConfig n = nativeConfigs[i]; 231 _GLFWfbconfig* u = usableConfigs + usableCount; 232 233 // Only consider RGBA GLXFBConfigs 234 if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) 235 continue; 236 237 // Only consider window GLXFBConfigs 238 if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) 239 { 240 if (trustWindowBit) 241 continue; 242 } 243 244 if (desired.transparent) 245 { 246 XVisualInfo* vi = _glfw.glx.GetVisualFromFBConfig(_glfw.x11.display, n); 247 if (vi) 248 { 249 u.transparent = _glfwIsVisualTransparentX11(vi.visual); 250 XFree(vi); 251 } 252 } 253 254 u.redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE); 255 u.greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE); 256 u.blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE); 257 258 u.alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE); 259 u.depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE); 260 u.stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE); 261 262 u.accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE); 263 u.accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE); 264 u.accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE); 265 u.accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE); 266 267 u.auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS); 268 269 if (getGLXFBConfigAttrib(n, GLX_STEREO)) 270 u.stereo = GLFW_TRUE; 271 if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER)) 272 u.doublebuffer = GLFW_TRUE; 273 274 if (_glfw.glx.ARB_multisample) 275 u.samples = getGLXFBConfigAttrib(n, GLX_SAMPLES); 276 277 if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB) 278 u.sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); 279 280 u.handle = cast(uintptr_t) n; 281 usableCount++; 282 } 283 284 closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); 285 if (closest) 286 *result = cast(GLXFBConfig) closest.handle; 287 288 XFree(nativeConfigs); 289 free(usableConfigs); 290 291 return closest != null; 292 } 293 294 // Create the OpenGL context using legacy API 295 // 296 static GLXContext createLegacyContextGLX(_GLFWwindow* window, GLXFBConfig fbconfig, GLXContext share) { 297 return _glfw.glx.CreateNewContext(_glfw.x11.display, 298 fbconfig, 299 GLX_RGBA_TYPE, 300 share, 301 True); 302 } 303 304 static void makeContextCurrentGLX(_GLFWwindow* window) { 305 if (window) 306 { 307 if (!_glfw.glx.MakeCurrent(_glfw.x11.display, 308 window.context.glx.window, 309 window.context.glx.handle)) 310 { 311 _glfwInputError(GLFW_PLATFORM_ERROR, 312 "GLX: Failed to make context current"); 313 return; 314 } 315 } 316 else 317 { 318 if (!_glfw.glx.MakeCurrent(_glfw.x11.display, None, null)) 319 { 320 _glfwInputError(GLFW_PLATFORM_ERROR, 321 "GLX: Failed to clear current context"); 322 return; 323 } 324 } 325 326 _glfwPlatformSetTls(&_glfw.contextSlot, window); 327 } 328 329 static void swapBuffersGLX(_GLFWwindow* window) { 330 _glfw.glx.SwapBuffers(_glfw.x11.display, window.context.glx.window); 331 } 332 333 static void swapIntervalGLX(int interval) { 334 auto window = cast(_GLFWwindow*) _glfwPlatformGetTls(&_glfw.contextSlot); 335 336 if (_glfw.glx.EXT_swap_control) 337 { 338 _glfw.glx.SwapIntervalEXT(_glfw.x11.display, 339 window.context.glx.window, 340 interval); 341 } 342 else if (_glfw.glx.MESA_swap_control) 343 _glfw.glx.SwapIntervalMESA(interval); 344 else if (_glfw.glx.SGI_swap_control) 345 { 346 if (interval > 0) 347 _glfw.glx.SwapIntervalSGI(interval); 348 } 349 } 350 351 static int extensionSupportedGLX(const(char)* extension) { 352 const(char)* extensions = _glfw.glx.QueryExtensionsString(_glfw.x11.display, _glfw.x11.screen); 353 if (extensions) 354 { 355 if (_glfwStringInExtensionString(extension, extensions)) 356 return GLFW_TRUE; 357 } 358 359 return GLFW_FALSE; 360 } 361 362 static GLFWglproc getProcAddressGLX(const(char)* procname) { 363 if (_glfw.glx.GetProcAddress) 364 return cast(typeof(return)) _glfw.glx.GetProcAddress(cast(const(GLubyte)*) procname); 365 else if (_glfw.glx.GetProcAddressARB) 366 return cast(typeof(return)) _glfw.glx.GetProcAddressARB(cast(const(GLubyte)*) procname); 367 else 368 return cast(typeof(return)) _glfw_dlsym(_glfw.glx.handle, procname); 369 } 370 371 static void destroyContextGLX(_GLFWwindow* window) { 372 if (window.context.glx.window) 373 { 374 _glfw.glx.DestroyWindow(_glfw.x11.display, window.context.glx.window); 375 window.context.glx.window = None; 376 } 377 378 if (window.context.glx.handle) 379 { 380 _glfw.glx.DestroyContext(_glfw.x11.display, window.context.glx.handle); 381 window.context.glx.handle = null; 382 } 383 } 384 385 386 ////////////////////////////////////////////////////////////////////////// 387 ////// GLFW internal API ////// 388 ////////////////////////////////////////////////////////////////////////// 389 390 // Initialize GLX 391 // 392 GLFWbool _glfwInitGLX() { 393 int i; 394 version(Cygwin) { 395 static immutable const(char)*[] sonames = ["libGL-1.so", "libGL.so.1","libGL.so",null]; 396 } else { 397 static immutable const(char)*[] sonames = ["libGL.so.1","libGL.so",null]; 398 } 399 400 if (_glfw.glx.handle) 401 return GLFW_TRUE; 402 403 for (i = 0; sonames[i]; i++) 404 { 405 _glfw.glx.handle = _glfw_dlopen(sonames[i]); 406 if (_glfw.glx.handle) 407 break; 408 } 409 410 if (!_glfw.glx.handle) 411 { 412 _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX"); 413 return GLFW_FALSE; 414 } 415 416 _glfw.glx.GetFBConfigs = cast(PFNGLXGETFBCONFIGSPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs"); 417 _glfw.glx.GetFBConfigAttrib = cast(PFNGLXGETFBCONFIGATTRIBPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); 418 _glfw.glx.GetClientString = cast(PFNGLXGETCLIENTSTRINGPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetClientString"); 419 _glfw.glx.QueryExtension = cast(PFNGLXQUERYEXTENSIONPROC) _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension"); 420 _glfw.glx.QueryVersion = cast(PFNGLXQUERYVERSIONPROC) _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion"); 421 _glfw.glx.DestroyContext = cast(PFNGLXDESTROYCONTEXTPROC) _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext"); 422 _glfw.glx.MakeCurrent = cast(PFNGLXMAKECURRENTPROC) _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent"); 423 _glfw.glx.SwapBuffers = cast(PFNGLXSWAPBUFFERSPROC) _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers"); 424 _glfw.glx.QueryExtensionsString = cast(PFNGLXQUERYEXTENSIONSSTRINGPROC) _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); 425 _glfw.glx.CreateNewContext = cast(PFNGLXCREATENEWCONTEXTPROC) _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext"); 426 _glfw.glx.CreateWindow = cast(PFNGLXCREATEWINDOWPROC) _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow"); 427 _glfw.glx.DestroyWindow = cast(PFNGLXDESTROYWINDOWPROC) _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow"); 428 429 _glfw.glx.GetProcAddress = cast(PFNGLXGETPROCADDRESSPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress"); 430 _glfw.glx.GetProcAddressARB = cast(PFNGLXGETPROCADDRESSPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); 431 _glfw.glx.GetVisualFromFBConfig = cast(PFNGLXGETVISUALFROMFBCONFIGPROC) _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); 432 433 if (!_glfw.glx.GetFBConfigs || 434 !_glfw.glx.GetFBConfigAttrib || 435 !_glfw.glx.GetClientString || 436 !_glfw.glx.QueryExtension || 437 !_glfw.glx.QueryVersion || 438 !_glfw.glx.DestroyContext || 439 !_glfw.glx.MakeCurrent || 440 !_glfw.glx.SwapBuffers || 441 !_glfw.glx.QueryExtensionsString || 442 !_glfw.glx.CreateNewContext || 443 !_glfw.glx.CreateWindow || 444 !_glfw.glx.DestroyWindow || 445 !_glfw.glx.GetProcAddress || 446 !_glfw.glx.GetProcAddressARB || 447 !_glfw.glx.GetVisualFromFBConfig) 448 { 449 _glfwInputError(GLFW_PLATFORM_ERROR, 450 "GLX: Failed to load required entry points"); 451 return GLFW_FALSE; 452 } 453 454 if (!_glfw.glx.QueryExtension(_glfw.x11.display, 455 &_glfw.glx.errorBase, 456 &_glfw.glx.eventBase)) 457 { 458 _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found"); 459 return GLFW_FALSE; 460 } 461 462 if (!_glfw.glx.QueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor)) 463 { 464 _glfwInputError(GLFW_API_UNAVAILABLE, 465 "GLX: Failed to query GLX version"); 466 return GLFW_FALSE; 467 } 468 469 if (_glfw.glx.major == 1 && _glfw.glx.minor < 3) 470 { 471 _glfwInputError(GLFW_API_UNAVAILABLE, 472 "GLX: GLX version 1.3 is required"); 473 return GLFW_FALSE; 474 } 475 476 if (extensionSupportedGLX("GLX_EXT_swap_control")) 477 { 478 _glfw.glx.SwapIntervalEXT = cast(PFNGLXSWAPINTERVALEXTPROC) 479 getProcAddressGLX("glXSwapIntervalEXT"); 480 481 if (_glfw.glx.SwapIntervalEXT) 482 _glfw.glx.EXT_swap_control = GLFW_TRUE; 483 } 484 485 if (extensionSupportedGLX("GLX_SGI_swap_control")) 486 { 487 _glfw.glx.SwapIntervalSGI = cast(PFNGLXSWAPINTERVALSGIPROC) 488 getProcAddressGLX("glXSwapIntervalSGI"); 489 490 if (_glfw.glx.SwapIntervalSGI) 491 _glfw.glx.SGI_swap_control = GLFW_TRUE; 492 } 493 494 if (extensionSupportedGLX("GLX_MESA_swap_control")) 495 { 496 _glfw.glx.SwapIntervalMESA = cast(PFNGLXSWAPINTERVALMESAPROC) 497 getProcAddressGLX("glXSwapIntervalMESA"); 498 499 if (_glfw.glx.SwapIntervalMESA) 500 _glfw.glx.MESA_swap_control = GLFW_TRUE; 501 } 502 503 if (extensionSupportedGLX("GLX_ARB_multisample")) 504 _glfw.glx.ARB_multisample = GLFW_TRUE; 505 506 if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB")) 507 _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; 508 509 if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB")) 510 _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE; 511 512 if (extensionSupportedGLX("GLX_ARB_create_context")) 513 { 514 _glfw.glx.CreateContextAttribsARB = cast(PFNGLXCREATECONTEXTATTRIBSARBPROC) 515 getProcAddressGLX("glXCreateContextAttribsARB"); 516 517 if (_glfw.glx.CreateContextAttribsARB) 518 _glfw.glx.ARB_create_context = GLFW_TRUE; 519 } 520 521 if (extensionSupportedGLX("GLX_ARB_create_context_robustness")) 522 _glfw.glx.ARB_create_context_robustness = GLFW_TRUE; 523 524 if (extensionSupportedGLX("GLX_ARB_create_context_profile")) 525 _glfw.glx.ARB_create_context_profile = GLFW_TRUE; 526 527 if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile")) 528 _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; 529 530 if (extensionSupportedGLX("GLX_ARB_create_context_no_error")) 531 _glfw.glx.ARB_create_context_no_error = GLFW_TRUE; 532 533 if (extensionSupportedGLX("GLX_ARB_context_flush_control")) 534 _glfw.glx.ARB_context_flush_control = GLFW_TRUE; 535 536 return GLFW_TRUE; 537 } 538 539 // Terminate GLX 540 // 541 void _glfwTerminateGLX() { 542 // NOTE: This function must not call any X11 functions, as it is called 543 // after XCloseDisplay (see _glfwPlatformTerminate for details) 544 545 if (_glfw.glx.handle) 546 { 547 _glfw_dlclose(_glfw.glx.handle); 548 _glfw.glx.handle = null; 549 } 550 } 551 552 553 // Create the OpenGL or OpenGL ES context 554 // 555 GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig) { 556 int[40] attribs; 557 int index; 558 void setAttrib(int a, int v) { 559 assert((cast(size_t) index + 1) < attribs.length); 560 attribs[index++] = a; 561 attribs[index++] = v; 562 } 563 GLXFBConfig native = null; 564 GLXContext share = null; 565 566 if (ctxconfig.share) 567 share = ctxconfig.share.context.glx.handle; 568 569 if (!chooseGLXFBConfig(fbconfig, &native)) 570 { 571 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 572 "GLX: Failed to find a suitable GLXFBConfig"); 573 return GLFW_FALSE; 574 } 575 576 if (ctxconfig.client == GLFW_OPENGL_ES_API) 577 { 578 if (!_glfw.glx.ARB_create_context || 579 !_glfw.glx.ARB_create_context_profile || 580 !_glfw.glx.EXT_create_context_es2_profile) 581 { 582 _glfwInputError(GLFW_API_UNAVAILABLE, 583 "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable"); 584 return GLFW_FALSE; 585 } 586 } 587 588 if (ctxconfig.forward) 589 { 590 if (!_glfw.glx.ARB_create_context) 591 { 592 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 593 "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable"); 594 return GLFW_FALSE; 595 } 596 } 597 598 if (ctxconfig.profile) 599 { 600 if (!_glfw.glx.ARB_create_context || 601 !_glfw.glx.ARB_create_context_profile) 602 { 603 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 604 "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable"); 605 return GLFW_FALSE; 606 } 607 } 608 609 _glfwGrabErrorHandlerX11(); 610 611 if (_glfw.glx.ARB_create_context) 612 { 613 index = 0; 614 int mask = 0;int flags = 0; 615 616 if (ctxconfig.client == GLFW_OPENGL_API) 617 { 618 if (ctxconfig.forward) 619 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 620 621 if (ctxconfig.profile == GLFW_OPENGL_CORE_PROFILE) 622 mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; 623 else if (ctxconfig.profile == GLFW_OPENGL_COMPAT_PROFILE) 624 mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 625 } 626 else 627 mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; 628 629 if (ctxconfig.debug_) 630 flags |= GLX_CONTEXT_DEBUG_BIT_ARB; 631 632 if (ctxconfig.robustness) 633 { 634 if (_glfw.glx.ARB_create_context_robustness) 635 { 636 if (ctxconfig.robustness == GLFW_NO_RESET_NOTIFICATION) 637 { 638 setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, 639 GLX_NO_RESET_NOTIFICATION_ARB); 640 } 641 else if (ctxconfig.robustness == GLFW_LOSE_CONTEXT_ON_RESET) 642 { 643 setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, 644 GLX_LOSE_CONTEXT_ON_RESET_ARB); 645 } 646 647 flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; 648 } 649 } 650 651 if (ctxconfig.release) 652 { 653 if (_glfw.glx.ARB_context_flush_control) 654 { 655 if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_NONE) 656 { 657 setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, 658 GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); 659 } 660 else if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_FLUSH) 661 { 662 setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, 663 GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); 664 } 665 } 666 } 667 668 if (ctxconfig.noerror) 669 { 670 if (_glfw.glx.ARB_create_context_no_error) 671 setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); 672 } 673 674 // NOTE: Only request an explicitly versioned context when necessary, as 675 // explicitly requesting version 1.0 does not always return the 676 // highest version supported by the driver 677 if (ctxconfig.major != 1 || ctxconfig.minor != 0) 678 { 679 setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig.major); 680 setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig.minor); 681 } 682 683 if (mask) 684 setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); 685 686 if (flags) 687 setAttrib(GLX_CONTEXT_FLAGS_ARB, flags); 688 689 setAttrib(None, None); 690 691 window.context.glx.handle = 692 _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, 693 native, 694 share, 695 True, 696 attribs.ptr); 697 698 // HACK: This is a fallback for broken versions of the Mesa 699 // implementation of GLX_ARB_create_context_profile that fail 700 // default 1.0 context creation with a GLXBadProfileARB error in 701 // violation of the extension spec 702 if (!window.context.glx.handle) 703 { 704 if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && 705 ctxconfig.client == GLFW_OPENGL_API && 706 ctxconfig.profile == GLFW_OPENGL_ANY_PROFILE && 707 ctxconfig.forward == GLFW_FALSE) 708 { 709 window.context.glx.handle = 710 createLegacyContextGLX(window, native, share); 711 } 712 } 713 } 714 else 715 { 716 window.context.glx.handle = 717 createLegacyContextGLX(window, native, share); 718 } 719 720 _glfwReleaseErrorHandlerX11(); 721 722 if (!window.context.glx.handle) 723 { 724 _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context"); 725 return GLFW_FALSE; 726 } 727 728 window.context.glx.window = 729 _glfw.glx.CreateWindow(_glfw.x11.display, native, window.x11.handle, null); 730 if (!window.context.glx.window) 731 { 732 _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window"); 733 return GLFW_FALSE; 734 } 735 736 window.context.makeCurrent = &makeContextCurrentGLX; 737 window.context.swapBuffers = &swapBuffersGLX; 738 window.context.swapInterval = &swapIntervalGLX; 739 window.context.extensionSupported = &extensionSupportedGLX; 740 window.context.getProcAddress = &getProcAddressGLX; 741 window.context.destroy = &destroyContextGLX; 742 743 return GLFW_TRUE; 744 } 745 746 // Returns the Visual and depth of the chosen GLXFBConfig 747 // 748 GLFWbool _glfwChooseVisualGLX(const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth) { 749 GLXFBConfig native; 750 XVisualInfo* result; 751 752 if (!chooseGLXFBConfig(fbconfig, &native)) 753 { 754 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 755 "GLX: Failed to find a suitable GLXFBConfig"); 756 return GLFW_FALSE; 757 } 758 759 result = _glfw.glx.GetVisualFromFBConfig(_glfw.x11.display, native); 760 if (!result) 761 { 762 _glfwInputError(GLFW_PLATFORM_ERROR, 763 "GLX: Failed to retrieve Visual for GLXFBConfig"); 764 return GLFW_FALSE; 765 } 766 767 *visual = result.visual; 768 *depth = result.depth; 769 770 XFree(result); 771 return GLFW_TRUE; 772 } 773 774 775 ////////////////////////////////////////////////////////////////////////// 776 ////// GLFW native API ////// 777 ////////////////////////////////////////////////////////////////////////// 778 779 GLXContext glfwGetGLXContext(GLFWwindow* handle) { 780 _GLFWwindow* window = cast(_GLFWwindow*) handle; 781 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("null")); 782 783 if (window.context.client == GLFW_NO_API) 784 { 785 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null); 786 return null; 787 } 788 789 return window.context.glx.handle; 790 } 791 792 GLXWindow glfwGetGLXWindow(GLFWwindow* handle) { 793 _GLFWwindow* window = cast(_GLFWwindow*) handle; 794 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("None")); 795 796 if (window.context.client == GLFW_NO_API) 797 { 798 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null); 799 return None; 800 } 801 802 return window.context.glx.window; 803 }