github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/egl_context.c (about)

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