From be2e5acd46846b1134448079f4ba1e9692ada7e8 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Thu, 7 Dec 2023 23:57:02 -0500 Subject: [PATCH 1/6] [wsi] Add init/quit functions, integrate them into DxvkInstance. This is preparation for loading/unloading WSI backends at runtime, which will be in an upcoming commit. --- src/dxvk/dxvk_instance.cpp | 5 +++++ src/wsi/meson.build | 1 + src/wsi/wsi_platform.cpp | 11 +++++++++++ src/wsi/wsi_platform.h | 7 +++++++ 4 files changed, 24 insertions(+) create mode 100644 src/wsi/wsi_platform.cpp diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index e86896d8..12785183 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -4,6 +4,7 @@ #include "dxvk_openvr.h" #include "dxvk_openxr.h" #include "dxvk_platform_exts.h" +#include "../wsi/wsi_platform.h" #include #include @@ -20,6 +21,8 @@ namespace dxvk { Logger::info(str::format("Game: ", env::getExeName())); Logger::info(str::format("DXVK: ", DXVK_VERSION)); + wsi::init(); + m_config = Config::getUserConfig(); m_config.merge(Config::getAppConfig(env::getExePath())); m_config.logOptions(); @@ -64,6 +67,8 @@ namespace dxvk { DxvkInstance::~DxvkInstance() { if (m_messenger) m_vki->vkDestroyDebugUtilsMessengerEXT(m_vki->instance(), m_messenger, nullptr); + + wsi::quit(); } diff --git a/src/wsi/meson.build b/src/wsi/meson.build index 27603cea..372ae037 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -1,5 +1,6 @@ wsi_common_src = [ 'wsi_edid.cpp', + 'wsi_platform.cpp', ] wsi_win32_src = [ diff --git a/src/wsi/wsi_platform.cpp b/src/wsi/wsi_platform.cpp new file mode 100644 index 00000000..56cd6c45 --- /dev/null +++ b/src/wsi/wsi_platform.cpp @@ -0,0 +1,11 @@ +#include "wsi_platform.h" + +namespace dxvk::wsi { + + void init() { + } + + void quit() { + } + +} diff --git a/src/wsi/wsi_platform.h b/src/wsi/wsi_platform.h index 38b5c5aa..0c94a3fa 100644 --- a/src/wsi/wsi_platform.h +++ b/src/wsi/wsi_platform.h @@ -7,3 +7,10 @@ #elif defined(DXVK_WSI_GLFW) #include "glfw/wsi_platform_glfw.h" #endif + +namespace dxvk::wsi { + + void init(); + void quit(); + +} From 0afcde05470fe95b6afde1ed28700f4dc1079291 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 8 Dec 2023 00:09:56 -0500 Subject: [PATCH 2/6] [dxvk] Move getInstanceExtensions platform logic to wsi. This ensures that all of the WSI backend logic is in one place rather than two. --- ..._win32_exts.cpp => dxvk_platform_exts.cpp} | 12 +++-- src/dxvk/meson.build | 15 +----- src/dxvk/platform/dxvk_glfw_exts.cpp | 49 ------------------ src/dxvk/platform/dxvk_sdl2_exts.cpp | 50 ------------------- src/wsi/glfw/wsi_platform_glfw.cpp | 25 ++++++++++ src/wsi/meson.build | 3 ++ src/wsi/sdl2/wsi_platform_sdl2.cpp | 23 +++++++++ src/wsi/win32/wsi_platform_win32.cpp | 9 ++++ src/wsi/wsi_platform.h | 3 ++ 9 files changed, 72 insertions(+), 117 deletions(-) rename src/dxvk/{platform/dxvk_win32_exts.cpp => dxvk_platform_exts.cpp} (67%) delete mode 100644 src/dxvk/platform/dxvk_glfw_exts.cpp delete mode 100644 src/dxvk/platform/dxvk_sdl2_exts.cpp create mode 100644 src/wsi/glfw/wsi_platform_glfw.cpp create mode 100644 src/wsi/sdl2/wsi_platform_sdl2.cpp create mode 100644 src/wsi/win32/wsi_platform_win32.cpp diff --git a/src/dxvk/platform/dxvk_win32_exts.cpp b/src/dxvk/dxvk_platform_exts.cpp similarity index 67% rename from src/dxvk/platform/dxvk_win32_exts.cpp rename to src/dxvk/dxvk_platform_exts.cpp index 25c81cc5..a1a7adea 100644 --- a/src/dxvk/platform/dxvk_win32_exts.cpp +++ b/src/dxvk/dxvk_platform_exts.cpp @@ -1,17 +1,21 @@ -#include "../dxvk_platform_exts.h" +#include "dxvk_platform_exts.h" +#include "../wsi/wsi_platform.h" namespace dxvk { DxvkPlatformExts DxvkPlatformExts::s_instance; std::string_view DxvkPlatformExts::getName() { - return "Win32 WSI"; + return "Platform WSI"; } DxvkNameSet DxvkPlatformExts::getInstanceExtensions() { + std::vector extensionNames = wsi::getInstanceExtensions(); + DxvkNameSet names; - names.add(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); + for (const char* name : extensionNames) + names.add(name); return names; } @@ -33,4 +37,4 @@ namespace dxvk { } -} \ No newline at end of file +} diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index c8fa9bda..78ff2ecf 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -89,6 +89,7 @@ dxvk_src = [ 'dxvk_options.cpp', 'dxvk_pipelayout.cpp', 'dxvk_pipemanager.cpp', + 'dxvk_platform_exts.cpp', 'dxvk_presenter.cpp', 'dxvk_queue.cpp', 'dxvk_resource.cpp', @@ -117,20 +118,6 @@ if platform == 'windows' ] endif -if dxvk_wsi == 'win32' - dxvk_src += [ - 'platform/dxvk_win32_exts.cpp' - ] -elif dxvk_wsi == 'sdl2' - dxvk_src += [ - 'platform/dxvk_sdl2_exts.cpp' - ] -elif dxvk_wsi == 'glfw' - dxvk_src += [ - 'platform/dxvk_glfw_exts.cpp' - ] -endif - dxvk_extra_deps = [ dependency('threads') ] if platform == 'linux' dxvk_extra_deps += [ cpp.find_library('dl', required: false) ] diff --git a/src/dxvk/platform/dxvk_glfw_exts.cpp b/src/dxvk/platform/dxvk_glfw_exts.cpp deleted file mode 100644 index f5cfee88..00000000 --- a/src/dxvk/platform/dxvk_glfw_exts.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "../dxvk_platform_exts.h" - -#include "../../vulkan/vulkan_loader.h" -#include - -namespace dxvk { - - DxvkPlatformExts DxvkPlatformExts::s_instance; - - std::string_view DxvkPlatformExts::getName() { - return "GLFW WSI"; - } - - DxvkNameSet DxvkPlatformExts::getInstanceExtensions() { - if (!glfwVulkanSupported()) - throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!")); - - uint32_t extensionCount = 0; - const char** extensionArray = glfwGetRequiredInstanceExtensions(&extensionCount); - - if (extensionCount == 0) - throw DxvkError(str::format("GLFW WSI: Failed to get required instance extensions")); - - DxvkNameSet names; - for (uint32_t i = 0; i < extensionCount; ++i) { - names.add(extensionArray[i]); - } - - return names; - } - - - DxvkNameSet DxvkPlatformExts::getDeviceExtensions( - uint32_t adapterId) { - return DxvkNameSet(); - } - - - void DxvkPlatformExts::initInstanceExtensions() { - //Nothing needs to be done here on GLFW - } - - - void DxvkPlatformExts::initDeviceExtensions( - const DxvkInstance* instance) { - //Nothing needs to be done here on GLFW - } - -} \ No newline at end of file diff --git a/src/dxvk/platform/dxvk_sdl2_exts.cpp b/src/dxvk/platform/dxvk_sdl2_exts.cpp deleted file mode 100644 index 13583aa7..00000000 --- a/src/dxvk/platform/dxvk_sdl2_exts.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "../dxvk_platform_exts.h" - -#include -#include - -namespace dxvk { - - DxvkPlatformExts DxvkPlatformExts::s_instance; - - std::string_view DxvkPlatformExts::getName() { - return "SDL2 WSI"; - } - - - DxvkNameSet DxvkPlatformExts::getInstanceExtensions() { - SDL_Vulkan_LoadLibrary(nullptr); - - uint32_t extensionCount = 0; - if (!SDL_Vulkan_GetInstanceExtensions(nullptr, &extensionCount, nullptr)) - throw DxvkError(str::format("SDL2 WSI: Failed to get instance extension count. ", SDL_GetError())); - - auto extensionNames = std::vector(extensionCount); - if (!SDL_Vulkan_GetInstanceExtensions(nullptr, &extensionCount, extensionNames.data())) - throw DxvkError(str::format("SDL2 WSI: Failed to get instance extensions. ", SDL_GetError())); - - DxvkNameSet names; - for (const char* name : extensionNames) - names.add(name); - - return names; - } - - - DxvkNameSet DxvkPlatformExts::getDeviceExtensions( - uint32_t adapterId) { - return DxvkNameSet(); - } - - - void DxvkPlatformExts::initInstanceExtensions() { - - } - - - void DxvkPlatformExts::initDeviceExtensions( - const DxvkInstance* instance) { - - } - -} diff --git a/src/wsi/glfw/wsi_platform_glfw.cpp b/src/wsi/glfw/wsi_platform_glfw.cpp new file mode 100644 index 00000000..d180f597 --- /dev/null +++ b/src/wsi/glfw/wsi_platform_glfw.cpp @@ -0,0 +1,25 @@ +#include "wsi_platform_glfw.h" +#include "../../util/util_error.h" +#include "../../util/util_string.h" + +namespace dxvk::wsi { + + std::vector getInstanceExtensions() { + if (!glfwVulkanSupported()) + throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!")); + + uint32_t extensionCount = 0; + const char** extensionArray = glfwGetRequiredInstanceExtensions(&extensionCount); + + if (extensionCount == 0) + throw DxvkError(str::format("GLFW WSI: Failed to get required instance extensions")); + + std::vector names(extensionCount); + for (uint32_t i = 0; i < extensionCount; ++i) { + names.push_back(extensionArray[i]); + } + + return names; + } + +} diff --git a/src/wsi/meson.build b/src/wsi/meson.build index 372ae037..1cabcf2f 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -5,16 +5,19 @@ wsi_common_src = [ wsi_win32_src = [ 'win32/wsi_monitor_win32.cpp', + 'win32/wsi_platform_win32.cpp', 'win32/wsi_window_win32.cpp', ] wsi_sdl2_src = [ 'sdl2/wsi_monitor_sdl2.cpp', + 'sdl2/wsi_platform_sdl2.cpp', 'sdl2/wsi_window_sdl2.cpp', ] wsi_glfw_src = [ 'glfw/wsi_monitor_glfw.cpp', + 'glfw/wsi_platform_glfw.cpp', 'glfw/wsi_window_glfw.cpp', ] diff --git a/src/wsi/sdl2/wsi_platform_sdl2.cpp b/src/wsi/sdl2/wsi_platform_sdl2.cpp new file mode 100644 index 00000000..cc8ac22b --- /dev/null +++ b/src/wsi/sdl2/wsi_platform_sdl2.cpp @@ -0,0 +1,23 @@ +#include "wsi_platform_sdl2.h" +#include "../../util/util_error.h" +#include "../../util/util_string.h" + +#include + +namespace dxvk::wsi { + + std::vector getInstanceExtensions() { + SDL_Vulkan_LoadLibrary(nullptr); + + uint32_t extensionCount = 0; + if (!SDL_Vulkan_GetInstanceExtensions(nullptr, &extensionCount, nullptr)) + throw DxvkError(str::format("SDL2 WSI: Failed to get instance extension count. ", SDL_GetError())); + + auto extensionNames = std::vector(extensionCount); + if (!SDL_Vulkan_GetInstanceExtensions(nullptr, &extensionCount, extensionNames.data())) + throw DxvkError(str::format("SDL2 WSI: Failed to get instance extensions. ", SDL_GetError())); + + return extensionNames; + } + +} diff --git a/src/wsi/win32/wsi_platform_win32.cpp b/src/wsi/win32/wsi_platform_win32.cpp new file mode 100644 index 00000000..8b16de56 --- /dev/null +++ b/src/wsi/win32/wsi_platform_win32.cpp @@ -0,0 +1,9 @@ +#include "wsi_platform_win32.h" + +namespace dxvk::wsi { + + std::vector getInstanceExtensions() { + return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; + } + +} diff --git a/src/wsi/wsi_platform.h b/src/wsi/wsi_platform.h index 0c94a3fa..7ccecc27 100644 --- a/src/wsi/wsi_platform.h +++ b/src/wsi/wsi_platform.h @@ -8,9 +8,12 @@ #include "glfw/wsi_platform_glfw.h" #endif +#include + namespace dxvk::wsi { void init(); void quit(); + std::vector getInstanceExtensions(); } From a741e2cd4a5198d952a5ff97ea7e3b9a537d779a Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 8 Dec 2023 00:45:46 -0500 Subject: [PATCH 3/6] [wsi] Refactor the WSI backends to be implementations of a WsiDriver interface. Rather than directly calling functions, the API now calls shared functions that call into a WsiDriver instance, which is allocated and implemented by the backend. Functionally this should be the same, it just has the extra allocation for the function table. This prepares the WSI library for supporting multiple implementations in a single binary. --- src/wsi/glfw/wsi_monitor_glfw.cpp | 18 ++-- src/wsi/glfw/wsi_platform_glfw.cpp | 6 +- src/wsi/glfw/wsi_platform_glfw.h | 89 ++++++++++++++++-- src/wsi/glfw/wsi_window_glfw.cpp | 22 ++--- src/wsi/sdl2/wsi_monitor_sdl2.cpp | 18 ++-- src/wsi/sdl2/wsi_platform_sdl2.cpp | 6 +- src/wsi/sdl2/wsi_platform_sdl2.h | 89 ++++++++++++++++-- src/wsi/sdl2/wsi_window_sdl2.cpp | 20 ++-- src/wsi/win32/wsi_monitor_win32.cpp | 20 ++-- src/wsi/win32/wsi_platform_win32.cpp | 6 +- src/wsi/win32/wsi_platform_win32.h | 92 ++++++++++++++++-- src/wsi/win32/wsi_window_win32.cpp | 23 +++-- src/wsi/wsi_platform.cpp | 135 +++++++++++++++++++++++++++ src/wsi/wsi_platform.h | 95 +++++++++++++++++-- src/wsi/wsi_window.h | 12 ++- 15 files changed, 559 insertions(+), 92 deletions(-) diff --git a/src/wsi/glfw/wsi_monitor_glfw.cpp b/src/wsi/glfw/wsi_monitor_glfw.cpp index e450f83c..00abc89a 100644 --- a/src/wsi/glfw/wsi_monitor_glfw.cpp +++ b/src/wsi/glfw/wsi_monitor_glfw.cpp @@ -11,22 +11,22 @@ namespace dxvk::wsi { - HMONITOR getDefaultMonitor() { + HMONITOR GlfwWsiDriver::getDefaultMonitor() { return enumMonitors(0); } - HMONITOR enumMonitors(uint32_t index) { + HMONITOR GlfwWsiDriver::enumMonitors(uint32_t index) { return isDisplayValid(int32_t(index)) ? toHmonitor(index) : nullptr; } - HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { + HMONITOR GlfwWsiDriver::enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { return enumMonitors(index); } - bool getDisplayName( + bool GlfwWsiDriver::getDisplayName( HMONITOR hMonitor, WCHAR (&Name)[32]) { const int32_t displayId = fromHmonitor(hMonitor); @@ -46,7 +46,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool GlfwWsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { const int32_t displayId = fromHmonitor(hMonitor); @@ -97,7 +97,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool GlfwWsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t ModeNumber, WsiMode* pMode) { @@ -121,7 +121,7 @@ namespace dxvk::wsi { } - bool getCurrentDisplayMode( + bool GlfwWsiDriver::getCurrentDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -141,7 +141,7 @@ namespace dxvk::wsi { } - bool getDesktopDisplayMode( + bool GlfwWsiDriver::getDesktopDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -159,7 +159,7 @@ namespace dxvk::wsi { return true; } - std::vector getMonitorEdid(HMONITOR hMonitor) { + std::vector GlfwWsiDriver::getMonitorEdid(HMONITOR hMonitor) { Logger::err("getMonitorEdid not implemented on this platform."); return {}; } diff --git a/src/wsi/glfw/wsi_platform_glfw.cpp b/src/wsi/glfw/wsi_platform_glfw.cpp index d180f597..fb711aeb 100644 --- a/src/wsi/glfw/wsi_platform_glfw.cpp +++ b/src/wsi/glfw/wsi_platform_glfw.cpp @@ -4,7 +4,7 @@ namespace dxvk::wsi { - std::vector getInstanceExtensions() { + std::vector GlfwWsiDriver::getInstanceExtensions() { if (!glfwVulkanSupported()) throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!")); @@ -22,4 +22,8 @@ namespace dxvk::wsi { return names; } + WsiDriver* platformCreateWsiDriver() { + return new GlfwWsiDriver(); + } + } diff --git a/src/wsi/glfw/wsi_platform_glfw.h b/src/wsi/glfw/wsi_platform_glfw.h index 25753494..83b95c5e 100644 --- a/src/wsi/glfw/wsi_platform_glfw.h +++ b/src/wsi/glfw/wsi_platform_glfw.h @@ -3,14 +3,91 @@ #include "../../vulkan/vulkan_loader.h" #include -#include "../wsi_monitor.h" +#include "../wsi_platform.h" namespace dxvk::wsi { - /** - * \brief Impl-dependent state - */ - struct DxvkWindowState { + class GlfwWsiDriver : public WsiDriver { + public: + // Platform + virtual std::vector getInstanceExtensions(); + + // Monitor + virtual HMONITOR getDefaultMonitor(); + + virtual HMONITOR enumMonitors(uint32_t index); + + virtual HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index); + + virtual bool getDisplayName( + HMONITOR hMonitor, + WCHAR (&Name)[32]); + + virtual bool getDesktopCoordinates( + HMONITOR hMonitor, + RECT* pRect); + + virtual bool getDisplayMode( + HMONITOR hMonitor, + uint32_t modeNumber, + WsiMode* pMode); + + virtual bool getCurrentDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual bool getDesktopDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual WsiEdidData getMonitorEdid(HMONITOR hMonitor); + + // Window + + virtual void getWindowSize( + HWND hWindow, + uint32_t* pWidth, + uint32_t* pWeight); + + virtual void resizeWindow( + HWND hWindow, + DxvkWindowState* pState, + uint32_t width, + uint32_t weight); + + virtual bool setWindowMode( + HMONITOR hMonitor, + HWND hWindow, + const WsiMode& mode); + + virtual bool enterFullscreenMode( + HMONITOR hMonitor, + HWND hWindow, + DxvkWindowState* pState, + [[maybe_unused]] + bool modeSwitch); + + virtual bool leaveFullscreenMode( + HWND hWindow, + DxvkWindowState* pState, + bool restoreCoordinates); + + virtual bool restoreDisplayMode(); + + virtual HMONITOR getWindowMonitor(HWND hWindow); + + virtual bool isWindow(HWND hWindow); + + virtual void updateFullscreenWindow( + HMONITOR hMonitor, + HWND hWindow, + bool forceTopmost); + + virtual VkResult createSurface( + HWND hWindow, + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, + VkInstance instance, + VkSurfaceKHR* pSurface); }; inline bool isDisplayValid(int32_t displayId) { @@ -20,4 +97,4 @@ namespace dxvk::wsi { return displayId < displayCount && displayId >= 0; } -} \ No newline at end of file +} diff --git a/src/wsi/glfw/wsi_window_glfw.cpp b/src/wsi/glfw/wsi_window_glfw.cpp index 70031250..b23a7923 100644 --- a/src/wsi/glfw/wsi_window_glfw.cpp +++ b/src/wsi/glfw/wsi_window_glfw.cpp @@ -12,7 +12,7 @@ namespace dxvk::wsi { - void getWindowSize( + void GlfwWsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -29,7 +29,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void GlfwWsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t Width, @@ -40,7 +40,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool GlfwWsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& pMode) { @@ -67,7 +67,7 @@ namespace dxvk::wsi { return true; } - bool enterFullscreenMode( + bool GlfwWsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, @@ -89,7 +89,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool GlfwWsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -103,13 +103,13 @@ namespace dxvk::wsi { } - bool restoreDisplayMode() { + bool GlfwWsiDriver::restoreDisplayMode() { // Don't need to do anything with GLFW here. return true; } - HMONITOR getWindowMonitor(HWND hWindow) { + HMONITOR GlfwWsiDriver::getWindowMonitor(HWND hWindow) { // TODO: implement this with glfwGetWindowMonitor // (or maybe not? glfwGetWindowMonitor only seems to reference *fullscreen* windows) // GLFWwindow* window = fromHwnd(hWindow); @@ -119,19 +119,19 @@ namespace dxvk::wsi { } - bool isWindow(HWND hWindow) { + bool GlfwWsiDriver::isWindow(HWND hWindow) { GLFWwindow* window = fromHwnd(hWindow); return window != nullptr; } - void updateFullscreenWindow( + void GlfwWsiDriver::updateFullscreenWindow( HMONITOR hMonitor, HWND hWindow, bool forceTopmost) { // Don't need to do anything with GLFW here. } - VkResult createSurface( + VkResult GlfwWsiDriver::createSurface( HWND hWindow, PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, VkInstance instance, @@ -141,4 +141,4 @@ namespace dxvk::wsi { return glfwCreateWindowSurface(instance, window, nullptr, pSurface); } -} \ No newline at end of file +} diff --git a/src/wsi/sdl2/wsi_monitor_sdl2.cpp b/src/wsi/sdl2/wsi_monitor_sdl2.cpp index f0de7cd6..5903ef68 100644 --- a/src/wsi/sdl2/wsi_monitor_sdl2.cpp +++ b/src/wsi/sdl2/wsi_monitor_sdl2.cpp @@ -12,22 +12,22 @@ namespace dxvk::wsi { - HMONITOR getDefaultMonitor() { + HMONITOR Sdl2WsiDriver::getDefaultMonitor() { return enumMonitors(0); } - HMONITOR enumMonitors(uint32_t index) { + HMONITOR Sdl2WsiDriver::enumMonitors(uint32_t index) { return isDisplayValid(int32_t(index)) ? toHmonitor(index) : nullptr; } - HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { + HMONITOR Sdl2WsiDriver::enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { return enumMonitors(index); } - bool getDisplayName( + bool Sdl2WsiDriver::getDisplayName( HMONITOR hMonitor, WCHAR (&Name)[32]) { const int32_t displayId = fromHmonitor(hMonitor); @@ -47,7 +47,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool Sdl2WsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { const int32_t displayId = fromHmonitor(hMonitor); @@ -90,7 +90,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool Sdl2WsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t ModeNumber, WsiMode* pMode) { @@ -109,7 +109,7 @@ namespace dxvk::wsi { } - bool getCurrentDisplayMode( + bool Sdl2WsiDriver::getCurrentDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -129,7 +129,7 @@ namespace dxvk::wsi { } - bool getDesktopDisplayMode( + bool Sdl2WsiDriver::getDesktopDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -148,7 +148,7 @@ namespace dxvk::wsi { return true; } - std::vector getMonitorEdid(HMONITOR hMonitor) { + std::vector Sdl2WsiDriver::getMonitorEdid(HMONITOR hMonitor) { Logger::err("getMonitorEdid not implemented on this platform."); return {}; } diff --git a/src/wsi/sdl2/wsi_platform_sdl2.cpp b/src/wsi/sdl2/wsi_platform_sdl2.cpp index cc8ac22b..96ecb076 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.cpp +++ b/src/wsi/sdl2/wsi_platform_sdl2.cpp @@ -6,7 +6,7 @@ namespace dxvk::wsi { - std::vector getInstanceExtensions() { + std::vector Sdl2WsiDriver::getInstanceExtensions() { SDL_Vulkan_LoadLibrary(nullptr); uint32_t extensionCount = 0; @@ -20,4 +20,8 @@ namespace dxvk::wsi { return extensionNames; } + WsiDriver* platformCreateWsiDriver() { + return new Sdl2WsiDriver(); + } + } diff --git a/src/wsi/sdl2/wsi_platform_sdl2.h b/src/wsi/sdl2/wsi_platform_sdl2.h index 411fe8f6..845725ab 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.h +++ b/src/wsi/sdl2/wsi_platform_sdl2.h @@ -2,14 +2,91 @@ #include -#include "../wsi_monitor.h" +#include "../wsi_platform.h" namespace dxvk::wsi { - /** - * \brief Impl-dependent state - */ - struct DxvkWindowState { + class Sdl2WsiDriver : public WsiDriver { + public: + // Platform + virtual std::vector getInstanceExtensions(); + + // Monitor + virtual HMONITOR getDefaultMonitor(); + + virtual HMONITOR enumMonitors(uint32_t index); + + virtual HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index); + + virtual bool getDisplayName( + HMONITOR hMonitor, + WCHAR (&Name)[32]); + + virtual bool getDesktopCoordinates( + HMONITOR hMonitor, + RECT* pRect); + + virtual bool getDisplayMode( + HMONITOR hMonitor, + uint32_t modeNumber, + WsiMode* pMode); + + virtual bool getCurrentDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual bool getDesktopDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual WsiEdidData getMonitorEdid(HMONITOR hMonitor); + + // Window + + virtual void getWindowSize( + HWND hWindow, + uint32_t* pWidth, + uint32_t* pWeight); + + virtual void resizeWindow( + HWND hWindow, + DxvkWindowState* pState, + uint32_t width, + uint32_t weight); + + virtual bool setWindowMode( + HMONITOR hMonitor, + HWND hWindow, + const WsiMode& mode); + + virtual bool enterFullscreenMode( + HMONITOR hMonitor, + HWND hWindow, + DxvkWindowState* pState, + [[maybe_unused]] + bool modeSwitch); + + virtual bool leaveFullscreenMode( + HWND hWindow, + DxvkWindowState* pState, + bool restoreCoordinates); + + virtual bool restoreDisplayMode(); + + virtual HMONITOR getWindowMonitor(HWND hWindow); + + virtual bool isWindow(HWND hWindow); + + virtual void updateFullscreenWindow( + HMONITOR hMonitor, + HWND hWindow, + bool forceTopmost); + + virtual VkResult createSurface( + HWND hWindow, + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, + VkInstance instance, + VkSurfaceKHR* pSurface); }; inline bool isDisplayValid(int32_t displayId) { @@ -18,4 +95,4 @@ namespace dxvk::wsi { return displayId < displayCount && displayId >= 0; } -} \ No newline at end of file +} diff --git a/src/wsi/sdl2/wsi_window_sdl2.cpp b/src/wsi/sdl2/wsi_window_sdl2.cpp index 1280b6c1..5622e876 100644 --- a/src/wsi/sdl2/wsi_window_sdl2.cpp +++ b/src/wsi/sdl2/wsi_window_sdl2.cpp @@ -11,7 +11,7 @@ namespace dxvk::wsi { - void getWindowSize( + void Sdl2WsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -28,7 +28,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void Sdl2WsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t Width, @@ -39,7 +39,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool Sdl2WsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& pMode) { @@ -73,7 +73,7 @@ namespace dxvk::wsi { - bool enterFullscreenMode( + bool Sdl2WsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, @@ -99,7 +99,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool Sdl2WsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -114,13 +114,13 @@ namespace dxvk::wsi { } - bool restoreDisplayMode() { + bool Sdl2WsiDriver::restoreDisplayMode() { // Don't need to do anything with SDL2 here. return true; } - HMONITOR getWindowMonitor(HWND hWindow) { + HMONITOR Sdl2WsiDriver::getWindowMonitor(HWND hWindow) { SDL_Window* window = fromHwnd(hWindow); const int32_t displayId = SDL_GetWindowDisplayIndex(window); @@ -128,13 +128,13 @@ namespace dxvk::wsi { } - bool isWindow(HWND hWindow) { + bool Sdl2WsiDriver::isWindow(HWND hWindow) { SDL_Window* window = fromHwnd(hWindow); return window != nullptr; } - void updateFullscreenWindow( + void Sdl2WsiDriver::updateFullscreenWindow( HMONITOR hMonitor, HWND hWindow, bool forceTopmost) { @@ -142,7 +142,7 @@ namespace dxvk::wsi { } - VkResult createSurface( + VkResult Sdl2WsiDriver::createSurface( HWND hWindow, PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, VkInstance instance, diff --git a/src/wsi/win32/wsi_monitor_win32.cpp b/src/wsi/win32/wsi_monitor_win32.cpp index ae4a0ff3..b37e0902 100644 --- a/src/wsi/win32/wsi_monitor_win32.cpp +++ b/src/wsi/win32/wsi_monitor_win32.cpp @@ -1,4 +1,4 @@ -#include "../wsi_monitor.h" +#include "wsi_platform_win32.h" #include "../../util/util_string.h" #include "../../util/log/log.h" @@ -13,7 +13,7 @@ namespace dxvk::wsi { - HMONITOR getDefaultMonitor() { + HMONITOR Win32WsiDriver::getDefaultMonitor() { return ::MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY); } @@ -45,7 +45,7 @@ namespace dxvk::wsi { return FALSE; } - HMONITOR enumMonitors(uint32_t index) { + HMONITOR Win32WsiDriver::enumMonitors(uint32_t index) { MonitorEnumInfo info; info.iMonitorId = index; info.oMonitor = nullptr; @@ -58,7 +58,7 @@ namespace dxvk::wsi { return info.oMonitor; } - HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { + HMONITOR Win32WsiDriver::enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { if (!numLUIDs) return enumMonitors(index); @@ -132,7 +132,7 @@ namespace dxvk::wsi { } - bool getDisplayName( + bool Win32WsiDriver::getDisplayName( HMONITOR hMonitor, WCHAR (&Name)[32]) { // Query monitor info to get the device name @@ -150,7 +150,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool Win32WsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { ::MONITORINFOEXW monInfo; @@ -200,7 +200,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool Win32WsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t modeNumber, WsiMode* pMode) { @@ -208,14 +208,14 @@ namespace dxvk::wsi { } - bool getCurrentDisplayMode( + bool Win32WsiDriver::getCurrentDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { return retrieveDisplayMode(hMonitor, ENUM_CURRENT_SETTINGS, pMode); } - bool getDesktopDisplayMode( + bool Win32WsiDriver::getDesktopDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { return retrieveDisplayMode(hMonitor, ENUM_REGISTRY_SETTINGS, pMode); @@ -308,7 +308,7 @@ namespace dxvk::wsi { wchar_t extraChars[MAX_DEVICE_ID_LEN]; }; - WsiEdidData getMonitorEdid(HMONITOR hMonitor) { + WsiEdidData Win32WsiDriver::getMonitorEdid(HMONITOR hMonitor) { static constexpr GUID GUID_DEVINTERFACE_MONITOR = { 0xe6f07b5f, 0xee97, 0x4a90, 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7 }; static auto pfnSetupDiGetClassDevsW = reinterpret_cast (::GetProcAddress(::GetModuleHandleW(L"setupapi.dll"), "SetupDiGetClassDevsW")); static auto pfnSetupDiEnumDeviceInterfaces = reinterpret_cast (::GetProcAddress(::GetModuleHandleW(L"setupapi.dll"), "SetupDiEnumDeviceInterfaces")); diff --git a/src/wsi/win32/wsi_platform_win32.cpp b/src/wsi/win32/wsi_platform_win32.cpp index 8b16de56..ab27869a 100644 --- a/src/wsi/win32/wsi_platform_win32.cpp +++ b/src/wsi/win32/wsi_platform_win32.cpp @@ -2,8 +2,12 @@ namespace dxvk::wsi { - std::vector getInstanceExtensions() { + std::vector Win32WsiDriver::getInstanceExtensions() { return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; } + WsiDriver* platformCreateWsiDriver() { + return new Win32WsiDriver(); + } + } diff --git a/src/wsi/win32/wsi_platform_win32.h b/src/wsi/win32/wsi_platform_win32.h index d382f20a..1364baf1 100644 --- a/src/wsi/win32/wsi_platform_win32.h +++ b/src/wsi/win32/wsi_platform_win32.h @@ -2,15 +2,91 @@ #include +#include "../wsi_platform.h" + namespace dxvk::wsi { - /** - * \brief Impl-dependent state - */ - struct DxvkWindowState { - LONG style = 0; - LONG exstyle = 0; - RECT rect = { 0, 0, 0, 0 }; + class Win32WsiDriver : public WsiDriver { + public: + // Platform + virtual std::vector getInstanceExtensions(); + + // Monitor + virtual HMONITOR getDefaultMonitor(); + + virtual HMONITOR enumMonitors(uint32_t index); + + virtual HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index); + + virtual bool getDisplayName( + HMONITOR hMonitor, + WCHAR (&Name)[32]); + + virtual bool getDesktopCoordinates( + HMONITOR hMonitor, + RECT* pRect); + + virtual bool getDisplayMode( + HMONITOR hMonitor, + uint32_t modeNumber, + WsiMode* pMode); + + virtual bool getCurrentDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual bool getDesktopDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode); + + virtual WsiEdidData getMonitorEdid(HMONITOR hMonitor); + + // Window + + virtual void getWindowSize( + HWND hWindow, + uint32_t* pWidth, + uint32_t* pWeight); + + virtual void resizeWindow( + HWND hWindow, + DxvkWindowState* pState, + uint32_t width, + uint32_t weight); + + virtual bool setWindowMode( + HMONITOR hMonitor, + HWND hWindow, + const WsiMode& mode); + + virtual bool enterFullscreenMode( + HMONITOR hMonitor, + HWND hWindow, + DxvkWindowState* pState, + [[maybe_unused]] + bool modeSwitch); + + virtual bool leaveFullscreenMode( + HWND hWindow, + DxvkWindowState* pState, + bool restoreCoordinates); + + virtual bool restoreDisplayMode(); + + virtual HMONITOR getWindowMonitor(HWND hWindow); + + virtual bool isWindow(HWND hWindow); + + virtual void updateFullscreenWindow( + HMONITOR hMonitor, + HWND hWindow, + bool forceTopmost); + + virtual VkResult createSurface( + HWND hWindow, + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, + VkInstance instance, + VkSurfaceKHR* pSurface); }; -} \ No newline at end of file +} diff --git a/src/wsi/win32/wsi_window_win32.cpp b/src/wsi/win32/wsi_window_win32.cpp index 597d7478..cf446980 100644 --- a/src/wsi/win32/wsi_window_win32.cpp +++ b/src/wsi/win32/wsi_window_win32.cpp @@ -1,5 +1,4 @@ -#include "../wsi_window.h" -#include "../wsi_monitor.h" +#include "wsi_platform_win32.h" #include "../../util/util_string.h" #include "../../util/log/log.h" @@ -94,7 +93,7 @@ namespace dxvk::wsi { } - void getWindowSize( + void Win32WsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -109,7 +108,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void Win32WsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t width, @@ -130,7 +129,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool Win32WsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& mode) { @@ -163,7 +162,7 @@ namespace dxvk::wsi { } - bool enterFullscreenMode( + bool Win32WsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, @@ -196,7 +195,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool Win32WsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -225,7 +224,7 @@ namespace dxvk::wsi { } - bool restoreDisplayMode() { + bool Win32WsiDriver::restoreDisplayMode() { bool success = true; bool result = ::EnumDisplayMonitors(nullptr, nullptr, &restoreDisplayModeCallback, @@ -235,7 +234,7 @@ namespace dxvk::wsi { } - HMONITOR getWindowMonitor(HWND hWindow) { + HMONITOR Win32WsiDriver::getWindowMonitor(HWND hWindow) { RECT windowRect = { 0, 0, 0, 0 }; ::GetWindowRect(hWindow, &windowRect); @@ -248,12 +247,12 @@ namespace dxvk::wsi { } - bool isWindow(HWND hWindow) { + bool Win32WsiDriver::isWindow(HWND hWindow) { return ::IsWindow(hWindow); } - void updateFullscreenWindow( + void Win32WsiDriver::updateFullscreenWindow( HMONITOR hMonitor, HWND hWindow, bool forceTopmost) { @@ -274,7 +273,7 @@ namespace dxvk::wsi { } - VkResult createSurface( + VkResult Win32WsiDriver::createSurface( HWND hWindow, PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, VkInstance instance, diff --git a/src/wsi/wsi_platform.cpp b/src/wsi/wsi_platform.cpp index 56cd6c45..f4802025 100644 --- a/src/wsi/wsi_platform.cpp +++ b/src/wsi/wsi_platform.cpp @@ -1,11 +1,146 @@ #include "wsi_platform.h" +#include "wsi_monitor.h" +#include "wsi_window.h" +#include "../util/util_error.h" namespace dxvk::wsi { + static WsiDriver* s_driver = nullptr; + static int s_refcount = 0; void init() { + if (s_refcount++ > 0) + return; + + s_driver = platformCreateWsiDriver(); + if (s_driver == nullptr) + throw DxvkError("Failed to initialize WSI."); } void quit() { + if (s_refcount == 0) + return; + + s_refcount--; + if (s_refcount == 0) { + delete s_driver; + s_driver = nullptr; + } + } + + std::vector getInstanceExtensions() { + return s_driver->getInstanceExtensions(); + } + + void getWindowSize( + HWND hWindow, + uint32_t* pWidth, + uint32_t* pHeight) { + s_driver->getWindowSize(hWindow, pWidth, pHeight); + } + + void resizeWindow( + HWND hWindow, + DxvkWindowState* pState, + uint32_t width, + uint32_t height) { + s_driver->resizeWindow(hWindow, pState, width, height); + } + + bool setWindowMode( + HMONITOR hMonitor, + HWND hWindow, + const WsiMode& mode) { + return s_driver->setWindowMode(hMonitor, hWindow, mode); + } + + bool enterFullscreenMode( + HMONITOR hMonitor, + HWND hWindow, + DxvkWindowState* pState, + [[maybe_unused]] + bool modeSwitch) { + return s_driver->enterFullscreenMode(hMonitor, hWindow, pState, modeSwitch); + } + + bool leaveFullscreenMode( + HWND hWindow, + DxvkWindowState* pState, + bool restoreCoordinates) { + return s_driver->leaveFullscreenMode(hWindow, pState, restoreCoordinates); + } + + bool restoreDisplayMode() { + return s_driver->restoreDisplayMode(); + } + + HMONITOR getWindowMonitor(HWND hWindow) { + return s_driver->getWindowMonitor(hWindow); + } + + bool isWindow(HWND hWindow) { + return s_driver->isWindow(hWindow); + } + + void updateFullscreenWindow( + HMONITOR hMonitor, + HWND hWindow, + bool forceTopmost) { + s_driver->updateFullscreenWindow(hMonitor, hWindow, forceTopmost); + } + + VkResult createSurface( + HWND hWindow, + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, + VkInstance instance, + VkSurfaceKHR* pSurface) { + return s_driver->createSurface(hWindow, pfnVkGetInstanceProcAddr, instance, pSurface); + } + + HMONITOR getDefaultMonitor() { + return s_driver->getDefaultMonitor(); + } + + HMONITOR enumMonitors(uint32_t index) { + return s_driver->enumMonitors(index); + } + + HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) { + return s_driver->enumMonitors(adapterLUID, numLUIDs, index); + } + + bool getDisplayName( + HMONITOR hMonitor, + WCHAR (&Name)[32]) { + return s_driver->getDisplayName(hMonitor, Name); + } + + bool getDesktopCoordinates( + HMONITOR hMonitor, + RECT* pRect) { + return s_driver->getDesktopCoordinates(hMonitor, pRect); + } + + bool getDisplayMode( + HMONITOR hMonitor, + uint32_t modeNumber, + WsiMode* pMode) { + return s_driver->getDisplayMode(hMonitor, modeNumber, pMode); + } + + bool getCurrentDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode) { + return s_driver->getCurrentDisplayMode(hMonitor, pMode); + } + + bool getDesktopDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode) { + return s_driver->getDesktopDisplayMode(hMonitor, pMode); + } + + WsiEdidData getMonitorEdid(HMONITOR hMonitor) { + return s_driver->getMonitorEdid(hMonitor); } } diff --git a/src/wsi/wsi_platform.h b/src/wsi/wsi_platform.h index 7ccecc27..f8373fe5 100644 --- a/src/wsi/wsi_platform.h +++ b/src/wsi/wsi_platform.h @@ -1,19 +1,100 @@ #pragma once -#if defined(DXVK_WSI_WIN32) -#include "win32/wsi_platform_win32.h" -#elif defined(DXVK_WSI_SDL2) -#include "sdl2/wsi_platform_sdl2.h" -#elif defined(DXVK_WSI_GLFW) -#include "glfw/wsi_platform_glfw.h" -#endif +#include "wsi_window.h" #include namespace dxvk::wsi { + class WsiDriver { + public: + virtual ~WsiDriver() { + } + + // Platform + virtual std::vector getInstanceExtensions() = 0; + + // Monitor + virtual HMONITOR getDefaultMonitor() = 0; + + virtual HMONITOR enumMonitors(uint32_t index) = 0; + + virtual HMONITOR enumMonitors(const LUID *adapterLUID[], uint32_t numLUIDs, uint32_t index) = 0; + + virtual bool getDisplayName( + HMONITOR hMonitor, + WCHAR (&Name)[32]) = 0; + + virtual bool getDesktopCoordinates( + HMONITOR hMonitor, + RECT* pRect) = 0; + + virtual bool getDisplayMode( + HMONITOR hMonitor, + uint32_t modeNumber, + WsiMode* pMode) = 0; + + virtual bool getCurrentDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode) = 0; + + virtual bool getDesktopDisplayMode( + HMONITOR hMonitor, + WsiMode* pMode) = 0; + + virtual WsiEdidData getMonitorEdid(HMONITOR hMonitor) = 0; + + // Window + + virtual void getWindowSize( + HWND hWindow, + uint32_t* pWidth, + uint32_t* pWeight) = 0; + + virtual void resizeWindow( + HWND hWindow, + DxvkWindowState* pState, + uint32_t width, + uint32_t weight) = 0; + + virtual bool setWindowMode( + HMONITOR hMonitor, + HWND hWindow, + const WsiMode& mode) = 0; + + virtual bool enterFullscreenMode( + HMONITOR hMonitor, + HWND hWindow, + DxvkWindowState* pState, + [[maybe_unused]] + bool modeSwitch) = 0; + + virtual bool leaveFullscreenMode( + HWND hWindow, + DxvkWindowState* pState, + bool restoreCoordinates) = 0; + + virtual bool restoreDisplayMode() = 0; + + virtual HMONITOR getWindowMonitor(HWND hWindow) = 0; + + virtual bool isWindow(HWND hWindow) = 0; + + virtual void updateFullscreenWindow( + HMONITOR hMonitor, + HWND hWindow, + bool forceTopmost) = 0; + + virtual VkResult createSurface( + HWND hWindow, + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, + VkInstance instance, + VkSurfaceKHR* pSurface) = 0; + }; + void init(); void quit(); std::vector getInstanceExtensions(); + WsiDriver* platformCreateWsiDriver(); } diff --git a/src/wsi/wsi_window.h b/src/wsi/wsi_window.h index e0587a0f..68c6db9c 100644 --- a/src/wsi/wsi_window.h +++ b/src/wsi/wsi_window.h @@ -3,12 +3,22 @@ #include #include "wsi_monitor.h" -#include "wsi_platform.h" #include "../vulkan/vulkan_loader.h" namespace dxvk::wsi { + /** + * \brief Impl-dependent state + */ + struct DxvkWindowState { +#ifdef DXVK_WSI_WIN32 + LONG style = 0; + LONG exstyle = 0; + RECT rect = { 0, 0, 0, 0 }; +#endif + }; + /** * \brief The size of the window * From ba575b5024353385729eae0a7936acf74ede53b6 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 8 Dec 2023 00:59:23 -0500 Subject: [PATCH 4/6] [native] Dynamically load SDL2/GLFW at runtime. Removing these link-time dependencies is important for making a single binary that is compatible with either backend, regardless of whether or not each one is currently available to the program. --- src/wsi/glfw/wsi_platform_glfw.cpp | 28 ++++++++++++++++++++++++++ src/wsi/glfw/wsi_platform_glfw.h | 24 +++++++++++++++------- src/wsi/glfw/wsi_platform_glfw_funcs.h | 12 +++++++++++ src/wsi/meson.build | 4 +--- src/wsi/sdl2/wsi_platform_sdl2.cpp | 28 ++++++++++++++++++++++++++ src/wsi/sdl2/wsi_platform_sdl2.h | 22 ++++++++++++++------ src/wsi/sdl2/wsi_platform_sdl2_funcs.h | 16 +++++++++++++++ 7 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 src/wsi/glfw/wsi_platform_glfw_funcs.h create mode 100644 src/wsi/sdl2/wsi_platform_sdl2_funcs.h diff --git a/src/wsi/glfw/wsi_platform_glfw.cpp b/src/wsi/glfw/wsi_platform_glfw.cpp index fb711aeb..09b95628 100644 --- a/src/wsi/glfw/wsi_platform_glfw.cpp +++ b/src/wsi/glfw/wsi_platform_glfw.cpp @@ -1,9 +1,37 @@ #include "wsi_platform_glfw.h" #include "../../util/util_error.h" #include "../../util/util_string.h" +#include "../../util/util_win32_compat.h" namespace dxvk::wsi { + GlfwWsiDriver::GlfwWsiDriver() { + libglfw = LoadLibraryA( // FIXME: Get soname as string from meson +#if defined(_WIN32) + "glfw.dll" +#elif defined(__APPLE__) + "libglfw.3.dylib" +#else + "libglfw.so.3" +#endif + ); + if (libglfw == nullptr) + throw DxvkError("GLFW WSI: Failed to load GLFW DLL."); + + #define GLFW_PROC(ret, name, params) \ + name = reinterpret_cast(GetProcAddress(libglfw, #name)); \ + if (name == nullptr) { \ + FreeLibrary(libglfw); \ + libglfw = nullptr; \ + throw DxvkError("GLFW WSI: Failed to load " #name "."); \ + } + #include "wsi_platform_glfw_funcs.h" + } + + GlfwWsiDriver::~GlfwWsiDriver() { + FreeLibrary(libglfw); + } + std::vector GlfwWsiDriver::getInstanceExtensions() { if (!glfwVulkanSupported()) throw DxvkError(str::format("GLFW WSI: Vulkan is not supported in any capacity!")); diff --git a/src/wsi/glfw/wsi_platform_glfw.h b/src/wsi/glfw/wsi_platform_glfw.h index 83b95c5e..849ce4f5 100644 --- a/src/wsi/glfw/wsi_platform_glfw.h +++ b/src/wsi/glfw/wsi_platform_glfw.h @@ -8,7 +8,24 @@ namespace dxvk::wsi { class GlfwWsiDriver : public WsiDriver { + private: + HMODULE libglfw; + #define GLFW_PROC(ret, name, params) \ + typedef ret (*pfn_##name) params; \ + pfn_##name name; + #include "wsi_platform_glfw_funcs.h" + + inline bool isDisplayValid(int32_t displayId) { + int32_t displayCount = 0; + glfwGetMonitors(&displayCount); + + return displayId < displayCount && displayId >= 0; + } + public: + GlfwWsiDriver(); + ~GlfwWsiDriver(); + // Platform virtual std::vector getInstanceExtensions(); @@ -89,12 +106,5 @@ namespace dxvk::wsi { VkInstance instance, VkSurfaceKHR* pSurface); }; - - inline bool isDisplayValid(int32_t displayId) { - int32_t displayCount = 0; - glfwGetMonitors(&displayCount); - - return displayId < displayCount && displayId >= 0; - } } diff --git a/src/wsi/glfw/wsi_platform_glfw_funcs.h b/src/wsi/glfw/wsi_platform_glfw_funcs.h new file mode 100644 index 00000000..89cedfd0 --- /dev/null +++ b/src/wsi/glfw/wsi_platform_glfw_funcs.h @@ -0,0 +1,12 @@ +GLFW_PROC(VkResult, glfwCreateWindowSurface, (VkInstance, GLFWwindow*, const VkAllocationCallbacks*, VkSurfaceKHR*)) +GLFW_PROC(GLFWmonitor**, glfwGetMonitors, (int*)) +GLFW_PROC(void, glfwGetMonitorWorkarea, (GLFWmonitor*, int*, int*, int*, int*)) +GLFW_PROC(GLFWmonitor*, glfwGetPrimaryMonitor, (void)) +GLFW_PROC(const char**, glfwGetRequiredInstanceExtensions, (uint32_t*)) +GLFW_PROC(const GLFWvidmode*, glfwGetVideoMode, (GLFWmonitor*)) +GLFW_PROC(const GLFWvidmode*, glfwGetVideoModes, (GLFWmonitor*, int*)) +GLFW_PROC(void, glfwGetWindowSize, (GLFWwindow*, int*, int*)) +GLFW_PROC(void, glfwSetWindowMonitor, (GLFWwindow*, GLFWmonitor*, int, int, int, int, int)) +GLFW_PROC(void, glfwSetWindowSize, (GLFWwindow*, int, int)) +GLFW_PROC(int, glfwVulkanSupported, (void)) +#undef GLFW_PROC diff --git a/src/wsi/meson.build b/src/wsi/meson.build index 1cabcf2f..f16a4e39 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -23,16 +23,14 @@ wsi_glfw_src = [ if dxvk_wsi == 'win32' wsi_src = wsi_common_src + wsi_win32_src - wsi_deps = [ dep_displayinfo ] elif dxvk_wsi == 'sdl2' wsi_src = wsi_common_src + wsi_sdl2_src - wsi_deps = [ dep_displayinfo, lib_sdl2 ] elif dxvk_wsi == 'glfw' wsi_src = wsi_common_src + wsi_glfw_src - wsi_deps = [ dep_displayinfo, lib_glfw ] else error('Unknown wsi') endif +wsi_deps = [ dep_displayinfo ] wsi_lib = static_library('wsi', wsi_src, dependencies : wsi_deps, diff --git a/src/wsi/sdl2/wsi_platform_sdl2.cpp b/src/wsi/sdl2/wsi_platform_sdl2.cpp index 96ecb076..d2574430 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.cpp +++ b/src/wsi/sdl2/wsi_platform_sdl2.cpp @@ -1,11 +1,39 @@ #include "wsi_platform_sdl2.h" #include "../../util/util_error.h" #include "../../util/util_string.h" +#include "../../util/util_win32_compat.h" #include namespace dxvk::wsi { + Sdl2WsiDriver::Sdl2WsiDriver() { + libsdl = LoadLibraryA( // FIXME: Get soname as string from meson +#if defined(_WIN32) + "SDL2.dll" +#elif defined(__APPLE__) + "libSDL2-2.0.0.dylib" +#else + "libSDL2-2.0.so.0" +#endif + ); + if (libsdl == nullptr) + throw DxvkError("SDL2 WSI: Failed to load SDL2 DLL."); + + #define SDL_PROC(ret, name, params) \ + name = reinterpret_cast(GetProcAddress(libsdl, #name)); \ + if (name == nullptr) { \ + FreeLibrary(libsdl); \ + libsdl = nullptr; \ + throw DxvkError("SDL2 WSI: Failed to load " #name "."); \ + } + #include "wsi_platform_sdl2_funcs.h" + } + + Sdl2WsiDriver::~Sdl2WsiDriver() { + FreeLibrary(libsdl); + } + std::vector Sdl2WsiDriver::getInstanceExtensions() { SDL_Vulkan_LoadLibrary(nullptr); diff --git a/src/wsi/sdl2/wsi_platform_sdl2.h b/src/wsi/sdl2/wsi_platform_sdl2.h index 845725ab..fc3ce353 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.h +++ b/src/wsi/sdl2/wsi_platform_sdl2.h @@ -7,7 +7,23 @@ namespace dxvk::wsi { class Sdl2WsiDriver : public WsiDriver { + private: + HMODULE libsdl; + #define SDL_PROC(ret, name, params) \ + typedef ret (SDLCALL *pfn_##name) params; \ + pfn_##name name; + #include "wsi_platform_sdl2_funcs.h" + + inline bool isDisplayValid(int32_t displayId) { + const int32_t displayCount = SDL_GetNumVideoDisplays(); + + return displayId < displayCount && displayId >= 0; + } + public: + Sdl2WsiDriver(); + ~Sdl2WsiDriver(); + // Platform virtual std::vector getInstanceExtensions(); @@ -88,11 +104,5 @@ namespace dxvk::wsi { VkInstance instance, VkSurfaceKHR* pSurface); }; - - inline bool isDisplayValid(int32_t displayId) { - const int32_t displayCount = SDL_GetNumVideoDisplays(); - - return displayId < displayCount && displayId >= 0; - } } diff --git a/src/wsi/sdl2/wsi_platform_sdl2_funcs.h b/src/wsi/sdl2/wsi_platform_sdl2_funcs.h new file mode 100644 index 00000000..3da94922 --- /dev/null +++ b/src/wsi/sdl2/wsi_platform_sdl2_funcs.h @@ -0,0 +1,16 @@ +SDL_PROC(SDL_DisplayMode*, SDL_GetClosestDisplayMode, (int, const SDL_DisplayMode*, SDL_DisplayMode*)) +SDL_PROC(int, SDL_GetCurrentDisplayMode, (int, SDL_DisplayMode*)) +SDL_PROC(int, SDL_GetDesktopDisplayMode, (int, SDL_DisplayMode*)) +SDL_PROC(int, SDL_GetDisplayBounds, (int, SDL_Rect*)) +SDL_PROC(int, SDL_GetDisplayMode, (int, int, SDL_DisplayMode*)) +SDL_PROC(const char*, SDL_GetError, (void)) +SDL_PROC(int, SDL_GetNumVideoDisplays, (void)) +SDL_PROC(int, SDL_GetWindowDisplayIndex, (SDL_Window*)) +SDL_PROC(int, SDL_SetWindowDisplayMode, (SDL_Window*, const SDL_DisplayMode*)) +SDL_PROC(int, SDL_SetWindowFullscreen, (SDL_Window*, Uint32)) +SDL_PROC(void, SDL_GetWindowSize, (SDL_Window*, int*, int*)) +SDL_PROC(void, SDL_SetWindowSize, (SDL_Window*, int, int)) +SDL_PROC(SDL_bool, SDL_Vulkan_CreateSurface, (SDL_Window*, VkInstance, VkSurfaceKHR*)) +SDL_PROC(SDL_bool, SDL_Vulkan_GetInstanceExtensions, (SDL_Window*, unsigned int*, const char**)) +SDL_PROC(int, SDL_Vulkan_LoadLibrary, (const char*)) +#undef SDL_PROC From f96ce6475d98767dc3627244c4300590a8dce1a8 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 8 Dec 2023 01:18:54 -0500 Subject: [PATCH 5/6] [wsi] Refactor platform system to support multiple WSI implementations --- meson.build | 15 ++++++++------- src/wsi/glfw/wsi_monitor_glfw.cpp | 4 ++++ src/wsi/glfw/wsi_platform_glfw.cpp | 18 ++++++++++++++++-- src/wsi/glfw/wsi_window_glfw.cpp | 6 +++++- src/wsi/meson.build | 20 +------------------- src/wsi/sdl2/wsi_monitor_sdl2.cpp | 4 ++++ src/wsi/sdl2/wsi_platform_sdl2.cpp | 18 ++++++++++++++++-- src/wsi/sdl2/wsi_window_sdl2.cpp | 6 +++++- src/wsi/win32/wsi_monitor_win32.cpp | 4 ++++ src/wsi/win32/wsi_platform_win32.cpp | 14 ++++++++++++-- src/wsi/win32/wsi_window_win32.cpp | 22 +++++++++++++--------- src/wsi/wsi_platform.cpp | 27 +++++++++++++++++++++++++-- src/wsi/wsi_platform.h | 16 +++++++++++++++- src/wsi/wsi_window.h | 16 ++++++++++++---- 14 files changed, 140 insertions(+), 50 deletions(-) diff --git a/meson.build b/meson.build index e35a9de0..1a82e4bc 100644 --- a/meson.build +++ b/meson.build @@ -115,7 +115,6 @@ if platform == 'windows' ) endif - dxvk_wsi = 'win32' dxvk_name_prefix = '' compiler_args += ['-DDXVK_WSI_WIN32'] else @@ -128,15 +127,17 @@ else './include/native/directx' ] - dxvk_wsi = get_option('dxvk_native_wsi') - - if dxvk_wsi == 'sdl2' - lib_sdl2 = cpp.find_library('SDL2') + lib_sdl2 = cpp.find_library('SDL2', required: false) + lib_glfw = cpp.find_library('glfw', required: false) + if lib_sdl2.found() compiler_args += ['-DDXVK_WSI_SDL2'] - elif dxvk_wsi == 'glfw' - lib_glfw = cpp.find_library('glfw') + endif + if lib_glfw.found() compiler_args += ['-DDXVK_WSI_GLFW'] endif + if (not lib_sdl2.found() and not lib_glfw.found()) + error('SDL2 or GLFW are required to build dxvk-native') + endif dxvk_name_prefix = 'libdxvk_' diff --git a/src/wsi/glfw/wsi_monitor_glfw.cpp b/src/wsi/glfw/wsi_monitor_glfw.cpp index 00abc89a..f6c09aaf 100644 --- a/src/wsi/glfw/wsi_monitor_glfw.cpp +++ b/src/wsi/glfw/wsi_monitor_glfw.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_GLFW) + #include "../wsi_monitor.h" #include "wsi/native_wsi.h" @@ -165,3 +167,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/glfw/wsi_platform_glfw.cpp b/src/wsi/glfw/wsi_platform_glfw.cpp index 09b95628..ee818bb2 100644 --- a/src/wsi/glfw/wsi_platform_glfw.cpp +++ b/src/wsi/glfw/wsi_platform_glfw.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_GLFW) + #include "wsi_platform_glfw.h" #include "../../util/util_error.h" #include "../../util/util_string.h" @@ -50,8 +52,20 @@ namespace dxvk::wsi { return names; } - WsiDriver* platformCreateWsiDriver() { - return new GlfwWsiDriver(); + static bool createGlfwWsiDriver(WsiDriver **driver) { + try { + *driver = new GlfwWsiDriver(); + } catch (const DxvkError& e) { + return false; + } + return true; } + WsiBootstrap GlfwWSI = { + "GLFW", + createGlfwWsiDriver + }; + } + +#endif diff --git a/src/wsi/glfw/wsi_window_glfw.cpp b/src/wsi/glfw/wsi_window_glfw.cpp index b23a7923..f763e759 100644 --- a/src/wsi/glfw/wsi_window_glfw.cpp +++ b/src/wsi/glfw/wsi_window_glfw.cpp @@ -1,6 +1,8 @@ +#if defined(DXVK_WSI_GLFW) + #include "../wsi_window.h" -#include "native/wsi/native_wsi.h" +#include "native/wsi/native_glfw.h" #include "wsi_platform_glfw.h" #include "../../util/util_string.h" @@ -142,3 +144,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/meson.build b/src/wsi/meson.build index f16a4e39..f60840b9 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -1,35 +1,17 @@ -wsi_common_src = [ +wsi_src = [ 'wsi_edid.cpp', 'wsi_platform.cpp', -] - -wsi_win32_src = [ 'win32/wsi_monitor_win32.cpp', 'win32/wsi_platform_win32.cpp', 'win32/wsi_window_win32.cpp', -] - -wsi_sdl2_src = [ 'sdl2/wsi_monitor_sdl2.cpp', 'sdl2/wsi_platform_sdl2.cpp', 'sdl2/wsi_window_sdl2.cpp', -] - -wsi_glfw_src = [ 'glfw/wsi_monitor_glfw.cpp', 'glfw/wsi_platform_glfw.cpp', 'glfw/wsi_window_glfw.cpp', ] -if dxvk_wsi == 'win32' - wsi_src = wsi_common_src + wsi_win32_src -elif dxvk_wsi == 'sdl2' - wsi_src = wsi_common_src + wsi_sdl2_src -elif dxvk_wsi == 'glfw' - wsi_src = wsi_common_src + wsi_glfw_src -else - error('Unknown wsi') -endif wsi_deps = [ dep_displayinfo ] wsi_lib = static_library('wsi', wsi_src, diff --git a/src/wsi/sdl2/wsi_monitor_sdl2.cpp b/src/wsi/sdl2/wsi_monitor_sdl2.cpp index 5903ef68..8f5f3290 100644 --- a/src/wsi/sdl2/wsi_monitor_sdl2.cpp +++ b/src/wsi/sdl2/wsi_monitor_sdl2.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_SDL2) + #include "../wsi_monitor.h" #include "wsi/native_wsi.h" @@ -154,3 +156,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/sdl2/wsi_platform_sdl2.cpp b/src/wsi/sdl2/wsi_platform_sdl2.cpp index d2574430..9223b598 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.cpp +++ b/src/wsi/sdl2/wsi_platform_sdl2.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_SDL2) + #include "wsi_platform_sdl2.h" #include "../../util/util_error.h" #include "../../util/util_string.h" @@ -48,8 +50,20 @@ namespace dxvk::wsi { return extensionNames; } - WsiDriver* platformCreateWsiDriver() { - return new Sdl2WsiDriver(); + static bool createSdl2WsiDriver(WsiDriver **driver) { + try { + *driver = new Sdl2WsiDriver(); + } catch (const DxvkError& e) { + return false; + } + return true; } + WsiBootstrap Sdl2WSI = { + "SDL2", + createSdl2WsiDriver + }; + } + +#endif diff --git a/src/wsi/sdl2/wsi_window_sdl2.cpp b/src/wsi/sdl2/wsi_window_sdl2.cpp index 5622e876..68e90229 100644 --- a/src/wsi/sdl2/wsi_window_sdl2.cpp +++ b/src/wsi/sdl2/wsi_window_sdl2.cpp @@ -1,6 +1,8 @@ +#if defined(DXVK_WSI_SDL2) + #include "../wsi_window.h" -#include "native/wsi/native_wsi.h" +#include "native/wsi/native_sdl2.h" #include "wsi_platform_sdl2.h" #include "../../util/util_string.h" @@ -155,3 +157,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/win32/wsi_monitor_win32.cpp b/src/wsi/win32/wsi_monitor_win32.cpp index b37e0902..0387d87f 100644 --- a/src/wsi/win32/wsi_monitor_win32.cpp +++ b/src/wsi/win32/wsi_monitor_win32.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_WIN32) + #include "wsi_platform_win32.h" #include "../../util/util_string.h" @@ -370,3 +372,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/win32/wsi_platform_win32.cpp b/src/wsi/win32/wsi_platform_win32.cpp index ab27869a..03bf40a5 100644 --- a/src/wsi/win32/wsi_platform_win32.cpp +++ b/src/wsi/win32/wsi_platform_win32.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_WIN32) + #include "wsi_platform_win32.h" namespace dxvk::wsi { @@ -6,8 +8,16 @@ namespace dxvk::wsi { return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; } - WsiDriver* platformCreateWsiDriver() { - return new Win32WsiDriver(); + static bool createWin32WsiDriver(WsiDriver **driver) { + *driver = new Win32WsiDriver(); + return true; } + WsiBootstrap Win32WSI = { + "Win32", + createWin32WsiDriver + }; + } + +#endif diff --git a/src/wsi/win32/wsi_window_win32.cpp b/src/wsi/win32/wsi_window_win32.cpp index cf446980..894da8e7 100644 --- a/src/wsi/win32/wsi_window_win32.cpp +++ b/src/wsi/win32/wsi_window_win32.cpp @@ -1,3 +1,5 @@ +#if defined(DXVK_WSI_WIN32) + #include "wsi_platform_win32.h" #include "../../util/util_string.h" @@ -169,14 +171,14 @@ namespace dxvk::wsi { [[maybe_unused]] bool modeSwitch) { // Find a display mode that matches what we need - ::GetWindowRect(hWindow, &pState->rect); + ::GetWindowRect(hWindow, &pState->win.rect); // Change the window flags to remove the decoration etc. LONG style = ::GetWindowLongW(hWindow, GWL_STYLE); LONG exstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE); - pState->style = style; - pState->exstyle = exstyle; + pState->win.style = style; + pState->win.exstyle = exstyle; style &= ~WS_OVERLAPPEDWINDOW; exstyle &= ~WS_EX_OVERLAPPEDWINDOW; @@ -204,20 +206,20 @@ namespace dxvk::wsi { LONG curStyle = ::GetWindowLongW(hWindow, GWL_STYLE) & ~WS_VISIBLE; LONG curExstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE) & ~WS_EX_TOPMOST; - if (curStyle == (pState->style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW)) - && curExstyle == (pState->exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) { - ::SetWindowLongW(hWindow, GWL_STYLE, pState->style); - ::SetWindowLongW(hWindow, GWL_EXSTYLE, pState->exstyle); + if (curStyle == (pState->win.style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW)) + && curExstyle == (pState->win.exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) { + ::SetWindowLongW(hWindow, GWL_STYLE, pState->win.style); + ::SetWindowLongW(hWindow, GWL_EXSTYLE, pState->win.exstyle); } // Restore window position and apply the style UINT flags = SWP_FRAMECHANGED | SWP_NOACTIVATE; - const RECT rect = pState->rect; + const RECT rect = pState->win.rect; if (!restoreCoordinates) flags |= SWP_NOSIZE | SWP_NOMOVE; - ::SetWindowPos(hWindow, (pState->exstyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_NOTOPMOST, + ::SetWindowPos(hWindow, (pState->win.exstyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_NOTOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags); return true; @@ -295,3 +297,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/wsi_platform.cpp b/src/wsi/wsi_platform.cpp index f4802025..27a342b2 100644 --- a/src/wsi/wsi_platform.cpp +++ b/src/wsi/wsi_platform.cpp @@ -1,18 +1,41 @@ #include "wsi_platform.h" #include "wsi_monitor.h" #include "wsi_window.h" +#include "../util/util_env.h" #include "../util/util_error.h" namespace dxvk::wsi { static WsiDriver* s_driver = nullptr; static int s_refcount = 0; + static const WsiBootstrap *wsiBootstrap[] = { +#if defined(DXVK_WSI_WIN32) + &Win32WSI, +#endif +#if defined(DXVK_WSI_SDL2) + &Sdl2WSI, +#endif +#if defined(DXVK_WSI_GLFW) + &GlfwWSI, +#endif + }; + void init() { if (s_refcount++ > 0) return; - s_driver = platformCreateWsiDriver(); - if (s_driver == nullptr) + bool success = false; + const std::string hint = dxvk::env::getEnvVar("DXVK_WSIDRIVER"); + for (const WsiBootstrap *b : wsiBootstrap) { + if ((hint != "") && (hint != b->name)) + continue; + if (b->createDriver(&s_driver)) { + success = true; + break; + } + } + + if (!success) throw DxvkError("Failed to initialize WSI."); } diff --git a/src/wsi/wsi_platform.h b/src/wsi/wsi_platform.h index f8373fe5..8c37bc94 100644 --- a/src/wsi/wsi_platform.h +++ b/src/wsi/wsi_platform.h @@ -92,9 +92,23 @@ namespace dxvk::wsi { VkSurfaceKHR* pSurface) = 0; }; + struct WsiBootstrap { + const std::string name; + bool (*createDriver)(WsiDriver **driver); + }; + +#if defined(DXVK_WSI_WIN32) + extern WsiBootstrap Win32WSI; +#endif +#if defined(DXVK_WSI_SDL2) + extern WsiBootstrap Sdl2WSI; +#endif +#if defined(DXVK_WSI_GLFW) + extern WsiBootstrap GlfwWSI; +#endif + void init(); void quit(); std::vector getInstanceExtensions(); - WsiDriver* platformCreateWsiDriver(); } diff --git a/src/wsi/wsi_window.h b/src/wsi/wsi_window.h index 68c6db9c..ceb14923 100644 --- a/src/wsi/wsi_window.h +++ b/src/wsi/wsi_window.h @@ -12,10 +12,18 @@ namespace dxvk::wsi { * \brief Impl-dependent state */ struct DxvkWindowState { -#ifdef DXVK_WSI_WIN32 - LONG style = 0; - LONG exstyle = 0; - RECT rect = { 0, 0, 0, 0 }; +#if defined(DXVK_WSI_WIN32) + struct { + LONG style = 0; + LONG exstyle = 0; + RECT rect = { 0, 0, 0, 0 }; + } win; +#endif +#if defined(DXVK_WSI_SDL2) + // Nothing to store +#endif +#if defined(DXVK_WSI_GLFW) + // Nothing to store #endif }; From d48b8767fab136d73395fdc6ffa0a46a547360ff Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 10 Feb 2024 13:06:33 -0500 Subject: [PATCH 6/6] [meson] Use dependency() instead of find_library() for SDL2/GLFW detection. Since we're not linking to the libraries anymore, it doesn't make much sense to use find_library, and in fact we need to use dependency() in order to get the right CFLAGS for includes, defines, etc, so use that instead. As a result, we can remove the 'SDL2/' folders from the includes, making the SDL includes more correct. --- include/native/wsi/native_sdl2.h | 4 ++-- meson.build | 4 ++-- src/wsi/meson.build | 7 +++++++ src/wsi/sdl2/wsi_platform_sdl2.h | 2 +- src/wsi/sdl2/wsi_window_sdl2.cpp | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/native/wsi/native_sdl2.h b/include/native/wsi/native_sdl2.h index b197d952..7ece3a55 100644 --- a/include/native/wsi/native_sdl2.h +++ b/include/native/wsi/native_sdl2.h @@ -1,6 +1,6 @@ #include -#include +#include namespace dxvk::wsi { @@ -22,4 +22,4 @@ namespace dxvk::wsi { return reinterpret_cast(static_cast(displayId + 1)); } -} \ No newline at end of file +} diff --git a/meson.build b/meson.build index 1a82e4bc..fe503562 100644 --- a/meson.build +++ b/meson.build @@ -127,8 +127,8 @@ else './include/native/directx' ] - lib_sdl2 = cpp.find_library('SDL2', required: false) - lib_glfw = cpp.find_library('glfw', required: false) + lib_sdl2 = dependency('SDL2', required: false) + lib_glfw = dependency('glfw', required: false) if lib_sdl2.found() compiler_args += ['-DDXVK_WSI_SDL2'] endif diff --git a/src/wsi/meson.build b/src/wsi/meson.build index f60840b9..4cfb13a8 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -14,6 +14,13 @@ wsi_src = [ wsi_deps = [ dep_displayinfo ] +if platform != 'windows' + wsi_deps += [ + lib_sdl2.partial_dependency(compile_args: true, includes: true), + lib_glfw.partial_dependency(compile_args: true, includes: true), + ] +endif + wsi_lib = static_library('wsi', wsi_src, dependencies : wsi_deps, include_directories : [ dxvk_include_path ]) diff --git a/src/wsi/sdl2/wsi_platform_sdl2.h b/src/wsi/sdl2/wsi_platform_sdl2.h index fc3ce353..1a6ac8aa 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.h +++ b/src/wsi/sdl2/wsi_platform_sdl2.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "../wsi_platform.h" diff --git a/src/wsi/sdl2/wsi_window_sdl2.cpp b/src/wsi/sdl2/wsi_window_sdl2.cpp index 68e90229..33084dc3 100644 --- a/src/wsi/sdl2/wsi_window_sdl2.cpp +++ b/src/wsi/sdl2/wsi_window_sdl2.cpp @@ -9,7 +9,7 @@ #include "../../util/log/log.h" #include -#include +#include namespace dxvk::wsi {