Преглед на файлове

Null: Add limited EGL context creation on Mesa

This provides very limited support for context creation via EGL on the
Null platform.  It supports Unix-like systems with a version of Mesa
that provides EGL_MESA_platform_surfaceless.

Even then, the actual framebuffer provided is not resized along with the
'window'.  That will hopefully change once context and framebuffer
creation are separated, but this commit should at least allow more
applications than before to run on the Null platform.
Camilla Löwy преди 1 година
родител
ревизия
738dd6ff1d
променени са 4 файла, в които са добавени 47 реда и са изтрити 10 реда
  1. 1 0
      README.md
  2. 33 8
      src/egl_context.c
  3. 8 0
      src/internal.h
  4. 5 2
      src/null_window.c

+ 1 - 0
README.md

@@ -125,6 +125,7 @@ information on what to include when reporting a bug.
    the limit of the mouse button tokens to be reported (#2423)
  - [Wayland] Bugfix: The fractional scaling related objects were not destroyed
  - [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
+ - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
 
 
 ## Contact

+ 33 - 8
src/egl_context.c

@@ -92,7 +92,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
     EGLConfig* nativeConfigs;
     _GLFWfbconfig* usableConfigs;
     const _GLFWfbconfig* closest;
-    int i, nativeCount, usableCount, apiBit;
+    int i, nativeCount, usableCount, apiBit, surfaceTypeBit;
     GLFWbool wrongApiAvailable = GLFW_FALSE;
 
     if (ctxconfig->client == GLFW_OPENGL_ES_API)
@@ -105,6 +105,11 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
     else
         apiBit = EGL_OPENGL_BIT;
 
+    if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
+        surfaceTypeBit = EGL_PBUFFER_BIT;
+    else
+        surfaceTypeBit = EGL_WINDOW_BIT;
+
     if (fbconfig->stereo)
     {
         _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
@@ -133,8 +138,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
         if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
             continue;
 
-        // Only consider window EGLConfigs
-        if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
+        if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & surfaceTypeBit))
             continue;
 
 #if defined(_GLFW_X11)
@@ -420,6 +424,8 @@ GLFWbool _glfwInitEGL(void)
         _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext");
     _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
         _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface");
+    _glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface)
+        _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreatePbufferSurface");
     _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
         _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent");
     _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
@@ -442,6 +448,7 @@ GLFWbool _glfwInitEGL(void)
         !_glfw.egl.DestroySurface ||
         !_glfw.egl.DestroyContext ||
         !_glfw.egl.CreateWindowSurface ||
+        !_glfw.egl.CreatePbufferSurface ||
         !_glfw.egl.MakeCurrent ||
         !_glfw.egl.SwapBuffers ||
         !_glfw.egl.SwapInterval ||
@@ -477,6 +484,8 @@ GLFWbool _glfwInitEGL(void)
             _glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions);
         _glfw.egl.ANGLE_platform_angle_metal =
             _glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions);
+        _glfw.egl.MESA_platform_surfaceless =
+            _glfwStringInExtensionString("EGL_MESA_platform_surfaceless", extensions);
     }
 
     if (_glfw.egl.EXT_platform_base)
@@ -708,20 +717,36 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
             SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
     }
 
+    if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
+    {
+        int width, height;
+        _glfw.platform.getFramebufferSize(window, &width, &height);
+
+        SET_ATTRIB(EGL_WIDTH, width);
+        SET_ATTRIB(EGL_HEIGHT, height);
+    }
+
     SET_ATTRIB(EGL_NONE, EGL_NONE);
 
     native = _glfw.platform.getEGLNativeWindow(window);
-    // HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT
-    //       despite reporting EGL_EXT_platform_base
-    if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE)
+    if (!_glfw.egl.platform || _glfw.egl.platform == EGL_PLATFORM_ANGLE_ANGLE)
     {
+        // HACK: Also use non-platform function for ANGLE, as it does not
+        //       implement eglCreatePlatformWindowSurfaceEXT despite reporting
+        //       support for EGL_EXT_platform_base
         window->context.egl.surface =
-            eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs);
+            eglCreateWindowSurface(_glfw.egl.display, config, native, attribs);
+    }
+    else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
+    {
+        // HACK: Use a pbuffer surface as the default framebuffer
+        window->context.egl.surface =
+            eglCreatePbufferSurface(_glfw.egl.display, config, attribs);
     }
     else
     {
         window->context.egl.surface =
-            eglCreateWindowSurface(_glfw.egl.display, config, native, attribs);
+            eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs);
     }
 
     if (window->context.egl.surface == EGL_NO_SURFACE)

+ 8 - 0
src/internal.h

@@ -150,6 +150,9 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
 #define EGL_NO_DISPLAY ((EGLDisplay) 0)
 #define EGL_NO_CONTEXT ((EGLContext) 0)
 #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
+#define EGL_PBUFFER_BIT 0x0001
+#define EGL_WIDTH 0x3057
+#define EGL_HEIGHT 0x3056
 
 #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
 #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
@@ -181,6 +184,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
 #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
 #define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489
 #define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f
+#define EGL_PLATFORM_SURFACELESS_MESA 0x31dd
 
 typedef int EGLint;
 typedef unsigned int EGLBoolean;
@@ -205,6 +209,7 @@ typedef EGLContext (APIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLCon
 typedef EGLBoolean (APIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
 typedef EGLBoolean (APIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
 typedef EGLSurface (APIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
+typedef EGLSurface (APIENTRY * PFN_eglCreatePbufferSurface)(EGLDisplay,EGLContext,const EGLint*);
 typedef EGLBoolean (APIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
 typedef EGLBoolean (APIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
 typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
@@ -221,6 +226,7 @@ typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*);
 #define eglDestroySurface _glfw.egl.DestroySurface
 #define eglDestroyContext _glfw.egl.DestroyContext
 #define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
+#define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface
 #define eglMakeCurrent _glfw.egl.MakeCurrent
 #define eglSwapBuffers _glfw.egl.SwapBuffers
 #define eglSwapInterval _glfw.egl.SwapInterval
@@ -813,6 +819,7 @@ struct _GLFWlibrary
         GLFWbool        ANGLE_platform_angle_d3d;
         GLFWbool        ANGLE_platform_angle_vulkan;
         GLFWbool        ANGLE_platform_angle_metal;
+        GLFWbool        MESA_platform_surfaceless;
 
         void*           handle;
 
@@ -827,6 +834,7 @@ struct _GLFWlibrary
         PFN_eglDestroySurface       DestroySurface;
         PFN_eglDestroyContext       DestroyContext;
         PFN_eglCreateWindowSurface  CreateWindowSurface;
+        PFN_eglCreatePbufferSurface CreatePbufferSurface;
         PFN_eglMakeCurrent          MakeCurrent;
         PFN_eglSwapBuffers          SwapBuffers;
         PFN_eglSwapInterval         SwapInterval;

+ 5 - 2
src/null_window.c

@@ -553,12 +553,15 @@ const char* _glfwGetClipboardStringNull(void)
 
 EGLenum _glfwGetEGLPlatformNull(EGLint** attribs)
 {
-    return 0;
+    if (_glfw.egl.EXT_platform_base && _glfw.egl.MESA_platform_surfaceless)
+        return EGL_PLATFORM_SURFACELESS_MESA;
+    else
+        return 0;
 }
 
 EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void)
 {
-    return 0;
+    return EGL_DEFAULT_DISPLAY;
 }
 
 EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window)