text: //========================================================================
  // GLFW 3.4 EGL - www.glfw.org
  //------------------------------------------------------------------------
  // Copyright (c) 2002-2006 Marcus Geelnard
  // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
  //
  // This software is provided 'as-is', without any express or implied
  // warranty. In no event will the authors be held liable for any damages
  // arising from the use of this software.
  //
  // Permission is granted to anyone to use this software for any purpose,
  // including commercial applications, and to alter it and redistribute it
  // freely, subject to the following restrictions:
  //
  // 1. The origin of this software must not be misrepresented; you must not
  //    claim that you wrote the original software. If you use this software
  //    in a product, an acknowledgment in the product documentation would
  //    be appreciated but is not required.
  //
  // 2. Altered source versions must be plainly marked as such, and must not
  //    be misrepresented as being the original software.
  //
  // 3. This notice may not be removed or altered from any source
  //    distribution.
  //
  //========================================================================
  // Please use C89 style variable declarations in this file because VS 2010
  //========================================================================
  
  #include "internal.h"
  
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <assert.h>
  
  
  // Return a description of the specified EGL error
  //
  static const char* getEGLErrorString(EGLint error)
  {
      switch (error)
      {
          case EGL_SUCCESS:
              return "Success";
          case EGL_NOT_INITIALIZED:
              return "EGL is not or could not be initialized";
          case EGL_BAD_ACCESS:
              return "EGL cannot access a requested resource";
          case EGL_BAD_ALLOC:
              return "EGL failed to allocate resources for the requested operation";
          case EGL_BAD_ATTRIBUTE:
              return "An unrecognized attribute or attribute value was passed in the attribute list";
          case EGL_BAD_CONTEXT:
              return "An EGLContext argument does not name a valid EGL rendering context";
          case EGL_BAD_CONFIG:
              return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
          case EGL_BAD_CURRENT_SURFACE:
              return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
          case EGL_BAD_DISPLAY:
              return "An EGLDisplay argument does not name a valid EGL display connection";
          case EGL_BAD_SURFACE:
              return "An EGLSurface argument does not name a valid surface configured for GL rendering";
          case EGL_BAD_MATCH:
              return "Arguments are inconsistent";
          case EGL_BAD_PARAMETER:
              return "One or more argument values are invalid";
          case EGL_BAD_NATIVE_PIXMAP:
              return "A NativePixmapType argument does not refer to a valid native pixmap";
          case EGL_BAD_NATIVE_WINDOW:
              return "A NativeWindowType argument does not refer to a valid native window";
          case EGL_CONTEXT_LOST:
              return "The application must destroy all contexts and reinitialise";
          default:
              return "ERROR: UNKNOWN EGL ERROR";
      }
  }
  
  // Returns the specified attribute of the specified EGLConfig
  //
  static int getEGLConfigAttrib(EGLConfig config, int attrib)
  {
      int value;
      eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
      return value;
  }
  
  // Return the EGLConfig most closely matching the specified hints
  //
  static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
                                  const _GLFWfbconfig* desired,
                                  EGLConfig* result)
  {
      EGLConfig* nativeConfigs;
      _GLFWfbconfig* usableConfigs;
      const _GLFWfbconfig* closest;
      int i, nativeCount, usableCount;
  
      eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
      if (!nativeCount)
      {
          _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
          return GLFW_FALSE;
      }
  
      nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
      eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
  
      usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
      usableCount = 0;
  
      for (i = 0;  i < nativeCount;  i++)
      {
          const EGLConfig n = nativeConfigs[i];
          _GLFWfbconfig* u = usableConfigs + usableCount;
  
          // Only consider RGB(A) EGLConfigs
          if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
              continue;
  
          // Only consider window EGLConfigs
          if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
              continue;
  
  #if defined(_GLFW_X11)
          XVisualInfo vi = {0};
  
          // Only consider EGLConfigs with associated Visuals
          vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
          if (!vi.visualid)
              continue;
  
          if (desired->transparent)
          {
              int count;
              XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
                                                VisualIDMask, &vi,
                                                &count);
              if (vis)
              {
                  u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
                  XFree(vis);
              }
          }
  #endif // _GLFW_X11
  
          if (ctxconfig->client == GLFW_OPENGL_ES_API)
          {
              if (ctxconfig->major == 1)
              {
                  if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
                      continue;
              }
              else
              {
                  if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
                      continue;
              }
          }
          else if (ctxconfig->client == GLFW_OPENGL_API)
          {
              if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
                  continue;
          }
  
          u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
          u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
          u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
  
          u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
          u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
          u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
  
          u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
          u->doublebuffer = GLFW_TRUE;
  
          u->handle = (uintptr_t) n;
          usableCount++;
      }
  
      closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
      if (closest)
          *result = (EGLConfig) closest->handle;
  
      free(nativeConfigs);
      free(usableConfigs);
  
      return closest != NULL;
  }
  
  static void makeContextCurrentEGL(_GLFWwindow* window)
  {
      if (window)
      {
          if (!eglMakeCurrent(_glfw.egl.display,
                              window->context.egl.surface,
                              window->context.egl.surface,
                              window->context.egl.handle))
          {
              _glfwInputError(GLFW_PLATFORM_ERROR,
                              "EGL: Failed to make context current: %s",
                              getEGLErrorString(eglGetError()));
              return;
          }
      }
      else
      {
          if (!eglMakeCurrent(_glfw.egl.display,
                              EGL_NO_SURFACE,
                              EGL_NO_SURFACE,
                              EGL_NO_CONTEXT))
          {
              _glfwInputError(GLFW_PLATFORM_ERROR,
                              "EGL: Failed to clear current context: %s",
                              getEGLErrorString(eglGetError()));
              return;
          }
      }
  
      _glfwPlatformSetTls(&_glfw.contextSlot, window);
  }
  
  static void swapBuffersEGL(_GLFWwindow* window)
  {
      if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
      {
          _glfwInputError(GLFW_PLATFORM_ERROR,
                          "EGL: The context must be current on the calling thread when swapping buffers");
          return;
      }
  
      eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
  }
  
  static void swapIntervalEGL(int interval)
  {
      eglSwapInterval(_glfw.egl.display, interval);
  }
  
  static int extensionSupportedEGL(const char* extension)
  {
      const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
      if (extensions)
      {
          if (_glfwStringInExtensionString(extension, extensions))
              return GLFW_TRUE;
      }
  
      return GLFW_FALSE;
  }
  
  static GLFWglproc getProcAddressEGL(const char* procname)
  {
      _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
  
      if (window->context.egl.client)
      {
          GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
                                                     procname);
          if (proc)
              return proc;
      }
  
      return eglGetProcAddress(procname);
  }
  
  static void destroyContextEGL(_GLFWwindow* window)
  {
  #if defined(_GLFW_X11)
      // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
      //       as it will make XCloseDisplay segfault
      if (window->context.client != GLFW_OPENGL_API)
  #endif // _GLFW_X11
      {
          if (window->context.egl.client)
          {
              _glfw_dlclose(window->context.egl.client);
              window->context.egl.client = NULL;
          }
      }
  
      if (window->context.egl.surface)
      {
          eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
          window->context.egl.surface = EGL_NO_SURFACE;
      }
  
      if (window->context.egl.handle)
      {
          eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
          window->context.egl.handle = EGL_NO_CONTEXT;
      }
  }
  
  
  //////////////////////////////////////////////////////////////////////////
  //////                       GLFW internal API                      //////
  //////////////////////////////////////////////////////////////////////////
  
  // Initialize EGL
  //
  GLFWbool _glfwInitEGL(void)
  {
      int i;
      const char* sonames[] =
      {
  #if defined(_GLFW_EGL_LIBRARY)
          _GLFW_EGL_LIBRARY,
  #elif defined(_GLFW_WIN32)
          "libEGL.dll",
          "EGL.dll",
  #elif defined(_GLFW_COCOA)
          "libEGL.dylib",
  #elif defined(__CYGWIN__)
          "libEGL-1.so",
  #else
          "libEGL.so.1",
  #endif
          NULL
      };
  
      if (_glfw.egl.handle)
          return GLFW_TRUE;
  
      for (i = 0;  sonames[i];  i++)
      {
          _glfw.egl.handle = _glfw_dlopen(sonames[i]);
          if (_glfw.egl.handle)
              break;
      }
  
      if (!_glfw.egl.handle)
      {
          _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
          return GLFW_FALSE;
      }
  
      _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
  
      _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
          _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
      _glfw.egl.GetConfigs = (PFN_eglGetConfigs)
          _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
      _glfw.egl.GetDisplay = (PFN_eglGetDisplay)
          _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
      _glfw.egl.GetError = (PFN_eglGetError)
          _glfw_dlsym(_glfw.egl.handle, "eglGetError");
      _glfw.egl.Initialize = (PFN_eglInitialize)
          _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
      _glfw.egl.Terminate = (PFN_eglTerminate)
          _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
      _glfw.egl.BindAPI = (PFN_eglBindAPI)
          _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
      _glfw.egl.CreateContext = (PFN_eglCreateContext)
          _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
      _glfw.egl.DestroySurface = (PFN_eglDestroySurface)
          _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
      _glfw.egl.DestroyContext = (PFN_eglDestroyContext)
          _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
      _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
          _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
      _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
          _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
      _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
          _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
      _glfw.egl.SwapInterval = (PFN_eglSwapInterval)
          _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
      _glfw.egl.QueryString = (PFN_eglQueryString)
          _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
      _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
          _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
  
      if (!_glfw.egl.GetConfigAttrib ||
          !_glfw.egl.GetConfigs ||
          !_glfw.egl.GetDisplay ||
          !_glfw.egl.GetError ||
          !_glfw.egl.Initialize ||
          !_glfw.egl.Terminate ||
          !_glfw.egl.BindAPI ||
          !_glfw.egl.CreateContext ||
          !_glfw.egl.DestroySurface ||
          !_glfw.egl.DestroyContext ||
          !_glfw.egl.CreateWindowSurface ||
          !_glfw.egl.MakeCurrent ||
          !_glfw.egl.SwapBuffers ||
          !_glfw.egl.SwapInterval ||
          !_glfw.egl.QueryString ||
          !_glfw.egl.GetProcAddress)
      {
          _glfwInputError(GLFW_PLATFORM_ERROR,
                          "EGL: Failed to load required entry points");
  
          _glfwTerminateEGL();
          return GLFW_FALSE;
      }
  
      _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
      if (_glfw.egl.display == EGL_NO_DISPLAY)
      {
          _glfwInputError(GLFW_API_UNAVAILABLE,
                          "EGL: Failed to get EGL display: %s",
                          getEGLErrorString(eglGetError()));
  
          _glfwTerminateEGL();
          return GLFW_FALSE;
      }
  
      if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
      {
          _glfwInputError(GLFW_API_UNAVAILABLE,
                          "EGL: Failed to initialize EGL: %s",
                          getEGLErrorString(eglGetError()));
  
          _glfwTerminateEGL();
          return GLFW_FALSE;
      }
  
      _glfw.egl.KHR_create_context =
          extensionSupportedEGL("EGL_KHR_create_context");
      _glfw.egl.KHR_create_context_no_error =
          extensionSupportedEGL("EGL_KHR_create_context_no_error");
      _glfw.egl.KHR_gl_colorspace =
          extensionSupportedEGL("EGL_KHR_gl_colorspace");
      _glfw.egl.KHR_get_all_proc_addresses =
          extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
      _glfw.egl.KHR_context_flush_control =
          extensionSupportedEGL("EGL_KHR_context_flush_control");
  
      return GLFW_TRUE;
  }
  
  // Terminate EGL
  //
  void _glfwTerminateEGL(void)
  {
      if (_glfw.egl.display)
      {
          eglTerminate(_glfw.egl.display);
          _glfw.egl.display = EGL_NO_DISPLAY;
      }
  
      if (_glfw.egl.handle)
      {
          _glfw_dlclose(_glfw.egl.handle);
          _glfw.egl.handle = NULL;
      }
  }
  
  #define setAttrib(a, v) \
  { \
      assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
      attribs[index++] = a; \
      attribs[index++] = v; \
  }
  
  // Create the OpenGL or OpenGL ES context
  //
  GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
                                 const _GLFWctxconfig* ctxconfig,
                                 const _GLFWfbconfig* fbconfig)
  {
      EGLint attribs[40];
      EGLConfig config;
      EGLContext share = NULL;
      int index = 0;
  
      if (!_glfw.egl.display)
      {
          _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
          return GLFW_FALSE;
      }
  
      if (ctxconfig->share)
          share = ctxconfig->share->context.egl.handle;
  
      if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
      {
          _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
                          "EGL: Failed to find a suitable EGLConfig");
          return GLFW_FALSE;
      }
  
      if (ctxconfig->client == GLFW_OPENGL_ES_API)
      {
          if (!eglBindAPI(EGL_OPENGL_ES_API))
          {
              _glfwInputError(GLFW_API_UNAVAILABLE,
                              "EGL: Failed to bind OpenGL ES: %s",
                              getEGLErrorString(eglGetError()));
              return GLFW_FALSE;
          }
      }
      else
      {
          if (!eglBindAPI(EGL_OPENGL_API))
          {
              _glfwInputError(GLFW_API_UNAVAILABLE,
                              "EGL: Failed to bind OpenGL: %s",
                              getEGLErrorString(eglGetError()));
              return GLFW_FALSE;
          }
      }
  
      if (_glfw.egl.KHR_create_context)
      {
          int mask = 0, flags = 0;
  
          if (ctxconfig->client == GLFW_OPENGL_API)
          {
              if (ctxconfig->forward)
                  flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
  
              if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
                  mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
              else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
                  mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
          }
  
          if (ctxconfig->debug)
              flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
  
          if (ctxconfig->robustness)
          {
              if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
              {
                  setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
                            EGL_NO_RESET_NOTIFICATION_KHR);
              }
              else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
              {
                  setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
                            EGL_LOSE_CONTEXT_ON_RESET_KHR);
              }
  
              flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
          }
  
          if (ctxconfig->noerror)
          {
              if (_glfw.egl.KHR_create_context_no_error)
                  setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
          }
  
          if (ctxconfig->major != 1 || ctxconfig->minor != 0)
          {
              setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
              setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
          }
  
          if (mask)
              setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
  
          if (flags)
              setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
      }
      else
      {
          if (ctxconfig->client == GLFW_OPENGL_ES_API)
              setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
      }
  
      if (_glfw.egl.KHR_context_flush_control)
      {
          if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
          {
              setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
                        EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
          }
          else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
          {
              setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
                        EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
          }
      }
  
      setAttrib(EGL_NONE, EGL_NONE);
  
      window->context.egl.handle = eglCreateContext(_glfw.egl.display,
                                                    config, share, attribs);
  
      if (window->context.egl.handle == EGL_NO_CONTEXT)
      {
          _glfwInputError(GLFW_VERSION_UNAVAILABLE,
                          "EGL: Failed to create context: %s",
                          getEGLErrorString(eglGetError()));
          return GLFW_FALSE;
      }
  
      // Set up attributes for surface creation
      {
          int index = 0;
  
          if (fbconfig->sRGB)
          {
              if (_glfw.egl.KHR_gl_colorspace)
                  setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
          }
  
          setAttrib(EGL_NONE, EGL_NONE);
      }
  
      window->context.egl.surface =
          eglCreateWindowSurface(_glfw.egl.display,
                                 config,
                                 _GLFW_EGL_NATIVE_WINDOW,
                                 attribs);
      if (window->context.egl.surface == EGL_NO_SURFACE)
      {
          _glfwInputError(GLFW_PLATFORM_ERROR,
                          "EGL: Failed to create window surface: %s",
                          getEGLErrorString(eglGetError()));
          return GLFW_FALSE;
      }
  
      window->context.egl.config = config;
  
      // Load the appropriate client library
      if (!_glfw.egl.KHR_get_all_proc_addresses)
      {
          int i;
          const char** sonames;
          const char* es1sonames[] =
          {
  #if defined(_GLFW_GLESV1_LIBRARY)
              _GLFW_GLESV1_LIBRARY,
  #elif defined(_GLFW_WIN32)
              "GLESv1_CM.dll",
              "libGLES_CM.dll",
  #elif defined(_GLFW_COCOA)
              "libGLESv1_CM.dylib",
  #else
              "libGLESv1_CM.so.1",
              "libGLES_CM.so.1",
  #endif
              NULL
          };
          const char* es2sonames[] =
          {
  #if defined(_GLFW_GLESV2_LIBRARY)
              _GLFW_GLESV2_LIBRARY,
  #elif defined(_GLFW_WIN32)
              "GLESv2.dll",
              "libGLESv2.dll",
  #elif defined(_GLFW_COCOA)
              "libGLESv2.dylib",
  #elif defined(__CYGWIN__)
              "libGLESv2-2.so",
  #else
              "libGLESv2.so.2",
  #endif
              NULL
          };
          const char* glsonames[] =
          {
  #if defined(_GLFW_OPENGL_LIBRARY)
              _GLFW_OPENGL_LIBRARY,
  #elif defined(_GLFW_WIN32)
  #elif defined(_GLFW_COCOA)
  #else
              "libGL.so.1",
  #endif
              NULL
          };
  
          if (ctxconfig->client == GLFW_OPENGL_ES_API)
          {
              if (ctxconfig->major == 1)
                  sonames = es1sonames;
              else
                  sonames = es2sonames;
          }
          else
              sonames = glsonames;
  
          for (i = 0;  sonames[i];  i++)
          {
              // HACK: Match presence of lib prefix to increase chance of finding
              //       a matching pair in the jungle that is Win32 EGL/GLES
              if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
                  continue;
  
              window->context.egl.client = _glfw_dlopen(sonames[i]);
              if (window->context.egl.client)
                  break;
          }
  
          if (!window->context.egl.client)
          {
              _glfwInputError(GLFW_API_UNAVAILABLE,
                              "EGL: Failed to load client library");
              return GLFW_FALSE;
          }
      }
  
      window->context.makeCurrent = makeContextCurrentEGL;
      window->context.swapBuffers = swapBuffersEGL;
      window->context.swapInterval = swapIntervalEGL;
      window->context.extensionSupported = extensionSupportedEGL;
      window->context.getProcAddress = getProcAddressEGL;
      window->context.destroy = destroyContextEGL;
  
      return GLFW_TRUE;
  }
  
  #undef setAttrib
  
  // Returns the Visual and depth of the chosen EGLConfig
  //
  #if defined(_GLFW_X11)
  GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
                                const _GLFWctxconfig* ctxconfig,
                                const _GLFWfbconfig* fbconfig,
                                Visual** visual, int* depth)
  {
      XVisualInfo* result;
      XVisualInfo desired;
      EGLConfig native;
      EGLint visualID = 0, count = 0;
      const long vimask = VisualScreenMask | VisualIDMask;
  
      if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
      {
          _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
                          "EGL: Failed to find a suitable EGLConfig");
          return GLFW_FALSE;
      }
  
      eglGetConfigAttrib(_glfw.egl.display, native,
                         EGL_NATIVE_VISUAL_ID, &visualID);
  
      desired.screen = _glfw.x11.screen;
      desired.visualid = visualID;
  
      result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
      if (!result)
      {
          _glfwInputError(GLFW_PLATFORM_ERROR,
                          "EGL: Failed to retrieve Visual for EGLConfig");
          return GLFW_FALSE;
      }
  
      *visual = result->visual;
      *depth = result->depth;
  
      XFree(result);
      return GLFW_TRUE;
  }
  #endif // _GLFW_X11
  
  
  //////////////////////////////////////////////////////////////////////////
  //////                        GLFW native API                       //////
  //////////////////////////////////////////////////////////////////////////
  
  GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
  {
      _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
      return _glfw.egl.display;
  }
  
  GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
  {
      _GLFWwindow* window = (_GLFWwindow*) handle;
      _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
  
      if (window->context.client == GLFW_NO_API)
      {
          _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
          return EGL_NO_CONTEXT;
      }
  
      return window->context.egl.handle;
  }
  
  GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
  {
      _GLFWwindow* window = (_GLFWwindow*) handle;
      _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
  
      if (window->context.client == GLFW_NO_API)
      {
          _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
          return EGL_NO_SURFACE;
      }
  
      return window->context.egl.surface;
  }
  
  