1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[wsi] Refactor platform system to support multiple WSI implementations

This commit is contained in:
Ethan Lee 2023-12-08 01:18:54 -05:00 committed by Joshie
parent 10b83d184b
commit d5d236a1e2
14 changed files with 148 additions and 50 deletions

View File

@ -115,7 +115,6 @@ if platform == 'windows'
) )
endif endif
dxvk_wsi = 'win32'
dxvk_name_prefix = '' dxvk_name_prefix = ''
compiler_args += ['-DDXVK_WSI_WIN32'] compiler_args += ['-DDXVK_WSI_WIN32']
else else
@ -128,15 +127,17 @@ else
'./include/native/directx' './include/native/directx'
] ]
dxvk_wsi = get_option('dxvk_native_wsi') lib_sdl2 = cpp.find_library('SDL2', required: false)
lib_glfw = cpp.find_library('glfw', required: false)
if dxvk_wsi == 'sdl2' if lib_sdl2.found()
lib_sdl2 = cpp.find_library('SDL2')
compiler_args += ['-DDXVK_WSI_SDL2'] compiler_args += ['-DDXVK_WSI_SDL2']
elif dxvk_wsi == 'glfw' endif
lib_glfw = cpp.find_library('glfw') if lib_glfw.found()
compiler_args += ['-DDXVK_WSI_GLFW'] compiler_args += ['-DDXVK_WSI_GLFW']
endif 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_' dxvk_name_prefix = 'libdxvk_'

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_GLFW)
#include "../wsi_monitor.h" #include "../wsi_monitor.h"
#include "wsi/native_wsi.h" #include "wsi/native_wsi.h"
@ -165,3 +167,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_GLFW)
#include "wsi_platform_glfw.h" #include "wsi_platform_glfw.h"
#include "../../util/util_error.h" #include "../../util/util_error.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -50,8 +52,20 @@ namespace dxvk::wsi {
return names; return names;
} }
WsiDriver* platformCreateWsiDriver() { static bool createGlfwWsiDriver(WsiDriver **driver) {
return new GlfwWsiDriver(); try {
*driver = new GlfwWsiDriver();
} catch (const DxvkError& e) {
return false;
}
return true;
} }
WsiBootstrap GlfwWSI = {
"GLFW",
createGlfwWsiDriver
};
} }
#endif

View File

@ -1,6 +1,8 @@
#if defined(DXVK_WSI_GLFW)
#include "../wsi_window.h" #include "../wsi_window.h"
#include "native/wsi/native_wsi.h" #include "native/wsi/native_glfw.h"
#include "wsi_platform_glfw.h" #include "wsi_platform_glfw.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -142,3 +144,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,35 +1,17 @@
wsi_common_src = [ wsi_src = [
'wsi_edid.cpp', 'wsi_edid.cpp',
'wsi_platform.cpp', 'wsi_platform.cpp',
]
wsi_win32_src = [
'win32/wsi_monitor_win32.cpp', 'win32/wsi_monitor_win32.cpp',
'win32/wsi_platform_win32.cpp', 'win32/wsi_platform_win32.cpp',
'win32/wsi_window_win32.cpp', 'win32/wsi_window_win32.cpp',
]
wsi_sdl2_src = [
'sdl2/wsi_monitor_sdl2.cpp', 'sdl2/wsi_monitor_sdl2.cpp',
'sdl2/wsi_platform_sdl2.cpp', 'sdl2/wsi_platform_sdl2.cpp',
'sdl2/wsi_window_sdl2.cpp', 'sdl2/wsi_window_sdl2.cpp',
]
wsi_glfw_src = [
'glfw/wsi_monitor_glfw.cpp', 'glfw/wsi_monitor_glfw.cpp',
'glfw/wsi_platform_glfw.cpp', 'glfw/wsi_platform_glfw.cpp',
'glfw/wsi_window_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_deps = [ dep_displayinfo ]
wsi_lib = static_library('wsi', wsi_src, wsi_lib = static_library('wsi', wsi_src,

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_SDL2)
#include "../wsi_monitor.h" #include "../wsi_monitor.h"
#include "wsi/native_wsi.h" #include "wsi/native_wsi.h"
@ -154,3 +156,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_SDL2)
#include "wsi_platform_sdl2.h" #include "wsi_platform_sdl2.h"
#include "../../util/util_error.h" #include "../../util/util_error.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -48,8 +50,20 @@ namespace dxvk::wsi {
return extensionNames; return extensionNames;
} }
WsiDriver* platformCreateWsiDriver() { static bool createSdl2WsiDriver(WsiDriver **driver) {
return new Sdl2WsiDriver(); try {
*driver = new Sdl2WsiDriver();
} catch (const DxvkError& e) {
return false;
}
return true;
} }
WsiBootstrap Sdl2WSI = {
"SDL2",
createSdl2WsiDriver
};
} }
#endif

View File

