diff --git a/README.md b/README.md index e514ced3..825329ca 100644 --- a/README.md +++ b/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 diff --git a/src/egl_context.c b/src/egl_context.c index 06deb76f..8dbe3caa 100644 --- a/src/egl_context.c +++ b/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) diff --git a/src/internal.h b/src/internal.h index e36c4455..ad59efb5 100644 --- a/src/internal.h +++ b/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; diff --git a/src/null_window.c b/src/null_window.c index f31489b0..f0e1dcc9 100644 --- a/src/null_window.c +++ b/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)