From 84e86a0bfa2ac992b1a8b5adbb89eb7d0b85b82e Mon Sep 17 00:00:00 2001 From: Martijn Courteaux Date: Tue, 1 Oct 2024 16:52:04 +0200 Subject: [PATCH] Properly support Wayland under EGL and Vulkan. --- examples/common/entry/entry_glfw.cpp | 14 ++------------ examples/common/entry/entry_sdl.cpp | 15 +-------------- examples/common/example-glue.cpp | 2 ++ src/glcontext_egl.cpp | 21 +++++++++++++++++++++ src/glcontext_egl.h | 7 +++++++ src/renderer_vk.cpp | 2 +- 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/examples/common/entry/entry_glfw.cpp b/examples/common/entry/entry_glfw.cpp index 578d9bdd88..2a4d277166 100644 --- a/examples/common/entry/entry_glfw.cpp +++ b/examples/common/entry/entry_glfw.cpp @@ -46,18 +46,8 @@ namespace entry { # if BX_PLATFORM_LINUX # if ENTRY_CONFIG_USE_WAYLAND - wl_egl_window *win_impl = (wl_egl_window*)glfwGetWindowUserPointer(_window); - if(!win_impl) - { - int width, height; - glfwGetWindowSize(_window, &width, &height); - struct wl_surface* surface = (struct wl_surface*)glfwGetWaylandWindow(_window); - if(!surface) - return nullptr; - win_impl = wl_egl_window_create(surface, width, height); - glfwSetWindowUserPointer(_window, (void*)(uintptr_t)win_impl); - } - return (void*)(uintptr_t)win_impl; + struct wl_surface* surface = (struct wl_surface*)glfwGetWaylandWindow(_window); + return (void*)surface; # else return (void*)(uintptr_t)glfwGetX11Window(_window); # endif diff --git a/examples/common/entry/entry_sdl.cpp b/examples/common/entry/entry_sdl.cpp index d185dd2c8d..c37468e107 100644 --- a/examples/common/entry/entry_sdl.cpp +++ b/examples/common/entry/entry_sdl.cpp @@ -51,20 +51,7 @@ namespace entry # if BX_PLATFORM_LINUX # if ENTRY_CONFIG_USE_WAYLAND if (wmi.subsystem == SDL_SYSWM_WAYLAND) - { - wl_egl_window *win_impl = (wl_egl_window*)SDL_GetWindowData(_window, "wl_egl_window"); - if(!win_impl) - { - int width, height; - SDL_GetWindowSize(_window, &width, &height); - struct wl_surface* surface = wmi.info.wl.surface; - if(!surface) - return nullptr; - win_impl = wl_egl_window_create(surface, width, height); - SDL_SetWindowData(_window, "wl_egl_window", win_impl); - } - return (void*)(uintptr_t)win_impl; - } + return (void*)wmi.info.wl.surface; else # endif // ENTRY_CONFIG_USE_WAYLAND return (void*)wmi.info.x11.window; diff --git a/examples/common/example-glue.cpp b/examples/common/example-glue.cpp index ba20862ffd..a0539bcd02 100644 --- a/examples/common/example-glue.cpp +++ b/examples/common/example-glue.cpp @@ -290,6 +290,8 @@ void showExampleDialog(entry::AppI* _app, const char* _errorText) } } } +#else + ImGui::Text("Renderer: %s", bgfx::getRendererName(bgfx::getRendererType())); #endif // 0 const bgfx::Stats* stats = bgfx::getStats(); diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index 1467e287a0..cf0777b643 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -27,6 +27,10 @@ # define EGL_CHECK(_call) _call #endif // BGFX_CONFIG_DEBUG +#if defined(WL_EGL_PLATFORM) +# include +#endif + namespace bgfx { namespace gl { #ifndef EGL_CONTEXT_FLAG_NO_ERROR_BIT_KHR @@ -329,6 +333,14 @@ EGL_IMPORT vc_dispmanx_update_submit_sync(dispmanUpdate); # endif // BX_PLATFORM_ANDROID +# if BX_PLATFORM_LINUX && defined(WL_EGL_PLATFORM) + if (g_platformData.type == NativeWindowHandleType::Wayland) { + // A wl_surface needs to be first wrapped in a wl_egl_window + // before it can be used to create the EGLSurface. + m_egl_window = wl_egl_window_create((wl_surface*)nwh, _width, _height); + nwh = m_egl_window; + } +# endif if (headless) { EGLint pbAttribs[] = @@ -430,6 +442,11 @@ EGL_IMPORT EGL_CHECK(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) ); EGL_CHECK(eglDestroyContext(m_display, m_context) ); EGL_CHECK(eglDestroySurface(m_display, m_surface) ); +# if BX_PLATFORM_LINUX && defined(WL_EGL_PLATFORM) + if (m_egl_window) { + wl_egl_window_destroy(m_egl_window); + } +# endif EGL_CHECK(eglTerminate(m_display) ); m_context = NULL; } @@ -461,6 +478,10 @@ EGL_IMPORT } # elif BX_PLATFORM_EMSCRIPTEN EMSCRIPTEN_CHECK(emscripten_set_canvas_element_size(HTML5_TARGET_CANVAS_SELECTOR, _width, _height) ); +# elif BX_PLATFORM_LINUX && defined(WL_EGL_PLATFORM) + if (NULL != m_egl_window) { + wl_egl_window_resize(m_egl_window, _width, _height, 0, 0); + } # else BX_UNUSED(_width, _height); # endif // BX_PLATFORM_* diff --git a/src/glcontext_egl.h b/src/glcontext_egl.h index 9648f9ed07..aedb3ecdc4 100644 --- a/src/glcontext_egl.h +++ b/src/glcontext_egl.h @@ -11,6 +11,7 @@ #include #include + // EGL pulls X11 crap... #if defined(None) # undef None @@ -35,6 +36,9 @@ namespace bgfx { namespace gl , m_context(NULL) , m_display(NULL) , m_surface(NULL) +#if BX_PLATFORM_LINUX && defined(WL_EGL_PLATFORM) + , m_egl_window(NULL) +#endif , m_msaaContext(false) { } @@ -62,6 +66,9 @@ namespace bgfx { namespace gl EGLContext m_context; EGLDisplay m_display; EGLSurface m_surface; +#if BX_PLATFORM_LINUX && defined(WL_EGL_PLATFORM) + struct wl_egl_window *m_egl_window; +#endif // true when MSAA is handled by the context instead of using MSAA FBO bool m_msaaContext; }; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index b36f3be3a1..c94a818445 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -6940,7 +6940,7 @@ VK_DESTROY sci.pNext = NULL; sci.flags = 0; sci.display = (wl_display*)g_platformData.ndt; - sci.surface = (wl_surface*)((wl_egl_window*)m_nwh)->surface; + sci.surface = (wl_surface*)m_nwh; result = vkCreateWaylandSurfaceKHR(instance, &sci, allocatorCb, &m_surface); } else