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