medfall

A super great game engine
Log | Files | Refs

egl_context.cc (23759B)


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