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 };