@ -1,6 +1,8 @@
#if defined(DXVK_WSI_SDL2)
#include "../wsi_window.h" #include "../wsi_window.h"
#include "native/wsi/native_wsi.h" #include "native/wsi/native_sdl2.h"
#include "wsi_platform_sdl2.h" #include "wsi_platform_sdl2.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -155,3 +157,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_WIN32)
#include "wsi_platform_win32.h" #include "wsi_platform_win32.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -370,3 +372,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_WIN32)
#include "wsi_platform_win32.h" #include "wsi_platform_win32.h"
namespace dxvk::wsi { namespace dxvk::wsi {
@ -6,8 +8,16 @@ namespace dxvk::wsi {
return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME };
} }
WsiDriver* platformCreateWsiDriver() { static bool createWin32WsiDriver(WsiDriver **driver) {
return new Win32WsiDriver(); *driver = new Win32WsiDriver();
return true;
} }
WsiBootstrap Win32WSI = {
"Win32",
createWin32WsiDriver
};
} }
#endif

View File

@ -1,3 +1,5 @@
#if defined(DXVK_WSI_WIN32)
#include "wsi_platform_win32.h" #include "wsi_platform_win32.h"
#include "../../util/util_string.h" #include "../../util/util_string.h"
@ -169,14 +171,14 @@ namespace dxvk::wsi {
[[maybe_unused]] [[maybe_unused]]
bool modeSwitch) { bool modeSwitch) {
// Find a display mode that matches what we need // 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. // Change the window flags to remove the decoration etc.
LONG style = ::GetWindowLongW(hWindow, GWL_STYLE); LONG style = ::GetWindowLongW(hWindow, GWL_STYLE);
LONG exstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE); LONG exstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE);
pState->style = style; pState->win.style = style;
pState->exstyle = exstyle; pState->win.exstyle = exstyle;
style &= ~WS_OVERLAPPEDWINDOW; style &= ~WS_OVERLAPPEDWINDOW;
exstyle &= ~WS_EX_OVERLAPPEDWINDOW; exstyle &= ~WS_EX_OVERLAPPEDWINDOW;
@ -204,20 +206,20 @@ namespace dxvk::wsi {
LONG curStyle = ::GetWindowLongW(hWindow, GWL_STYLE) & ~WS_VISIBLE; LONG curStyle = ::GetWindowLongW(hWindow, GWL_STYLE) & ~WS_VISIBLE;
LONG curExstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE) & ~WS_EX_TOPMOST; LONG curExstyle = ::GetWindowLongW(hWindow, GWL_EXSTYLE) & ~WS_EX_TOPMOST;
if (curStyle == (pState->style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW)) if (curStyle == (pState->win.style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW))
&& curExstyle == (pState->exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) { && curExstyle == (pState->win.exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) {
::SetWindowLongW(hWindow, GWL_STYLE, pState->style); ::SetWindowLongW(hWindow, GWL_STYLE, pState->win.style);
::SetWindowLongW(hWindow, GWL_EXSTYLE, pState->exstyle); ::SetWindowLongW(hWindow, GWL_EXSTYLE, pState->win.exstyle);
} }
// Restore window position and apply the style // Restore window position and apply the style
UINT flags = SWP_FRAMECHANGED | SWP_NOACTIVATE; UINT flags = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const RECT rect = pState->rect; const RECT rect = pState->win.rect;
if (!restoreCoordinates) if (!restoreCoordinates)
flags |= SWP_NOSIZE | SWP_NOMOVE; 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); rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags);
return true; return true;
@ -295,3 +297,5 @@ namespace dxvk::wsi {
} }
} }
#endif

View File

@ -1,18 +1,49 @@
#include "wsi_platform.h" #include "wsi_platform.h"
#include "wsi_monitor.h" #include "wsi_monitor.h"
#include "wsi_window.h" #include "wsi_window.h"
#include "../util/util_env.h"
#include "../util/util_error.h" #include "../util/util_error.h"
namespace dxvk::wsi { namespace dxvk::wsi {
static WsiDriver* s_driver = nullptr; static WsiDriver* s_driver = nullptr;
static int s_refcount = 0; 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() { void init() {
if (s_refcount++ > 0) if (s_refcount++ > 0)
return; return;
s_driver = platformCreateWsiDriver(); std::string hint = dxvk::env::getEnvVar("DXVK_WSIDRIVER");
if (s_driver == nullptr) if (hint == "") {
// At least for Windows, it is reasonable to fall back to a default;
// for other platforms however we _need_ to know which WSI to use!
#if defined(DXVK_WSI_WIN32)
hint = "Win32";
#else
throw DxvkError("DXVK_WSIDRIVER environment variable unset");
#endif
}
bool success = false;
for (const WsiBootstrap *b : wsiBootstrap) {
if (hint == b->name && b->createDriver(&s_driver)) {
success = true;
break;
}
}
if (!success)
throw DxvkError("Failed to initialize WSI."); throw DxvkError("Failed to initialize WSI.");
} }

View File

@ -92,9 +92,23 @@ namespace dxvk::wsi {
VkSurfaceKHR* pSurface) = 0; 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 init();
void quit(); void quit();
std::vector<const char *> getInstanceExtensions(); std::vector<const char *> getInstanceExtensions();
WsiDriver* platformCreateWsiDriver();
} }

View File

@ -12,10 +12,18 @@ namespace dxvk::wsi {
* \brief Impl-dependent state * \brief Impl-dependent state
*/ */
struct DxvkWindowState { struct DxvkWindowState {
#ifdef DXVK_WSI_WIN32 #if defined(DXVK_WSI_WIN32)
LONG style = 0; struct {
LONG exstyle = 0; LONG style = 0;
RECT rect = { 0, 0, 0, 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 #endif
}; };