From aec9fae8f34079561d408c8599e7ac08a7013041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 3 Jun 2020 22:02:25 +0200 Subject: [PATCH] EGL: Add support for EGL_EXT_platform_base This adds support for EGL_EXT_platform_base and its associated X11 and Wayland extensions, allowing us to explicitly tell EGL which window system we are using. This is based on work by @linkmauve in #1691. Closes #1691. --- README.md | 1 + src/cocoa_window.m | 5 +++++ src/egl_context.c | 53 ++++++++++++++++++++++++++++++++++++++++------ src/egl_context.h | 15 +++++++++++++ src/internal.h | 1 + src/win32_window.c | 5 +++++ src/wl_window.c | 8 +++++++ src/x11_window.c | 13 +++++++++++- 8 files changed, 94 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4c7d6454..5e20a3d6 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,7 @@ information on what to include when reporting a bug. - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer macOS versions (#1442) - [NSGL] Bugfix: Workaround for swap interval on 10.14 broke on 10.12 (#1483) + - [EGL] Added platform selection via the `EGL_EXT_platform_base` extension ## Contact diff --git a/src/cocoa_window.m b/src/cocoa_window.m index ebc747c7..5ddb34c1 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1721,6 +1721,11 @@ const char* _glfwPlatformGetClipboardString(void) } // autoreleasepool } +EGLenum _glfwPlatformGetEGLPlatform(void) +{ + return 0; +} + EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) { return EGL_DEFAULT_DISPLAY; diff --git a/src/egl_context.c b/src/egl_context.c index a167f341..b9736fd1 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -303,6 +303,7 @@ static void destroyContextEGL(_GLFWwindow* window) GLFWbool _glfwInitEGL(void) { int i; + const char* extensions; const char* sonames[] = { #if defined(_GLFW_EGL_LIBRARY) @@ -395,7 +396,39 @@ GLFWbool _glfwInitEGL(void) return GLFW_FALSE; } - _glfw.egl.display = eglGetDisplay(_glfwPlatformGetEGLNativeDisplay()); + extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (extensions && eglGetError() == EGL_SUCCESS) + _glfw.egl.EXT_client_extensions = GLFW_TRUE; + + if (_glfw.egl.EXT_client_extensions) + { + _glfw.egl.EXT_platform_base = + _glfwStringInExtensionString("EGL_EXT_platform_base", extensions); + _glfw.egl.EXT_platform_x11 = + _glfwStringInExtensionString("EGL_EXT_platform_x11", extensions); + _glfw.egl.EXT_platform_wayland = + _glfwStringInExtensionString("EGL_EXT_platform_wayland", extensions); + } + + if (_glfw.egl.EXT_platform_base) + { + _glfw.egl.GetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) + eglGetProcAddress("eglGetPlatformDisplayEXT"); + _glfw.egl.CreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) + eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + } + + _glfw.egl.platform = _glfwPlatformGetEGLPlatform(); + if (_glfw.egl.platform) + { + _glfw.egl.display = + eglGetPlatformDisplayEXT(_glfw.egl.platform, + _glfwPlatformGetEGLNativeDisplay(), + NULL); + } + else + _glfw.egl.display = eglGetDisplay(_glfwPlatformGetEGLNativeDisplay()); + if (_glfw.egl.display == EGL_NO_DISPLAY) { _glfwInputError(GLFW_API_UNAVAILABLE, @@ -463,6 +496,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, EGLint attribs[40]; EGLConfig config; EGLContext share = NULL; + EGLNativeWindowType native; int index = 0; if (!_glfw.egl.display) @@ -598,11 +632,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, setAttrib(EGL_NONE, EGL_NONE); - window->context.egl.surface = - eglCreateWindowSurface(_glfw.egl.display, - config, - _glfwPlatformGetEGLNativeWindow(window), - attribs); + native = _glfwPlatformGetEGLNativeWindow(window); + if (_glfw.egl.platform) + { + window->context.egl.surface = + eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs); + } + else + { + window->context.egl.surface = + eglCreateWindowSurface(_glfw.egl.display, config, native, attribs); + } + if (window->context.egl.surface == EGL_NO_SURFACE) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/src/egl_context.h b/src/egl_context.h index 8ad0b1ba..0aca105a 100644 --- a/src/egl_context.h +++ b/src/egl_context.h @@ -90,6 +90,8 @@ #define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 #define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 +#define EGL_PLATFORM_X11_EXT 0x31d5 +#define EGL_PLATFORM_WAYLAND_EXT 0x31d8 typedef int EGLint; typedef unsigned int EGLBoolean; @@ -136,6 +138,11 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*); #define eglQueryString _glfw.egl.QueryString #define eglGetProcAddress _glfw.egl.GetProcAddress +typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*); +typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*); +#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT +#define eglCreatePlatformWindowSurfaceEXT _glfw.egl.CreatePlatformWindowSurfaceEXT + #define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl #define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl @@ -156,6 +163,7 @@ typedef struct _GLFWcontextEGL // typedef struct _GLFWlibraryEGL { + EGLenum platform; EGLDisplay display; EGLint major, minor; GLFWbool prefix; @@ -165,6 +173,10 @@ typedef struct _GLFWlibraryEGL GLFWbool KHR_gl_colorspace; GLFWbool KHR_get_all_proc_addresses; GLFWbool KHR_context_flush_control; + GLFWbool EXT_client_extensions; + GLFWbool EXT_platform_base; + GLFWbool EXT_platform_x11; + GLFWbool EXT_platform_wayland; void* handle; @@ -185,6 +197,9 @@ typedef struct _GLFWlibraryEGL PFN_eglQueryString QueryString; PFN_eglGetProcAddress GetProcAddress; + PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT; + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT; + } _GLFWlibraryEGL; diff --git a/src/internal.h b/src/internal.h index b7ed9659..ccc8ab1d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -681,6 +681,7 @@ void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEventsTimeout(double timeout); void _glfwPlatformPostEmptyEvent(void); +EGLenum _glfwPlatformGetEGLPlatform(void); EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void); EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window); diff --git a/src/win32_window.c b/src/win32_window.c index a55cb7f7..5d385b4f 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2186,6 +2186,11 @@ const char* _glfwPlatformGetClipboardString(void) return _glfw.win32.clipboardString; } +EGLenum _glfwPlatformGetEGLPlatform(void) +{ + return 0; +} + EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) { return EGL_DEFAULT_DISPLAY; diff --git a/src/wl_window.c b/src/wl_window.c index 6e0d2ed7..56db1f8e 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1684,6 +1684,14 @@ const char* _glfwPlatformGetClipboardString(void) return _glfw.wl.clipboardString; } +EGLenum _glfwPlatformGetEGLPlatform(void) +{ + if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_wayland) + return EGL_PLATFORM_WAYLAND_EXT; + else + return 0; +} + EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) { return _glfw.wl.display; diff --git a/src/x11_window.c b/src/x11_window.c index 3329a66c..494493fe 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -3048,6 +3048,14 @@ const char* _glfwPlatformGetClipboardString(void) return getSelectionString(_glfw.x11.CLIPBOARD); } +EGLenum _glfwPlatformGetEGLPlatform(void) +{ + if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_x11) + return EGL_PLATFORM_X11_EXT; + else + return 0; +} + EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) { return _glfw.x11.display; @@ -3055,7 +3063,10 @@ EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window) { - return (EGLNativeWindowType) window->x11.handle; + if (_glfw.egl.platform) + return &window->x11.handle; + else + return (EGLNativeWindowType) window->x11.handle; } void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)