zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

egl_context.c (24689B)


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