From fcab8f8f1a15c0dcfd33adfb0021439827b93c92 Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Thu, 15 Dec 2022 07:44:14 +0000 Subject: [PATCH] Linux: Add CMake find module for wayland + make wayland optional (#572) --- CMakeLists.txt | 8 ++++++++ cmake/FindWayland.cmake | 14 ++++++++++++++ src/CMakeLists.txt | 4 +++- src/Cafe/CMakeLists.txt | 5 +++++ src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h | 2 ++ .../HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp | 11 +++++++++-- src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 2 ++ src/gui/CMakeLists.txt | 3 +++ src/gui/canvas/VulkanCanvas.cpp | 8 ++++++-- src/gui/canvas/VulkanCanvas.h | 7 ++----- src/gui/guiWrapper.cpp | 8 ++++++-- src/gui/guiWrapper.h | 8 ++++---- 12 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 cmake/FindWayland.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 28ac8760..03cfc26f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,10 @@ if (APPLE) enable_language(OBJC OBJCXX) endif() +if (UNIX AND NOT APPLE) + option(ENABLE_WAYLAND "Build with Wayland support" ON) +endif() + option(ENABLE_OPENGL "Enables the OpenGL backend" ON) option(ENABLE_VULKAN "Enables the Vulkan backend" ON) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) @@ -114,6 +118,10 @@ endif() if (UNIX AND NOT APPLE) find_package(X11 REQUIRED) + if (ENABLE_WAYLAND) + find_package(Wayland REQUIRED) + add_compile_definitions(HAS_WAYLAND) + endif() find_package(GTK3 REQUIRED) endif() diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake new file mode 100644 index 00000000..813bcf06 --- /dev/null +++ b/cmake/FindWayland.cmake @@ -0,0 +1,14 @@ +find_package(PkgConfig) + +pkg_search_module(WAYLAND_CLIENT IMPORTED_TARGET wayland-client) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Wayland + REQUIRED_VARS + WAYLAND_CLIENT_LIBRARIES + VERSION_VAR WAYLAND_CLIENT_VERSION +) + +if (Wayland_FOUND) + add_library(Wayland::client ALIAS PkgConfig::WAYLAND_CLIENT) +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d44158e4..33a86883 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,8 +27,10 @@ elseif(UNIX) add_compile_definitions( VK_USE_PLATFORM_XLIB_KHR # legacy. Do we need to support XLIB surfaces? VK_USE_PLATFORM_XCB_KHR - VK_USE_PLATFORM_WAYLAND_KHR ) + if (ENABLE_WAYLAND) + add_compile_definitions(VK_USE_PLATFORM_WAYLAND_KHR) + endif() endif() add_compile_options(-maes) # warnings diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 61b4815e..9c671b1e 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -502,6 +502,11 @@ target_link_libraries(CemuCafe PRIVATE zstd::zstd ) +if (ENABLE_WAYLAND) + # PUBLIC because wayland-client.h is included in VulkanAPI.h + target_link_libraries(CemuCafe PUBLIC Wayland::client) +endif() + if (ENABLE_WXWIDGETS) target_link_libraries(CemuCafe PRIVATE wx::base wx::core) endif() diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h index becd1c8d..de4f1bb8 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h @@ -129,8 +129,10 @@ VKFUNC_DEVICE(vkCmdBindPipeline); #if BOOST_OS_LINUX VKFUNC_INSTANCE(vkCreateXlibSurfaceKHR); VKFUNC_INSTANCE(vkCreateXcbSurfaceKHR); +#ifdef HAS_WAYLAND VKFUNC_INSTANCE(vkCreateWaylandSurfaceKHR); #endif +#endif #if BOOST_OS_WINDOWS VKFUNC_INSTANCE(vkCreateWin32SurfaceKHR); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index b9364051..f3793ed7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -110,8 +110,10 @@ std::vector VulkanRenderer::GetDevices() auto backend = gui_getWindowInfo().window_main.backend; if(backend == WindowHandleInfo::Backend::X11) requiredExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); + #ifdef HAS_WAYLAND else if (backend == WindowHandleInfo::Backend::WAYLAND) requiredExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); + #endif #elif BOOST_OS_MACOS requiredExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); #endif @@ -1156,8 +1158,10 @@ std::vector VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo auto backend = gui_getWindowInfo().window_main.backend; if(backend == WindowHandleInfo::Backend::X11) requiredInstanceExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); + #if HAS_WAYLAND else if (backend == WindowHandleInfo::Backend::WAYLAND) requiredInstanceExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); + #endif #elif BOOST_OS_MACOS requiredInstanceExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); #endif @@ -1275,7 +1279,7 @@ VkSurfaceKHR VulkanRenderer::CreateXcbSurface(VkInstance instance, xcb_connectio return result; } - +#ifdef HAS_WAYLAND VkSurfaceKHR VulkanRenderer::CreateWaylandSurface(VkInstance instance, wl_display* display, wl_surface* surface) { VkWaylandSurfaceCreateInfoKHR sci{}; @@ -1294,7 +1298,8 @@ VkSurfaceKHR VulkanRenderer::CreateWaylandSurface(VkInstance instance, wl_displa return result; } -#endif +#endif // HAS_WAYLAND +#endif // BOOST_OS_LINUX VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo) { @@ -1303,8 +1308,10 @@ VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struc #elif BOOST_OS_LINUX if(windowInfo.backend == WindowHandleInfo::Backend::X11) return CreateXlibSurface(instance, windowInfo.xlib_display, windowInfo.xlib_window); + #ifdef HAS_WAYLAND if(windowInfo.backend == WindowHandleInfo::Backend::WAYLAND) return CreateWaylandSurface(instance, windowInfo.display, windowInfo.surface); + #endif return {}; #elif BOOST_OS_MACOS return CreateCocoaSurface(instance, windowInfo.handle); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 96ac9480..81c3801d 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -201,7 +201,9 @@ public: #if BOOST_OS_LINUX static VkSurfaceKHR CreateXlibSurface(VkInstance instance, Display* dpy, Window window); static VkSurfaceKHR CreateXcbSurface(VkInstance instance, xcb_connection_t* connection, xcb_window_t window); + #ifdef HAS_WAYLAND static VkSurfaceKHR CreateWaylandSurface(VkInstance instance, wl_display* display, wl_surface* surface); + #endif #endif static VkSurfaceKHR CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index a08891db..23d8bb5e 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -150,6 +150,9 @@ target_link_libraries(CemuGui PRIVATE if(ENABLE_WXWIDGETS AND UNIX AND NOT APPLE) # PUBLIC because gdk/gdkkeysyms.h is included in guiWrapper.h target_link_libraries(CemuGui PUBLIC GTK3::gtk) + if (ENABLE_WAYLAND) + target_link_libraries(CemuGui PRIVATE Wayland::client) + endif() endif() if(ENABLE_CUBEB) diff --git a/src/gui/canvas/VulkanCanvas.cpp b/src/gui/canvas/VulkanCanvas.cpp index 53130048..671cba43 100644 --- a/src/gui/canvas/VulkanCanvas.cpp +++ b/src/gui/canvas/VulkanCanvas.cpp @@ -2,6 +2,10 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" #include "gui/guiWrapper.h" +#if BOOST_OS_LINUX && HAS_WAYLAND +#include "gui/helpers/wxWayland.h" +#endif + #include VulkanCanvas::VulkanCanvas(wxWindow* parent, const wxSize& size, bool is_main_window) @@ -14,7 +18,7 @@ VulkanCanvas::VulkanCanvas(wxWindow* parent, const wxSize& size, bool is_main_wi { WindowHandleInfo& canvasMain = gui_getWindowInfo().canvas_main; gui_initHandleContextFromWxWidgetsWindow(canvasMain, this); - #if BOOST_OS_LINUX + #if BOOST_OS_LINUX && HAS_WAYLAND if(canvasMain.backend == WindowHandleInfo::Backend::WAYLAND) { m_subsurface = std::make_unique(this); @@ -65,7 +69,7 @@ void VulkanCanvas::OnPaint(wxPaintEvent& event) void VulkanCanvas::OnResize(wxSizeEvent& event) { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX && HAS_WAYLAND if(m_subsurface) { int32_t x,y; diff --git a/src/gui/canvas/VulkanCanvas.h b/src/gui/canvas/VulkanCanvas.h index 5d866cf0..13d03a1e 100644 --- a/src/gui/canvas/VulkanCanvas.h +++ b/src/gui/canvas/VulkanCanvas.h @@ -6,14 +6,11 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" #include -#if BOOST_OS_LINUX -#include "gui/helpers/wxWayland.h" -#endif class VulkanCanvas : public IRenderCanvas, public wxWindow { -#if BOOST_OS_LINUX - std::unique_ptr m_subsurface; +#if BOOST_OS_LINUX && HAS_WAYLAND + std::unique_ptr m_subsurface; #endif public: VulkanCanvas(wxWindow* parent, const wxSize& size, bool is_main_window); diff --git a/src/gui/guiWrapper.cpp b/src/gui/guiWrapper.cpp index 3ea04d72..1a5e999b 100644 --- a/src/gui/guiWrapper.cpp +++ b/src/gui/guiWrapper.cpp @@ -3,8 +3,10 @@ #include #include #include +#ifdef HAS_WAYLAND #include #endif +#endif #include "gui/wxgui.h" #include "gui/guiWrapper.h" @@ -219,16 +221,18 @@ void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, c cemuLog_log(LogType::Force, "Unable to get xlib display"); } } - else if(GDK_IS_WAYLAND_WINDOW(gdkWindow)) + else +#ifdef HAS_WAYLAND + if(GDK_IS_WAYLAND_WINDOW(gdkWindow)) { handleInfoOut.backend = WindowHandleInfo::Backend::WAYLAND; handleInfoOut.surface = gdk_wayland_window_get_wl_surface(gdkWindow); handleInfoOut.display = gdk_wayland_display_get_wl_display(gdkDisplay); } else +#endif { cemuLog_log(LogType::Force, "Unsuported GTK backend"); - } #else handleInfoOut.handle = wxw->GetHandle(); diff --git a/src/gui/guiWrapper.h b/src/gui/guiWrapper.h index ed9f6667..0e13596b 100644 --- a/src/gui/guiWrapper.h +++ b/src/gui/guiWrapper.h @@ -5,7 +5,6 @@ #if BOOST_OS_LINUX #include "xcb/xproto.h" #include -#include #endif #if BOOST_OS_MACOS @@ -29,9 +28,10 @@ struct WindowHandleInfo // XCB (not used by GTK so we cant retrieve these without making our own window) //xcb_connection_t* xcb_con{}; //xcb_window_t xcb_window{}; - // Wayland - wl_display* display; - wl_surface* surface; + #ifdef HAS_WAYLAND + struct wl_display* display; + struct wl_surface* surface; + #endif // HAS_WAYLAND #else void* handle; #endif