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