From edeaaebc7d9498938b04b2a0d64178b1296357d1 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 29 Feb 2024 20:03:40 +1000 Subject: [PATCH] OpenGLContextEGL: Fix X11+platform base combination --- src/util/opengl_context_egl.cpp | 116 ++++++++++-------------- src/util/opengl_context_egl.h | 11 ++- src/util/opengl_context_egl_wayland.cpp | 27 ++---- src/util/opengl_context_egl_wayland.h | 4 +- src/util/opengl_context_egl_x11.cpp | 15 ++- src/util/opengl_context_egl_x11.h | 3 +- 6 files changed, 80 insertions(+), 96 deletions(-) diff --git a/src/util/opengl_context_egl.cpp b/src/util/opengl_context_egl.cpp index 1ead62391..5c1037728 100644 --- a/src/util/opengl_context_egl.cpp +++ b/src/util/opengl_context_egl.cpp @@ -61,22 +61,6 @@ static bool LoadGLADEGL(EGLDisplay display, Error* error) return true; } -static std::vector EGLAttribToInt(const EGLAttrib* attribs) -{ - std::vector int_attribs; - if (attribs) - { - for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE;) - { - int_attribs.push_back(static_cast(*(attrib++))); // key - int_attribs.push_back(static_cast(*(attrib++))); // value - } - int_attribs.push_back(EGL_NONE); - int_attribs.push_back(0); - } - return int_attribs; -} - OpenGLContextEGL::OpenGLContextEGL(const WindowInfo& wi) : OpenGLContext(wi) { LoadEGL(); @@ -104,7 +88,7 @@ bool OpenGLContextEGL::Initialize(std::span versions_to_try, Erro if (!LoadGLADEGL(EGL_NO_DISPLAY, error)) return false; - m_display = GetPlatformDisplay(nullptr, error); + m_display = GetPlatformDisplay(error); if (m_display == EGL_NO_DISPLAY) return false; @@ -135,16 +119,24 @@ bool OpenGLContextEGL::Initialize(std::span versions_to_try, Erro return false; } -EGLDisplay OpenGLContextEGL::GetPlatformDisplay(const EGLAttrib* attribs, Error* error) +EGLDisplay OpenGLContextEGL::GetPlatformDisplay(Error* error) { - EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, attribs); + EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, "EGL_MESA_platform_surfaceless"); if (dpy == EGL_NO_DISPLAY) dpy = GetFallbackDisplay(error); return dpy; } -EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAttrib* attribs) +EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, void* win, Error* error) +{ + EGLSurface surface = TryCreatePlatformSurface(config, win, error); + if (!surface) + surface = CreateFallbackSurface(config, win, error); + return surface; +} + +EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const char* platform_ext) { const char* extensions_str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (!extensions_str) @@ -154,36 +146,17 @@ EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAt } EGLDisplay dpy = EGL_NO_DISPLAY; - if (std::strstr(extensions_str, "EGL_KHR_platform_base")) + if (platform_ext && std::strstr(extensions_str, platform_ext)) { - Log_DevPrint("Using EGL_KHR_platform_base."); - - PFNEGLGETPLATFORMDISPLAYPROC get_platform_display; - if (s_egl_library.GetSymbol("eglGetPlatformDisplay", &get_platform_display)) - { - dpy = get_platform_display(platform, m_wi.display_connection, attribs); - if (dpy == EGL_NO_DISPLAY) - { - const EGLint err = eglGetError(); - Log_ErrorFmt("eglGetPlatformDisplay() failed: {} (0x{:X})", err, err); - } - } - else - { - Log_WarningPrint("eglGetPlatformDisplay() was not found"); - } - } - else if (std::strstr(extensions_str, "EGL_EXT_platform_base")) - { - Log_DevPrint("Using EGL_EXT_platform_base."); + Log_DevFmt("Using EGL platform {}.", platform_ext); PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display_ext = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); if (get_platform_display_ext) { - const std::vector int_attribs = EGLAttribToInt(attribs); - dpy = get_platform_display_ext(platform, m_wi.display_connection, attribs ? int_attribs.data() : nullptr); - if (dpy == EGL_NO_DISPLAY) + dpy = get_platform_display_ext(platform, m_wi.display_connection, nullptr); + m_use_ext_platform_base = (dpy != EGL_NO_DISPLAY); + if (!m_use_ext_platform_base) { const EGLint err = eglGetError(); Log_ErrorFmt("eglGetPlatformDisplayEXT() failed: {} (0x{:X})", err, err); @@ -196,15 +169,41 @@ EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAt } else { - Log_WarningPrint("EGL_EXT_platform_base nor EGL_KHR_platform_base is supported."); + Log_WarningFmt("{} is not supported.", platform_ext); } return dpy; } +EGLSurface OpenGLContextEGL::TryCreatePlatformSurface(EGLConfig config, void* win, Error* error) +{ + EGLSurface surface = EGL_NO_SURFACE; + if (m_use_ext_platform_base) + { + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window_surface_ext = + (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + if (create_platform_window_surface_ext) + { + surface = create_platform_window_surface_ext(m_display, config, win, nullptr); + if (surface == EGL_NO_SURFACE) + { + const EGLint err = eglGetError(); + Error::SetStringFmt(error, "eglCreatePlatformWindowSurfaceEXT() failed: {} (0x{:X})", err, err); + } + } + else + { + Log_ErrorPrint("eglCreatePlatformWindowSurfaceEXT() not found"); + } + } + + return surface; +} + EGLDisplay OpenGLContextEGL::GetFallbackDisplay(Error* error) { Log_WarningPrint("Using fallback eglGetDisplay() path."); + EGLDisplay dpy = eglGetDisplay(m_wi.display_connection); if (dpy == EGL_NO_DISPLAY) { @@ -215,32 +214,11 @@ EGLDisplay OpenGLContextEGL::GetFallbackDisplay(Error* error) return dpy; } -EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error) -{ - EGLSurface surface = EGL_NO_SURFACE; - if (GLAD_EGL_VERSION_1_5) - { - surface = eglCreatePlatformWindowSurface(m_display, config, m_wi.window_handle, attribs); - if (surface == EGL_NO_SURFACE) - { - const EGLint err = eglGetError(); - Error::SetStringFmt(error, "eglCreatePlatformWindowSurface() failed: {} (0x{:X})", err, err); - } - } - if (surface == EGL_NO_SURFACE) - surface = CreateFallbackSurface(config, attribs, m_wi.window_handle, error); - - return surface; -} - -EGLSurface OpenGLContextEGL::CreateFallbackSurface(EGLConfig config, const EGLAttrib* attribs, void* win, Error* error) +EGLSurface OpenGLContextEGL::CreateFallbackSurface(EGLConfig config, void* win, Error* error) { Log_WarningPrint("Using fallback eglCreateWindowSurface() path."); - const std::vector int_attribs = EGLAttribToInt(attribs); - - EGLSurface surface = - eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)win, attribs ? int_attribs.data() : nullptr); + EGLSurface surface = eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)win, nullptr); if (surface == EGL_NO_SURFACE) { const EGLint err = eglGetError(); @@ -358,7 +336,7 @@ bool OpenGLContextEGL::CreateSurface() } Error error; - m_surface = CreatePlatformSurface(m_config, nullptr, &error); + m_surface = CreatePlatformSurface(m_config, m_wi.window_handle, &error); if (m_surface == EGL_NO_SURFACE) { Log_ErrorFmt("Failed to create platform surface: {}", error.GetDescription()); diff --git a/src/util/opengl_context_egl.h b/src/util/opengl_context_egl.h index c7b148fe9..3ba78a722 100644 --- a/src/util/opengl_context_egl.h +++ b/src/util/opengl_context_egl.h @@ -27,12 +27,13 @@ public: virtual std::unique_ptr CreateSharedContext(const WindowInfo& wi, Error* error) override; protected: - virtual EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error); - virtual EGLSurface CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error); + virtual EGLDisplay GetPlatformDisplay(Error* error); + virtual EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error); - EGLDisplay TryGetPlatformDisplay(EGLenum platform, const EGLAttrib* attribs); + EGLDisplay TryGetPlatformDisplay(EGLenum platform, const char* platform_ext); + EGLSurface TryCreatePlatformSurface(EGLConfig config, void* window, Error* error); EGLDisplay GetFallbackDisplay(Error* error); - EGLSurface CreateFallbackSurface(EGLConfig config, const EGLAttrib* attribs, void* window, Error* error); + EGLSurface CreateFallbackSurface(EGLConfig config, void* window, Error* error); bool Initialize(std::span versions_to_try, Error* error); bool CreateContext(const Version& version, EGLContext share_context); @@ -49,4 +50,6 @@ protected: EGLContext m_context = EGL_NO_CONTEXT; EGLConfig m_config = {}; + + bool m_use_ext_platform_base = false; }; diff --git a/src/util/opengl_context_egl_wayland.cpp b/src/util/opengl_context_egl_wayland.cpp index 54d71038e..51834335b 100644 --- a/src/util/opengl_context_egl_wayland.cpp +++ b/src/util/opengl_context_egl_wayland.cpp @@ -50,16 +50,16 @@ void OpenGLContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surfa OpenGLContextEGL::ResizeSurface(new_surface_width, new_surface_height); } -EGLDisplay OpenGLContextEGLWayland::GetPlatformDisplay(const EGLAttrib* attribs, Error* error) +EGLDisplay OpenGLContextEGLWayland::GetPlatformDisplay(Error* error) { - EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, attribs); + EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, "EGL_EXT_platform_wayland"); if (dpy == EGL_NO_DISPLAY) dpy = GetFallbackDisplay(error); return dpy; } -EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error) +EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, void* win, Error* error) { if (m_wl_window) { @@ -67,32 +67,23 @@ EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, cons m_wl_window = nullptr; } - m_wl_window = - m_wl_egl_window_create(static_cast(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height); + m_wl_window = m_wl_egl_window_create(static_cast(win), m_wi.surface_width, m_wi.surface_height); if (!m_wl_window) { Error::SetStringView(error, "wl_egl_window_create() failed"); return EGL_NO_SURFACE; } - EGLSurface surface = EGL_NO_SURFACE; - if (GLAD_EGL_VERSION_1_5) + EGLSurface surface = TryCreatePlatformSurface(config, m_wl_window, error); + if (surface == EGL_NO_SURFACE) { - surface = eglCreatePlatformWindowSurface(m_display, config, m_wl_window, attribs); + surface = CreateFallbackSurface(config, m_wl_window, error); if (surface == EGL_NO_SURFACE) { - const EGLint err = eglGetError(); - Error::SetStringFmt(error, "eglCreatePlatformWindowSurface() for Wayland failed: {} (0x{:X})", err, err); + m_wl_egl_window_destroy(m_wl_window); + m_wl_window = nullptr; } } - if (surface == EGL_NO_SURFACE) - surface = CreateFallbackSurface(config, attribs, m_wl_window, error); - - if (surface == EGL_NO_SURFACE) - { - m_wl_egl_window_destroy(m_wl_window); - m_wl_window = nullptr; - } return surface; } diff --git a/src/util/opengl_context_egl_wayland.h b/src/util/opengl_context_egl_wayland.h index 822cff494..f5a8cff8f 100644 --- a/src/util/opengl_context_egl_wayland.h +++ b/src/util/opengl_context_egl_wayland.h @@ -20,8 +20,8 @@ public: void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; protected: - EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error) override; - EGLSurface CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error) override; + EGLDisplay GetPlatformDisplay(Error* error) override; + EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error) override; private: bool LoadModule(Error* error); diff --git a/src/util/opengl_context_egl_x11.cpp b/src/util/opengl_context_egl_x11.cpp index 9ea15401d..af608acac 100644 --- a/src/util/opengl_context_egl_x11.cpp +++ b/src/util/opengl_context_egl_x11.cpp @@ -32,11 +32,22 @@ std::unique_ptr OpenGLContextEGLX11::CreateSharedContext(const Wi return context; } -EGLDisplay OpenGLContextEGLX11::GetPlatformDisplay(const EGLAttrib* attribs, Error* error) +EGLDisplay OpenGLContextEGLX11::GetPlatformDisplay(Error* error) { - EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_X11_KHR, attribs); + EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_X11_KHR, "EGL_EXT_platform_x11"); if (dpy == EGL_NO_DISPLAY) dpy = GetFallbackDisplay(error); return dpy; } + +EGLSurface OpenGLContextEGLX11::CreatePlatformSurface(EGLConfig config, void* win, Error* error) +{ + // This is hideous.. the EXT version requires a pointer to the window, whereas the base + // version requires the window itself, casted to void*... + EGLSurface surface = TryCreatePlatformSurface(config, &win, error); + if (surface == EGL_NO_SURFACE) + surface = CreateFallbackSurface(config, win, error); + + return surface; +} \ No newline at end of file diff --git a/src/util/opengl_context_egl_x11.h b/src/util/opengl_context_egl_x11.h index e0af7e081..9337a626d 100644 --- a/src/util/opengl_context_egl_x11.h +++ b/src/util/opengl_context_egl_x11.h @@ -17,5 +17,6 @@ public: std::unique_ptr CreateSharedContext(const WindowInfo& wi, Error* error) override; protected: - EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error) override; + EGLDisplay GetPlatformDisplay(Error* error) override; + EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error) override; };