volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

egl_context.c (29593B)


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