glx_context.c 23 KB

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