Atlas - egl_context.c
Home / ext / glfw / src Lines: 1 | Size: 32384 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1//======================================================================== 2// GLFW 3.5 EGL - 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 28#include "internal.h" 29 30#include <stdio.h> 31#include <string.h> 32#include <stdlib.h> 33#include <assert.h> 34 35 36// Return a description of the specified EGL error 37// 38static const char* getEGLErrorString(EGLint error) 39{ 40 switch (error) 41 { 42 case EGL_SUCCESS: 43 return "Success"; 44 case EGL_NOT_INITIALIZED: 45 return "EGL is not or could not be initialized"; 46 case EGL_BAD_ACCESS: 47 return "EGL cannot access a requested resource"; 48 case EGL_BAD_ALLOC: 49 return "EGL failed to allocate resources for the requested operation"; 50 case EGL_BAD_ATTRIBUTE: 51 return "An unrecognized attribute or attribute value was passed in the attribute list"; 52 case EGL_BAD_CONTEXT: 53 return "An EGLContext argument does not name a valid EGL rendering context"; 54 case EGL_BAD_CONFIG: 55 return "An EGLConfig argument does not name a valid EGL frame buffer configuration"; 56 case EGL_BAD_CURRENT_SURFACE: 57 return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid"; 58 case EGL_BAD_DISPLAY: 59 return "An EGLDisplay argument does not name a valid EGL display connection"; 60 case EGL_BAD_SURFACE: 61 return "An EGLSurface argument does not name a valid surface configured for GL rendering"; 62 case EGL_BAD_MATCH: 63 return "Arguments are inconsistent"; 64 case EGL_BAD_PARAMETER: 65 return "One or more argument values are invalid"; 66 case EGL_BAD_NATIVE_PIXMAP: 67 return "A NativePixmapType argument does not refer to a valid native pixmap"; 68 case EGL_BAD_NATIVE_WINDOW: 69 return "A NativeWindowType argument does not refer to a valid native window"; 70 case EGL_CONTEXT_LOST: 71 return "The application must destroy all contexts and reinitialise"; 72 default: 73 return "ERROR: UNKNOWN EGL ERROR"; 74 } 75} 76 77// Returns the specified attribute of the specified EGLConfig 78// 79static int getEGLConfigAttrib(EGLConfig config, int attrib) 80{ 81 int value; 82 eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value); 83 return value; 84} 85 86// Return the EGLConfig most closely matching the specified hints 87// 88static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, 89 const _GLFWfbconfig* fbconfig, 90 EGLConfig* result) 91{ 92 EGLConfig* nativeConfigs; 93 _GLFWfbconfig* usableConfigs; 94 const _GLFWfbconfig* closest; 95 int i, nativeCount, usableCount, apiBit, surfaceTypeBit; 96 GLFWbool wrongApiAvailable = GLFW_FALSE; 97 98 if (ctxconfig->client == GLFW_OPENGL_ES_API) 99 { 100 if (ctxconfig->major == 1) 101 apiBit = EGL_OPENGL_ES_BIT; 102 else 103 apiBit = EGL_OPENGL_ES2_BIT; 104 } 105 else 106 apiBit = EGL_OPENGL_BIT; 107 108 if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) 109 surfaceTypeBit = EGL_PBUFFER_BIT; 110 else 111 surfaceTypeBit = EGL_WINDOW_BIT; 112 113 if (fbconfig->stereo) 114 { 115 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported"); 116 return GLFW_FALSE; 117 } 118 119 eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); 120 if (!nativeCount) 121 { 122 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned"); 123 return GLFW_FALSE; 124 } 125 126 nativeConfigs = _glfw_calloc(nativeCount, sizeof(EGLConfig)); 127 eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); 128 129 usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); 130 usableCount = 0; 131 132 for (i = 0; i < nativeCount; i++) 133 { 134 const EGLConfig n = nativeConfigs[i]; 135 _GLFWfbconfig* u = usableConfigs + usableCount; 136 137 // Only consider RGB(A) EGLConfigs 138 if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) 139 continue; 140 141 if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & surfaceTypeBit)) 142 continue; 143 144#if defined(_GLFW_X11) 145 if (_glfw.platform.platformID == GLFW_PLATFORM_X11) 146 { 147 XVisualInfo vi = {0}; 148 149 // Only consider EGLConfigs with associated Visuals 150 vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID); 151 if (!vi.visualid) 152 continue; 153 154 if (fbconfig->transparent) 155 { 156 int count; 157 XVisualInfo* vis = 158 XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count); 159 if (vis) 160 { 161 u->transparent = _glfwIsVisualTransparentX11(vis[0].visual); 162 XFree(vis); 163 } 164 } 165 } 166#endif // _GLFW_X11 167 168 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit)) 169 { 170 wrongApiAvailable = GLFW_TRUE; 171 continue; 172 } 173 174 u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); 175 u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE); 176 u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE); 177 178 u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE); 179 u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE); 180 u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); 181 182#if defined(_GLFW_WAYLAND) 183 if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) 184 { 185 // NOTE: The wl_surface opaque region is no guarantee that its buffer 186 // is presented as opaque, if it also has an alpha channel 187 // HACK: If EGL_EXT_present_opaque is unavailable, ignore any config 188 // with an alpha channel to ensure the buffer is opaque 189 if (!_glfw.egl.EXT_present_opaque) 190 { 191 if (!fbconfig->transparent && u->alphaBits > 0) 192 continue; 193 } 194 } 195#endif // _GLFW_WAYLAND 196 197 u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); 198 u->doublebuffer = fbconfig->doublebuffer; 199 200 u->handle = (uintptr_t) n; 201 usableCount++; 202 } 203 204 closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount); 205 if (closest) 206 *result = (EGLConfig) closest->handle; 207 else 208 { 209 if (wrongApiAvailable) 210 { 211 if (ctxconfig->client == GLFW_OPENGL_ES_API) 212 { 213 if (ctxconfig->major == 1) 214 { 215 _glfwInputError(GLFW_API_UNAVAILABLE, 216 "EGL: Failed to find support for OpenGL ES 1.x"); 217 } 218 else 219 { 220 _glfwInputError(GLFW_API_UNAVAILABLE, 221 "EGL: Failed to find support for OpenGL ES 2 or later"); 222 } 223 } 224 else 225 { 226 _glfwInputError(GLFW_API_UNAVAILABLE, 227 "EGL: Failed to find support for OpenGL"); 228 } 229 } 230 else 231 { 232 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 233 "EGL: Failed to find a suitable EGLConfig"); 234 } 235 } 236 237 _glfw_free(nativeConfigs); 238 _glfw_free(usableConfigs); 239 240 return closest != NULL; 241} 242 243static void makeContextCurrentEGL(_GLFWwindow* window) 244{ 245 if (window) 246 { 247 if (!eglMakeCurrent(_glfw.egl.display, 248 window->context.egl.surface, 249 window->context.egl.surface, 250 window->context.egl.handle)) 251 { 252 _glfwInputError(GLFW_PLATFORM_ERROR, 253 "EGL: Failed to make context current: %s", 254 getEGLErrorString(eglGetError())); 255 return; 256 } 257 258#if defined(_GLFW_WAYLAND) 259 // NOTE: Disable EGL vsync so we can substitute our own that includes a timeout 260 if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) 261 eglSwapInterval(_glfw.egl.display, 0); 262#endif // _GLFW_WAYLAND 263 } 264 else 265 { 266 if (!eglMakeCurrent(_glfw.egl.display, 267 EGL_NO_SURFACE, 268 EGL_NO_SURFACE, 269 EGL_NO_CONTEXT)) 270 { 271 _glfwInputError(GLFW_PLATFORM_ERROR, 272 "EGL: Failed to clear current context: %s", 273 getEGLErrorString(eglGetError())); 274 return; 275 } 276 } 277 278 _glfwPlatformSetTls(&_glfw.contextSlot, window); 279} 280 281static void swapBuffersEGL(_GLFWwindow* window) 282{ 283 if (window != _glfwPlatformGetTls(&_glfw.contextSlot)) 284 { 285 _glfwInputError(GLFW_PLATFORM_ERROR, 286 "EGL: The context must be current on the calling thread when swapping buffers"); 287 return; 288 } 289 290#if defined(_GLFW_WAYLAND) 291 if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) 292 { 293 // NOTE: Swapping buffers on a hidden window on Wayland makes it visible 294 if (!window->wl.visible) 295 return; 296 297 // NOTE: We wait for a frame manually so we can add a timeout, 298 // as the EGL implementation will wait indefinitely 299 if (window->wl.egl.interval > 0) 300 { 301 window->context.Flush(); 302 if (!_glfwWaitForEGLFrameWayland(window)) 303 return; 304 } 305 } 306#endif 307 308 eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); 309} 310 311static void swapIntervalEGL(int interval) 312{ 313#if defined(_GLFW_WAYLAND) 314 if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) 315 { 316 _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); 317 assert(window != NULL); 318 window->wl.egl.interval = interval; 319 return; 320 } 321#endif 322 323 eglSwapInterval(_glfw.egl.display, interval); 324} 325 326static int extensionSupportedEGL(const char* extension) 327{ 328 const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS); 329 if (extensions) 330 { 331 if (_glfwStringInExtensionString(extension, extensions)) 332 return GLFW_TRUE; 333 } 334 335 return GLFW_FALSE; 336} 337 338static GLFWglproc getProcAddressEGL(const char* procname) 339{ 340 const GLFWglproc proc = (GLFWglproc) eglGetProcAddress(procname); 341 if (proc) 342 return proc; 343 344 if (!_glfw.egl.KHR_get_all_proc_addresses) 345 { 346 _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); 347 assert(window != NULL); 348 349 return _glfwPlatformGetModuleSymbol(window->context.egl.client, procname); 350 } 351 352 return NULL; 353} 354 355static void destroyContextEGL(_GLFWwindow* window) 356{ 357 // NOTE: Do not unload libGL.so.1 while the X11 display is still open, 358 // as it will make XCloseDisplay segfault 359 if (_glfw.platform.platformID != GLFW_PLATFORM_X11 || 360 window->context.client != GLFW_OPENGL_API) 361 { 362 _glfwPlatformFreeModule(window->context.egl.client); 363 window->context.egl.client = NULL; 364 } 365 366 if (window->context.egl.surface) 367 { 368 eglDestroySurface(_glfw.egl.display, window->context.egl.surface); 369 window->context.egl.surface = EGL_NO_SURFACE; 370 } 371 372 if (window->context.egl.handle) 373 { 374 eglDestroyContext(_glfw.egl.display, window->context.egl.handle); 375 window->context.egl.handle = EGL_NO_CONTEXT; 376 } 377} 378 379 380////////////////////////////////////////////////////////////////////////// 381////// GLFW internal API ////// 382////////////////////////////////////////////////////////////////////////// 383 384GLFWbool _glfwInitEGL(void) 385{ 386 int i; 387 EGLint* attribs = NULL; 388 const char* extensions; 389 const char* sonames[] = 390 { 391#if defined(_GLFW_EGL_LIBRARY) 392 _GLFW_EGL_LIBRARY, 393#elif defined(_WIN32) 394 "libEGL.dll", 395 "EGL.dll", 396#elif defined(__APPLE__) 397 "libEGL.dylib", 398#elif defined(__CYGWIN__) 399 "libEGL-1.so", 400#elif defined(__OpenBSD__) || defined(__NetBSD__) 401 "libEGL.so", 402#else 403 "libEGL.so.1", 404#endif 405 NULL 406 }; 407 408 if (_glfw.egl.handle) 409 return GLFW_TRUE; 410 411 for (i = 0; sonames[i]; i++) 412 { 413 _glfw.egl.handle = _glfwPlatformLoadModule(sonames[i]); 414 if (_glfw.egl.handle) 415 break; 416 } 417 418 if (!_glfw.egl.handle) 419 { 420 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found"); 421 return GLFW_FALSE; 422 } 423 424 _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); 425 426 _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib) 427 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetConfigAttrib"); 428 _glfw.egl.GetConfigs = (PFN_eglGetConfigs) 429 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetConfigs"); 430 _glfw.egl.GetDisplay = (PFN_eglGetDisplay) 431 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetDisplay"); 432 _glfw.egl.GetError = (PFN_eglGetError) 433 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetError"); 434 _glfw.egl.Initialize = (PFN_eglInitialize) 435 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglInitialize"); 436 _glfw.egl.Terminate = (PFN_eglTerminate) 437 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglTerminate"); 438 _glfw.egl.BindAPI = (PFN_eglBindAPI) 439 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglBindAPI"); 440 _glfw.egl.CreateContext = (PFN_eglCreateContext) 441 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateContext"); 442 _glfw.egl.DestroySurface = (PFN_eglDestroySurface) 443 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroySurface"); 444 _glfw.egl.DestroyContext = (PFN_eglDestroyContext) 445 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext"); 446 _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) 447 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface"); 448 _glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface) 449 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreatePbufferSurface"); 450 _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) 451 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent"); 452 _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) 453 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglSwapBuffers"); 454 _glfw.egl.SwapInterval = (PFN_eglSwapInterval) 455 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglSwapInterval"); 456 _glfw.egl.QueryString = (PFN_eglQueryString) 457 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglQueryString"); 458 _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress) 459 _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetProcAddress"); 460 461 if (!_glfw.egl.GetConfigAttrib || 462 !_glfw.egl.GetConfigs || 463 !_glfw.egl.GetDisplay || 464 !_glfw.egl.GetError || 465 !_glfw.egl.Initialize || 466 !_glfw.egl.Terminate || 467 !_glfw.egl.BindAPI || 468 !_glfw.egl.CreateContext || 469 !_glfw.egl.DestroySurface || 470 !_glfw.egl.DestroyContext || 471 !_glfw.egl.CreateWindowSurface || 472 !_glfw.egl.CreatePbufferSurface || 473 !_glfw.egl.MakeCurrent || 474 !_glfw.egl.SwapBuffers || 475 !_glfw.egl.SwapInterval || 476 !_glfw.egl.QueryString || 477 !_glfw.egl.GetProcAddress) 478 { 479 _glfwInputError(GLFW_PLATFORM_ERROR, 480 "EGL: Failed to load required entry points"); 481 482 _glfwTerminateEGL(); 483 return GLFW_FALSE; 484 } 485 486 extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); 487 if (extensions && eglGetError() == EGL_SUCCESS) 488 _glfw.egl.EXT_client_extensions = GLFW_TRUE; 489 490 if (_glfw.egl.EXT_client_extensions) 491 { 492 _glfw.egl.EXT_platform_base = 493 _glfwStringInExtensionString("EGL_EXT_platform_base", extensions); 494 _glfw.egl.EXT_platform_x11 = 495 _glfwStringInExtensionString("EGL_EXT_platform_x11", extensions); 496 _glfw.egl.EXT_platform_wayland = 497 _glfwStringInExtensionString("EGL_EXT_platform_wayland", extensions); 498 _glfw.egl.ANGLE_platform_angle = 499 _glfwStringInExtensionString("EGL_ANGLE_platform_angle", extensions); 500 _glfw.egl.ANGLE_platform_angle_opengl = 501 _glfwStringInExtensionString("EGL_ANGLE_platform_angle_opengl", extensions); 502 _glfw.egl.ANGLE_platform_angle_d3d = 503 _glfwStringInExtensionString("EGL_ANGLE_platform_angle_d3d", extensions); 504 _glfw.egl.ANGLE_platform_angle_vulkan = 505 _glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions); 506 _glfw.egl.ANGLE_platform_angle_metal = 507 _glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions); 508 _glfw.egl.MESA_platform_surfaceless = 509 _glfwStringInExtensionString("EGL_MESA_platform_surfaceless", extensions); 510 } 511 512 if (_glfw.egl.EXT_platform_base) 513 { 514 _glfw.egl.GetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) 515 eglGetProcAddress("eglGetPlatformDisplayEXT"); 516 _glfw.egl.CreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) 517 eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); 518 } 519 520 _glfw.egl.platform = _glfw.platform.getEGLPlatform(&attribs); 521 if (_glfw.egl.platform) 522 { 523 _glfw.egl.display = 524 eglGetPlatformDisplayEXT(_glfw.egl.platform, 525 _glfw.platform.getEGLNativeDisplay(), 526 attribs); 527 } 528 else 529 _glfw.egl.display = eglGetDisplay(_glfw.platform.getEGLNativeDisplay()); 530 531 _glfw_free(attribs); 532 533 if (_glfw.egl.display == EGL_NO_DISPLAY) 534 { 535 _glfwInputError(GLFW_API_UNAVAILABLE, 536 "EGL: Failed to get EGL display: %s", 537 getEGLErrorString(eglGetError())); 538 539 _glfwTerminateEGL(); 540 return GLFW_FALSE; 541 } 542 543 if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) 544 { 545 _glfwInputError(GLFW_API_UNAVAILABLE, 546 "EGL: Failed to initialize EGL: %s", 547 getEGLErrorString(eglGetError())); 548 549 _glfwTerminateEGL(); 550 return GLFW_FALSE; 551 } 552 553 _glfw.egl.KHR_create_context = 554 extensionSupportedEGL("EGL_KHR_create_context"); 555 _glfw.egl.KHR_create_context_no_error = 556 extensionSupportedEGL("EGL_KHR_create_context_no_error"); 557 _glfw.egl.KHR_gl_colorspace = 558 extensionSupportedEGL("EGL_KHR_gl_colorspace"); 559 _glfw.egl.KHR_get_all_proc_addresses = 560 extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); 561 _glfw.egl.KHR_context_flush_control = 562 extensionSupportedEGL("EGL_KHR_context_flush_control"); 563 _glfw.egl.EXT_present_opaque = 564 extensionSupportedEGL("EGL_EXT_present_opaque"); 565 566 return GLFW_TRUE; 567} 568 569void _glfwTerminateEGL(void) 570{ 571 if (_glfw.egl.display) 572 { 573 eglTerminate(_glfw.egl.display); 574 _glfw.egl.display = EGL_NO_DISPLAY; 575 } 576 577 // Free modules only after all wayland termination functions are called 578 if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) 579 { 580 _glfwPlatformFreeModule(_glfw.egl.handle); 581 _glfw.egl.handle = NULL; 582 } 583} 584 585#define SET_ATTRIB(a, v) \ 586{ \ 587 assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ 588 attribs[index++] = a; \ 589 attribs[index++] = v; \ 590} 591 592GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, 593 const _GLFWctxconfig* ctxconfig, 594 const _GLFWfbconfig* fbconfig) 595{ 596 EGLint attribs[40]; 597 EGLConfig config; 598 EGLContext share = NULL; 599 EGLNativeWindowType native; 600 int index = 0; 601 602 if (!_glfw.egl.display) 603 { 604 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available"); 605 return GLFW_FALSE; 606 } 607 608 if (ctxconfig->share) 609 share = ctxconfig->share->context.egl.handle; 610 611 if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) 612 return GLFW_FALSE; 613 614 if (ctxconfig->client == GLFW_OPENGL_ES_API) 615 { 616 if (!eglBindAPI(EGL_OPENGL_ES_API)) 617 { 618 _glfwInputError(GLFW_API_UNAVAILABLE, 619 "EGL: Failed to bind OpenGL ES: %s", 620 getEGLErrorString(eglGetError())); 621 return GLFW_FALSE; 622 } 623 } 624 else 625 { 626 if (!eglBindAPI(EGL_OPENGL_API)) 627 { 628 _glfwInputError(GLFW_API_UNAVAILABLE, 629 "EGL: Failed to bind OpenGL: %s", 630 getEGLErrorString(eglGetError())); 631 return GLFW_FALSE; 632 } 633 } 634 635 if (_glfw.egl.KHR_create_context) 636 { 637 int mask = 0, flags = 0; 638 639 if (ctxconfig->client == GLFW_OPENGL_API) 640 { 641 if (ctxconfig->forward) 642 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 643 644 if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) 645 mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 646 else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) 647 mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; 648 } 649 650 if (ctxconfig->debug) 651 flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 652 653 if (ctxconfig->robustness) 654 { 655 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) 656 { 657 SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 658 EGL_NO_RESET_NOTIFICATION_KHR); 659 } 660 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) 661 { 662 SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 663 EGL_LOSE_CONTEXT_ON_RESET_KHR); 664 } 665 666 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 667 } 668 669 if (ctxconfig->major != 1 || ctxconfig->minor != 0) 670 { 671 SET_ATTRIB(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); 672 SET_ATTRIB(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); 673 } 674 675 if (ctxconfig->noerror) 676 { 677 if (_glfw.egl.KHR_create_context_no_error) 678 SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true); 679 } 680 681 if (mask) 682 SET_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); 683 684 if (flags) 685 SET_ATTRIB(EGL_CONTEXT_FLAGS_KHR, flags); 686 } 687 else 688 { 689 if (ctxconfig->client == GLFW_OPENGL_ES_API) 690 SET_ATTRIB(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); 691 } 692 693 if (_glfw.egl.KHR_context_flush_control) 694 { 695 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) 696 { 697 SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 698 EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR); 699 } 700 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) 701 { 702 SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 703 EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR); 704 } 705 } 706 707 SET_ATTRIB(EGL_NONE, EGL_NONE); 708 709 window->context.egl.handle = eglCreateContext(_glfw.egl.display, 710 config, share, attribs); 711 712 if (window->context.egl.handle == EGL_NO_CONTEXT) 713 { 714 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 715 "EGL: Failed to create context: %s", 716 getEGLErrorString(eglGetError())); 717 return GLFW_FALSE; 718 } 719 720 // Set up attributes for surface creation 721 index = 0; 722 723 if (fbconfig->sRGB) 724 { 725 if (_glfw.egl.KHR_gl_colorspace) 726 SET_ATTRIB(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); 727 } 728 729 if (!fbconfig->doublebuffer) 730 SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); 731 732 if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) 733 { 734 if (_glfw.egl.EXT_present_opaque) 735 SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); 736 } 737 738 if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) 739 { 740 int width, height; 741 _glfw.platform.getFramebufferSize(window, &width, &height); 742 743 SET_ATTRIB(EGL_WIDTH, width); 744 SET_ATTRIB(EGL_HEIGHT, height); 745 } 746 747 SET_ATTRIB(EGL_NONE, EGL_NONE); 748 749 native = _glfw.platform.getEGLNativeWindow(window); 750 if (!_glfw.egl.platform || _glfw.egl.platform == EGL_PLATFORM_ANGLE_ANGLE) 751 { 752 // HACK: Also use non-platform function for ANGLE, as it does not 753 // implement eglCreatePlatformWindowSurfaceEXT despite reporting 754 // support for EGL_EXT_platform_base 755 window->context.egl.surface = 756 eglCreateWindowSurface(_glfw.egl.display, config, native, attribs); 757 } 758 else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) 759 { 760 // HACK: Use a pbuffer surface as the default framebuffer 761 window->context.egl.surface = 762 eglCreatePbufferSurface(_glfw.egl.display, config, attribs); 763 } 764 else 765 { 766 window->context.egl.surface = 767 eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs); 768 } 769 770 if (window->context.egl.surface == EGL_NO_SURFACE) 771 { 772 _glfwInputError(GLFW_PLATFORM_ERROR, 773 "EGL: Failed to create window surface: %s", 774 getEGLErrorString(eglGetError())); 775 return GLFW_FALSE; 776 } 777 778 window->context.egl.config = config; 779 780 // Load the appropriate client library 781 if (!_glfw.egl.KHR_get_all_proc_addresses) 782 { 783 int i; 784 const char** sonames; 785 const char* es1sonames[] = 786 { 787#if defined(_GLFW_GLESV1_LIBRARY) 788 _GLFW_GLESV1_LIBRARY, 789#elif defined(_WIN32) 790 "GLESv1_CM.dll", 791 "libGLES_CM.dll", 792#elif defined(__APPLE__) 793 "libGLESv1_CM.dylib", 794#elif defined(__OpenBSD__) || defined(__NetBSD__) 795 "libGLESv1_CM.so", 796#else 797 "libGLESv1_CM.so.1", 798 "libGLES_CM.so.1", 799#endif 800 NULL 801 }; 802 const char* es2sonames[] = 803 { 804#if defined(_GLFW_GLESV2_LIBRARY) 805 _GLFW_GLESV2_LIBRARY, 806#elif defined(_WIN32) 807 "GLESv2.dll", 808 "libGLESv2.dll", 809#elif defined(__APPLE__) 810 "libGLESv2.dylib", 811#elif defined(__CYGWIN__) 812 "libGLESv2-2.so", 813#elif defined(__OpenBSD__) || defined(__NetBSD__) 814 "libGLESv2.so", 815#else 816 "libGLESv2.so.2", 817#endif 818 NULL 819 }; 820 const char* glsonames[] = 821 { 822#if defined(_GLFW_OPENGL_LIBRARY) 823 _GLFW_OPENGL_LIBRARY, 824#elif defined(_WIN32) 825#elif defined(__APPLE__) 826#elif defined(__OpenBSD__) || defined(__NetBSD__) 827 "libGL.so", 828#else 829 "libOpenGL.so.0", 830 "libGL.so.1", 831#endif 832 NULL 833 }; 834 835 if (ctxconfig->client == GLFW_OPENGL_ES_API) 836 { 837 if (ctxconfig->major == 1) 838 sonames = es1sonames; 839 else 840 sonames = es2sonames; 841 } 842 else 843 sonames = glsonames; 844 845 for (i = 0; sonames[i]; i++) 846 { 847 // HACK: Match presence of lib prefix to increase chance of finding 848 // a matching pair in the jungle that is Win32 EGL/GLES 849 if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0)) 850 continue; 851 852 window->context.egl.client = _glfwPlatformLoadModule(sonames[i]); 853 if (window->context.egl.client) 854 break; 855 } 856 857 if (!window->context.egl.client) 858 { 859 _glfwInputError(GLFW_API_UNAVAILABLE, 860 "EGL: Failed to load client library"); 861 return GLFW_FALSE; 862 } 863 } 864 865 window->context.makeCurrent = makeContextCurrentEGL; 866 window->context.swapBuffers = swapBuffersEGL; 867 window->context.swapInterval = swapIntervalEGL; 868 window->context.extensionSupported = extensionSupportedEGL; 869 window->context.getProcAddress = getProcAddressEGL; 870 window->context.destroy = destroyContextEGL; 871 872 return GLFW_TRUE; 873} 874 875#undef SET_ATTRIB 876 877// Returns the Visual and depth of the chosen EGLConfig 878// 879#if defined(_GLFW_X11) 880GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, 881 const _GLFWctxconfig* ctxconfig, 882 const _GLFWfbconfig* fbconfig, 883 Visual** visual, int* depth) 884{ 885 XVisualInfo* result; 886 XVisualInfo desired; 887 EGLConfig native; 888 EGLint visualID = 0, count = 0; 889 const long vimask = VisualScreenMask | VisualIDMask; 890 891 if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) 892 return GLFW_FALSE; 893 894 eglGetConfigAttrib(_glfw.egl.display, native, 895 EGL_NATIVE_VISUAL_ID, &visualID); 896 897 desired.screen = _glfw.x11.screen; 898 desired.visualid = visualID; 899 900 result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count); 901 if (!result) 902 { 903 _glfwInputError(GLFW_PLATFORM_ERROR, 904 "EGL: Failed to retrieve Visual for EGLConfig"); 905 return GLFW_FALSE; 906 } 907 908 *visual = result->visual; 909 *depth = result->depth; 910 911 XFree(result); 912 return GLFW_TRUE; 913} 914#endif // _GLFW_X11 915 916 917////////////////////////////////////////////////////////////////////////// 918////// GLFW native API ////// 919////////////////////////////////////////////////////////////////////////// 920 921GLFWAPI EGLDisplay glfwGetEGLDisplay(void) 922{ 923 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY); 924 return _glfw.egl.display; 925} 926 927GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) 928{ 929 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); 930 931 _GLFWwindow* window = (_GLFWwindow*) handle; 932 assert(window != NULL); 933 934 if (window->context.source != GLFW_EGL_CONTEXT_API) 935 { 936 if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND || 937 window->context.source != GLFW_NATIVE_CONTEXT_API) 938 { 939 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 940 return EGL_NO_CONTEXT; 941 } 942 } 943 944 return window->context.egl.handle; 945} 946 947GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) 948{ 949 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); 950 951 _GLFWwindow* window = (_GLFWwindow*) handle; 952 assert(window != NULL); 953 954 if (window->context.source != GLFW_EGL_CONTEXT_API) 955 { 956 if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND || 957 window->context.source != GLFW_NATIVE_CONTEXT_API) 958 { 959 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 960 return EGL_NO_SURFACE; 961 } 962 } 963 964 return window->context.egl.surface; 965} 966 967GLFWAPI int glfwGetEGLConfig(GLFWwindow* handle, EGLConfig* config) 968{ 969 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 970 971 _GLFWwindow* window = (_GLFWwindow*) handle; 972 assert(window != NULL); 973 assert(config != NULL); 974 975 if (window->context.source != GLFW_EGL_CONTEXT_API) 976 { 977 if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND || 978 window->context.source != GLFW_NATIVE_CONTEXT_API) 979 { 980 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 981 return GLFW_FALSE; 982 } 983 } 984 985 *config = window->context.egl.config; 986 return GLFW_TRUE; 987} 988 989[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.