glx_context.c 22 KB

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