[wsi] Refactor platform system to support multiple WSI implementations

This commit is contained in:
Ethan Lee 2023-12-08 01:18:54 -05:00
parent ba575b5024
commit f96ce6475d
14 changed files with 140 additions and 50 deletions

View File

@ -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_'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.");
}

View File

@ -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<const char *> getInstanceExtensions();
WsiDriver* platformCreateWsiDriver();
}

View File

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