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