egl_context.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. //========================================================================
  2. // GLFW 3.4 EGL - 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. // Please use C89 style variable declarations in this file because VS 2010
  28. //========================================================================
  29. #include "internal.h"
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <assert.h>
  34. // Return a description of the specified EGL error
  35. //
  36. static const char* getEGLErrorString(EGLint error)
  37. {
  38. switch (error)
  39. {
  40. case EGL_SUCCESS:
  41. return "Success";
  42. case EGL_NOT_INITIALIZED:
  43. return "EGL is not or could not be initialized";
  44. case EGL_BAD_ACCESS:
  45. return "EGL cannot access a requested resource";
  46. case EGL_BAD_ALLOC:
  47. return "EGL failed to allocate resources for the requested operation";
  48. case EGL_BAD_ATTRIBUTE:
  49. return "An unrecognized attribute or attribute value was passed in the attribute list";
  50. case EGL_BAD_CONTEXT:
  51. return "An EGLContext argument does not name a valid EGL rendering context";
  52. case EGL_BAD_CONFIG:
  53. return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
  54. case EGL_BAD_CURRENT_SURFACE:
  55. return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
  56. case EGL_BAD_DISPLAY:
  57. return "An EGLDisplay argument does not name a valid EGL display connection";
  58. case EGL_BAD_SURFACE:
  59. return "An EGLSurface argument does not name a valid surface configured for GL rendering";
  60. case EGL_BAD_MATCH:
  61. return "Arguments are inconsistent";
  62. case EGL_BAD_PARAMETER:
  63. return "One or more argument values are invalid";
  64. case EGL_BAD_NATIVE_PIXMAP:
  65. return "A NativePixmapType argument does not refer to a valid native pixmap";
  66. case EGL_BAD_NATIVE_WINDOW:
  67. return "A NativeWindowType argument does not refer to a valid native window";
  68. case EGL_CONTEXT_LOST:
  69. return "The application must destroy all contexts and reinitialise";
  70. default:
  71. return "ERROR: UNKNOWN EGL ERROR";
  72. }
  73. }
  74. #ifdef _GLFW_X11
  75. // Returns the specified attribute of the specified EGLConfig
  76. //
  77. static int getEGLConfigAttrib(EGLConfig config, int attrib)
  78. {
  79. int value;
  80. eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
  81. return value;
  82. }
  83. #endif
  84. // Return the EGLConfig most closely matching the specified hints
  85. //
  86. static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
  87. const _GLFWfbconfig* desired,
  88. EGLConfig* result)
  89. {
  90. EGLConfig configs[512];
  91. int i = 0, nativeCount = 0, ans_idx = 0;
  92. EGLint attributes[64];
  93. #define ATTR(k, v) { attributes[i++] = k; attributes[i++] = v; }
  94. ATTR(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
  95. ATTR(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
  96. if (ctxconfig->client == GLFW_OPENGL_ES_API) {
  97. if (ctxconfig->major == 1) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT)
  98. else ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
  99. }
  100. else if (ctxconfig->client == GLFW_OPENGL_API) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
  101. if (desired->samples > 0) ATTR(EGL_SAMPLES, desired->samples);
  102. if (desired->depthBits > 0) ATTR(EGL_DEPTH_SIZE, desired->depthBits);
  103. if (desired->stencilBits > 0) ATTR(EGL_STENCIL_SIZE, desired->stencilBits);
  104. if (desired->redBits > 0) ATTR(EGL_RED_SIZE, desired->redBits);
  105. if (desired->greenBits > 0) ATTR(EGL_GREEN_SIZE, desired->greenBits);
  106. if (desired->blueBits > 0) ATTR(EGL_BLUE_SIZE, desired->blueBits);
  107. if (desired->alphaBits > 0) ATTR(EGL_ALPHA_SIZE, desired->alphaBits);
  108. ATTR(EGL_NONE, EGL_NONE);
  109. #undef ATTR
  110. if (!eglChooseConfig(_glfw.egl.display, attributes, configs, sizeof(configs)/sizeof(configs[0]), &nativeCount)) {
  111. _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: eglChooseConfig failed");
  112. return false;
  113. }
  114. if (!nativeCount)
  115. {
  116. _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
  117. return false;
  118. }
  119. for (i = 0; i < nativeCount; i++)
  120. {
  121. #if defined(_GLFW_X11)
  122. {
  123. const EGLConfig n = configs[i];
  124. XVisualInfo vi = {0};
  125. // Only consider EGLConfigs with associated Visuals
  126. vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
  127. if (!vi.visualid)
  128. continue;
  129. if (desired->transparent)
  130. {
  131. int count;
  132. XVisualInfo* vis =
  133. XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
  134. if (vis)
  135. {
  136. bool transparent = _glfwIsVisualTransparentX11(vis[0].visual);
  137. XFree(vis);
  138. if (!transparent) continue;
  139. }
  140. }
  141. }
  142. #endif // _GLFW_X11
  143. ans_idx = i;
  144. break;
  145. }
  146. *result = configs[ans_idx];
  147. return true;
  148. }
  149. static void makeContextCurrentEGL(_GLFWwindow* window)
  150. {
  151. if (window)
  152. {
  153. if (!eglMakeCurrent(_glfw.egl.display,
  154. window->context.egl.surface,
  155. window->context.egl.surface,
  156. window->context.egl.handle))
  157. {
  158. _glfwInputError(GLFW_PLATFORM_ERROR,
  159. "EGL: Failed to make context current: %s",
  160. getEGLErrorString(eglGetError()));
  161. return;
  162. }
  163. }
  164. else
  165. {
  166. if (!eglMakeCurrent(_glfw.egl.display,
  167. EGL_NO_SURFACE,
  168. EGL_NO_SURFACE,
  169. EGL_NO_CONTEXT))
  170. {
  171. _glfwInputError(GLFW_PLATFORM_ERROR,
  172. "EGL: Failed to clear current context: %s",
  173. getEGLErrorString(eglGetError()));
  174. return;
  175. }
  176. }
  177. _glfwPlatformSetTls(&_glfw.contextSlot, window);
  178. }
  179. static void swapBuffersEGL(_GLFWwindow* window)
  180. {
  181. if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
  182. {
  183. _glfwInputError(GLFW_PLATFORM_ERROR,
  184. "EGL: The context must be current on the calling thread when swapping buffers");
  185. return;
  186. }
  187. eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
  188. }
  189. static void swapIntervalEGL(int interval)
  190. {
  191. eglSwapInterval(_glfw.egl.display, interval);
  192. }
  193. static int extensionSupportedEGL(const char* extension)
  194. {
  195. const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
  196. if (extensions)
  197. {
  198. if (_glfwStringInExtensionString(extension, extensions))
  199. return true;
  200. }
  201. return false;
  202. }
  203. static GLFWglproc getProcAddressEGL(const char* procname)
  204. {
  205. _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
  206. if (window->context.egl.client)
  207. {
  208. GLFWglproc proc = NULL;
  209. glfw_dlsym(proc, window->context.egl.client, procname);
  210. if (proc)
  211. return proc;
  212. }
  213. return eglGetProcAddress(procname);
  214. }
  215. static void destroyContextEGL(_GLFWwindow* window)
  216. {
  217. #if defined(_GLFW_X11)
  218. // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
  219. // as it will make XCloseDisplay segfault
  220. if (window->context.client != GLFW_OPENGL_API)
  221. #endif // _GLFW_X11
  222. {
  223. if (window->context.egl.client)
  224. {
  225. _glfw_dlclose(window->context.egl.client);
  226. window->context.egl.client = NULL;
  227. }
  228. }
  229. if (window->context.egl.surface)
  230. {
  231. eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
  232. window->context.egl.surface = EGL_NO_SURFACE;
  233. }
  234. if (window->context.egl.handle)
  235. {
  236. eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
  237. window->context.egl.handle = EGL_NO_CONTEXT;
  238. }
  239. }
  240. //////////////////////////////////////////////////////////////////////////
  241. ////// GLFW internal API //////
  242. //////////////////////////////////////////////////////////////////////////
  243. // Initialize EGL
  244. //
  245. bool _glfwInitEGL(void)
  246. {
  247. int i;
  248. EGLint* attribs = NULL;
  249. const char* extensions;
  250. const char* sonames[] =
  251. {
  252. #if defined(_GLFW_EGL_LIBRARY)
  253. _GLFW_EGL_LIBRARY,
  254. #elif defined(_GLFW_WIN32)
  255. "libEGL.dll",
  256. "EGL.dll",
  257. #elif defined(_GLFW_COCOA)
  258. "libEGL.dylib",
  259. #elif defined(__CYGWIN__)
  260. "libEGL-1.so",
  261. #else
  262. "libEGL.so.1",
  263. #endif
  264. NULL
  265. };
  266. if (_glfw.egl.handle)
  267. return true;
  268. for (i = 0; sonames[i]; i++)
  269. {
  270. _glfw.egl.handle = _glfw_dlopen(sonames[i]);
  271. if (_glfw.egl.handle)
  272. break;
  273. }
  274. if (!_glfw.egl.handle)
  275. {
  276. _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
  277. return false;
  278. }
  279. _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
  280. glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib");
  281. glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs");
  282. glfw_dlsym(_glfw.egl.ChooseConfig, _glfw.egl.handle, "eglChooseConfig");
  283. glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay");
  284. glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError");
  285. glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize");
  286. glfw_dlsym(_glfw.egl.Terminate, _glfw.egl.handle, "eglTerminate");
  287. glfw_dlsym(_glfw.egl.BindAPI, _glfw.egl.handle, "eglBindAPI");
  288. glfw_dlsym(_glfw.egl.CreateContext, _glfw.egl.handle, "eglCreateContext");
  289. glfw_dlsym(_glfw.egl.DestroySurface, _glfw.egl.handle, "eglDestroySurface");
  290. glfw_dlsym(_glfw.egl.DestroyContext, _glfw.egl.handle, "eglDestroyContext");
  291. glfw_dlsym(_glfw.egl.CreateWindowSurface, _glfw.egl.handle, "eglCreateWindowSurface");
  292. glfw_dlsym(_glfw.egl.MakeCurrent, _glfw.egl.handle, "eglMakeCurrent");
  293. glfw_dlsym(_glfw.egl.SwapBuffers, _glfw.egl.handle, "eglSwapBuffers");
  294. glfw_dlsym(_glfw.egl.SwapInterval, _glfw.egl.handle, "eglSwapInterval");
  295. glfw_dlsym(_glfw.egl.QueryString, _glfw.egl.handle, "eglQueryString");
  296. glfw_dlsym(_glfw.egl.QuerySurface, _glfw.egl.handle, "eglQuerySurface");
  297. glfw_dlsym(_glfw.egl.GetProcAddress, _glfw.egl.handle, "eglGetProcAddress");
  298. if (!_glfw.egl.GetConfigAttrib ||
  299. !_glfw.egl.GetConfigs ||
  300. !_glfw.egl.ChooseConfig ||
  301. !_glfw.egl.GetDisplay ||
  302. !_glfw.egl.GetError ||
  303. !_glfw.egl.Initialize ||
  304. !_glfw.egl.Terminate ||
  305. !_glfw.egl.BindAPI ||
  306. !_glfw.egl.CreateContext ||
  307. !_glfw.egl.DestroySurface ||
  308. !_glfw.egl.DestroyContext ||
  309. !_glfw.egl.CreateWindowSurface ||
  310. !_glfw.egl.MakeCurrent ||
  311. !_glfw.egl.SwapBuffers ||
  312. !_glfw.egl.SwapInterval ||
  313. !_glfw.egl.QueryString ||
  314. !_glfw.egl.GetProcAddress)
  315. {
  316. _glfwInputError(GLFW_PLATFORM_ERROR,
  317. "EGL: Failed to load required entry points");
  318. _glfwTerminateEGL();
  319. return false;
  320. }
  321. extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
  322. if (extensions && eglGetError() == EGL_SUCCESS)
  323. _glfw.egl.EXT_client_extensions = true;
  324. if (_glfw.egl.EXT_client_extensions)
  325. {
  326. _glfw.egl.EXT_platform_base =
  327. _glfwStringInExtensionString("EGL_EXT_platform_base", extensions);
  328. _glfw.egl.EXT_platform_x11 =
  329. _glfwStringInExtensionString("EGL_EXT_platform_x11", extensions);
  330. _glfw.egl.EXT_platform_wayland =
  331. _glfwStringInExtensionString("EGL_EXT_platform_wayland", extensions);
  332. _glfw.egl.ANGLE_platform_angle =
  333. _glfwStringInExtensionString("EGL_ANGLE_platform_angle", extensions);
  334. _glfw.egl.ANGLE_platform_angle_opengl =
  335. _glfwStringInExtensionString("EGL_ANGLE_platform_angle_opengl", extensions);
  336. _glfw.egl.ANGLE_platform_angle_d3d =
  337. _glfwStringInExtensionString("EGL_ANGLE_platform_angle_d3d", extensions);
  338. _glfw.egl.ANGLE_platform_angle_vulkan =
  339. _glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions);
  340. _glfw.egl.ANGLE_platform_angle_metal =
  341. _glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions);
  342. }
  343. if (_glfw.egl.EXT_platform_base)
  344. {
  345. _glfw.egl.GetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)
  346. eglGetProcAddress("eglGetPlatformDisplayEXT");
  347. _glfw.egl.CreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)
  348. eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
  349. }
  350. _glfw.egl.platform = _glfwPlatformGetEGLPlatform(&attribs);
  351. if (_glfw.egl.platform)
  352. {
  353. _glfw.egl.display =
  354. eglGetPlatformDisplayEXT(_glfw.egl.platform,
  355. _glfwPlatformGetEGLNativeDisplay(),
  356. attribs);
  357. }
  358. else
  359. _glfw.egl.display = eglGetDisplay(_glfwPlatformGetEGLNativeDisplay());
  360. free(attribs);
  361. if (_glfw.egl.display == EGL_NO_DISPLAY)
  362. {
  363. _glfwInputError(GLFW_API_UNAVAILABLE,
  364. "EGL: Failed to get EGL display: %s",
  365. getEGLErrorString(eglGetError()));
  366. _glfwTerminateEGL();
  367. return false;
  368. }
  369. if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
  370. {
  371. _glfwInputError(GLFW_API_UNAVAILABLE,
  372. "EGL: Failed to initialize EGL: %s",
  373. getEGLErrorString(eglGetError()));
  374. _glfwTerminateEGL();
  375. return false;
  376. }
  377. _glfw.egl.KHR_create_context =
  378. extensionSupportedEGL("EGL_KHR_create_context");
  379. _glfw.egl.KHR_create_context_no_error =
  380. extensionSupportedEGL("EGL_KHR_create_context_no_error");
  381. _glfw.egl.KHR_gl_colorspace =
  382. extensionSupportedEGL("EGL_KHR_gl_colorspace");
  383. _glfw.egl.KHR_get_all_proc_addresses =
  384. extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
  385. _glfw.egl.KHR_context_flush_control =
  386. extensionSupportedEGL("EGL_KHR_context_flush_control");
  387. _glfw.egl.EXT_present_opaque =
  388. extensionSupportedEGL("EGL_EXT_present_opaque");
  389. return true;
  390. }
  391. // Terminate EGL
  392. //
  393. void _glfwTerminateEGL(void)
  394. {
  395. if (_glfw.egl.display)
  396. {
  397. eglTerminate(_glfw.egl.display);
  398. _glfw.egl.display = EGL_NO_DISPLAY;
  399. }
  400. if (_glfw.egl.handle)
  401. {
  402. _glfw_dlclose(_glfw.egl.handle);
  403. _glfw.egl.handle = NULL;
  404. }
  405. }
  406. #define setAttrib(a, v) \
  407. { \
  408. assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
  409. attribs[index++] = a; \
  410. attribs[index++] = v; \
  411. }
  412. // Create the OpenGL or OpenGL ES context
  413. //
  414. bool _glfwCreateContextEGL(_GLFWwindow* window,
  415. const _GLFWctxconfig* ctxconfig,
  416. const _GLFWfbconfig* fbconfig)
  417. {
  418. EGLint attribs[40];
  419. EGLConfig config;
  420. EGLContext share = NULL;
  421. EGLNativeWindowType native;
  422. int index = 0;
  423. if (!_glfw.egl.display)
  424. {
  425. _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
  426. return false;
  427. }
  428. if (ctxconfig->share)
  429. share = ctxconfig->share->context.egl.handle;
  430. if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
  431. {
  432. _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
  433. "EGL: Failed to find a suitable EGLConfig");
  434. return false;
  435. }
  436. if (ctxconfig->client == GLFW_OPENGL_ES_API)
  437. {
  438. if (!eglBindAPI(EGL_OPENGL_ES_API))
  439. {
  440. _glfwInputError(GLFW_API_UNAVAILABLE,
  441. "EGL: Failed to bind OpenGL ES: %s",
  442. getEGLErrorString(eglGetError()));
  443. return false;
  444. }
  445. }
  446. else
  447. {
  448. if (!eglBindAPI(EGL_OPENGL_API))
  449. {
  450. _glfwInputError(GLFW_API_UNAVAILABLE,
  451. "EGL: Failed to bind OpenGL: %s",
  452. getEGLErrorString(eglGetError()));
  453. return false;
  454. }
  455. }
  456. if (_glfw.egl.KHR_create_context)
  457. {
  458. int mask = 0, flags = 0;
  459. if (ctxconfig->client == GLFW_OPENGL_API)
  460. {
  461. if (ctxconfig->forward)
  462. flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
  463. if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
  464. mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
  465. else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
  466. mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
  467. }
  468. if (ctxconfig->debug)
  469. flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
  470. if (ctxconfig->robustness)
  471. {
  472. if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
  473. {
  474. setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
  475. EGL_NO_RESET_NOTIFICATION_KHR);
  476. }
  477. else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
  478. {
  479. setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
  480. EGL_LOSE_CONTEXT_ON_RESET_KHR);
  481. }
  482. flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
  483. }
  484. if (ctxconfig->noerror)
  485. {
  486. if (_glfw.egl.KHR_create_context_no_error)
  487. setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
  488. }
  489. if (ctxconfig->major != 1 || ctxconfig->minor != 0)
  490. {
  491. setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
  492. setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
  493. }
  494. if (mask)
  495. setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
  496. if (flags)
  497. setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
  498. }
  499. else
  500. {
  501. if (ctxconfig->client == GLFW_OPENGL_ES_API)
  502. setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
  503. }
  504. if (_glfw.egl.KHR_context_flush_control)
  505. {
  506. if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
  507. {
  508. setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
  509. EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
  510. }
  511. else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
  512. {
  513. setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
  514. EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
  515. }
  516. }
  517. setAttrib(EGL_NONE, EGL_NONE);
  518. window->context.egl.handle = eglCreateContext(_glfw.egl.display,
  519. config, share, attribs);
  520. if (window->context.egl.handle == EGL_NO_CONTEXT)
  521. {
  522. _glfwInputError(GLFW_VERSION_UNAVAILABLE,
  523. "EGL: Failed to create context: %s",
  524. getEGLErrorString(eglGetError()));
  525. return false;
  526. }
  527. // Set up attributes for surface creation
  528. index = 0;
  529. if (fbconfig->sRGB)
  530. {
  531. if (_glfw.egl.KHR_gl_colorspace)
  532. setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
  533. }
  534. // Disabled because it prevents transparency from working on NVIDIA drivers under Wayland
  535. // https://github.com/kovidgoyal/kitty/issues/5479
  536. // We anyway dont use the alpha bits for anything.
  537. /* if (_glfw.egl.EXT_present_opaque) */
  538. /* setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); */
  539. setAttrib(EGL_NONE, EGL_NONE);
  540. native = _glfwPlatformGetEGLNativeWindow(window);
  541. // HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT
  542. // despite reporting EGL_EXT_platform_base
  543. if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE)
  544. {
  545. window->context.egl.surface =
  546. eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs);
  547. }
  548. else
  549. {
  550. window->context.egl.surface =
  551. eglCreateWindowSurface(_glfw.egl.display, config, native, attribs);
  552. }
  553. if (window->context.egl.surface == EGL_NO_SURFACE)
  554. {
  555. _glfwInputError(GLFW_PLATFORM_ERROR,
  556. "EGL: Failed to create window surface: %s",
  557. getEGLErrorString(eglGetError()));
  558. return false;
  559. }
  560. window->context.egl.config = config;
  561. EGLint a = EGL_MIN_SWAP_INTERVAL;
  562. if (!eglGetConfigAttrib(_glfw.egl.display, config, a, &a)) {
  563. _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: could not check for non-blocking buffer swap with error: %s", getEGLErrorString(eglGetError()));
  564. } else {
  565. if (a > 0) {
  566. _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: non-blocking swap buffers not available, minimum swap interval is: %d", a);
  567. }
  568. }
  569. // Load the appropriate client library
  570. if (!_glfw.egl.KHR_get_all_proc_addresses)
  571. {
  572. int i;
  573. const char** sonames;
  574. const char* es1sonames[] =
  575. {
  576. #if defined(_GLFW_GLESV1_LIBRARY)
  577. _GLFW_GLESV1_LIBRARY,
  578. #elif defined(_GLFW_WIN32)
  579. "GLESv1_CM.dll",
  580. "libGLES_CM.dll",
  581. #elif defined(_GLFW_COCOA)
  582. "libGLESv1_CM.dylib",
  583. #else
  584. "libGLESv1_CM.so.1",
  585. "libGLES_CM.so.1",
  586. #endif
  587. NULL
  588. };
  589. const char* es2sonames[] =
  590. {
  591. #if defined(_GLFW_GLESV2_LIBRARY)
  592. _GLFW_GLESV2_LIBRARY,
  593. #elif defined(_GLFW_WIN32)
  594. "GLESv2.dll",
  595. "libGLESv2.dll",
  596. #elif defined(_GLFW_COCOA)
  597. "libGLESv2.dylib",
  598. #elif defined(__CYGWIN__)
  599. "libGLESv2-2.so",
  600. #else
  601. "libGLESv2.so.2",
  602. #endif
  603. NULL
  604. };
  605. const char* glsonames[] =
  606. {
  607. #if defined(_GLFW_OPENGL_LIBRARY)
  608. _GLFW_OPENGL_LIBRARY,
  609. #elif defined(_GLFW_WIN32)
  610. #elif defined(_GLFW_COCOA)
  611. #else
  612. "libGL.so.1",
  613. #endif
  614. NULL
  615. };
  616. if (ctxconfig->client == GLFW_OPENGL_ES_API)
  617. {
  618. if (ctxconfig->major == 1)
  619. sonames = es1sonames;
  620. else
  621. sonames = es2sonames;
  622. }
  623. else
  624. sonames = glsonames;
  625. for (i = 0; sonames[i]; i++)
  626. {
  627. // HACK: Match presence of lib prefix to increase chance of finding
  628. // a matching pair in the jungle that is Win32 EGL/GLES
  629. if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
  630. continue;
  631. window->context.egl.client = _glfw_dlopen(sonames[i]);
  632. if (window->context.egl.client)
  633. break;
  634. }
  635. if (!window->context.egl.client)
  636. {
  637. _glfwInputError(GLFW_API_UNAVAILABLE,
  638. "EGL: Failed to load client library");
  639. return false;
  640. }
  641. }
  642. window->context.makeCurrent = makeContextCurrentEGL;
  643. window->context.swapBuffers = swapBuffersEGL;
  644. window->context.swapInterval = swapIntervalEGL;
  645. window->context.extensionSupported = extensionSupportedEGL;
  646. window->context.getProcAddress = getProcAddressEGL;
  647. window->context.destroy = destroyContextEGL;
  648. return true;
  649. }
  650. #undef setAttrib
  651. // Returns the Visual and depth of the chosen EGLConfig
  652. //
  653. #if defined(_GLFW_X11)
  654. bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig UNUSED,
  655. const _GLFWctxconfig* ctxconfig,
  656. const _GLFWfbconfig* fbconfig,
  657. Visual** visual, int* depth)
  658. {
  659. XVisualInfo* result;
  660. XVisualInfo desired;
  661. EGLConfig native;
  662. EGLint visualID = 0, count = 0;
  663. const long vimask = VisualScreenMask | VisualIDMask;
  664. if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
  665. {
  666. _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
  667. "EGL: Failed to find a suitable EGLConfig");
  668. return false;
  669. }
  670. eglGetConfigAttrib(_glfw.egl.display, native,
  671. EGL_NATIVE_VISUAL_ID, &visualID);
  672. desired.screen = _glfw.x11.screen;
  673. desired.visualid = visualID;
  674. result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
  675. if (!result)
  676. {
  677. _glfwInputError(GLFW_PLATFORM_ERROR,
  678. "EGL: Failed to retrieve Visual for EGLConfig");
  679. return false;
  680. }
  681. *visual = result->visual;
  682. *depth = result->depth;
  683. XFree(result);
  684. return true;
  685. }
  686. #endif // _GLFW_X11
  687. //////////////////////////////////////////////////////////////////////////
  688. ////// GLFW native API //////
  689. //////////////////////////////////////////////////////////////////////////
  690. GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
  691. {
  692. _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
  693. return _glfw.egl.display;
  694. }
  695. GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
  696. {
  697. _GLFWwindow* window = (_GLFWwindow*) handle;
  698. _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
  699. if (window->context.client == GLFW_NO_API)
  700. {
  701. _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
  702. return EGL_NO_CONTEXT;
  703. }
  704. return window->context.egl.handle;
  705. }
  706. GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
  707. {
  708. _GLFWwindow* window = (_GLFWwindow*) handle;
  709. _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
  710. if (window->context.client == GLFW_NO_API)
  711. {
  712. _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
  713. return EGL_NO_SURFACE;
  714. }
  715. return window->context.egl.surface;
  716. }