diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml index 9fe6485a..669a38fa 100644 --- a/.github/workflows/artifacts.yml +++ b/.github/workflows/artifacts.yml @@ -54,7 +54,7 @@ jobs: shell: bash run: | export VERSION_NAME="${GITHUB_REF##*/}-${GITHUB_SHA##*/}" - ./package-native.sh ${VERSION_NAME} build --no-package + ./package-native.sh ${VERSION_NAME} build echo "VERSION_NAME=${VERSION_NAME}" >> $GITHUB_ENV - name: Upload artifacts @@ -62,5 +62,5 @@ jobs: uses: actions/upload-artifact@v3 with: name: dxvk-${{ env.VERSION_NAME }} - path: build/dxvk-native-${{ env.VERSION_NAME }} + path: build/dxvk-native-${{ env.VERSION_NAME }}.tar.gz if-no-files-found: error diff --git a/include/native/meson.build b/include/native/meson.build new file mode 100644 index 00000000..4e1a6ff5 --- /dev/null +++ b/include/native/meson.build @@ -0,0 +1,18 @@ +install_subdir( + 'directx', + install_dir: get_option('includedir') / 'dxvk', + strip_directory: true, +) + +install_subdir( + 'windows', + install_dir: get_option('includedir') / 'dxvk', + strip_directory: true, +) + +install_headers( + 'wsi/native_wsi.h', + 'wsi/native_sdl2.h', + 'wsi/native_glfw.h', + subdir: 'dxvk/wsi', +) 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 2a263735..e99e8fd4 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,6 @@ -project('dxvk', ['c', 'cpp'], version : 'v2.3.1', meson_version : '>= 0.58', default_options : [ 'cpp_std=c++17', 'warning_level=2' ]) +project('dxvk', ['c', 'cpp'], version : '2.3.1', meson_version : '>= 0.58', default_options : [ 'cpp_std=c++17', 'warning_level=2' ]) +pkg = import('pkgconfig') cpu_family = target_machine.cpu_family() platform = target_machine.system() fs = import('fs') @@ -54,6 +55,8 @@ dep_displayinfo = dependency( ) if platform == 'windows' + dxvk_so_version = {'name_prefix': ''} + compiler_args += [ '-DNOMINMAX', '-D_WIN32_WINNT=0xa00', @@ -115,10 +118,13 @@ if platform == 'windows' ) endif - dxvk_wsi = 'win32' dxvk_name_prefix = '' compiler_args += ['-DDXVK_WSI_WIN32'] else + dxvk_abi_version = '0' + dxvk_version = meson.project_version().strip('v').split('.') + dxvk_so_version = {'version': dxvk_abi_version + '.' + dxvk_version[0] + '.' + dxvk_version[1]} + wrc = find_program('touch') wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] ) @@ -128,17 +134,20 @@ else './include/native/directx' ] - dxvk_wsi = get_option('dxvk_native_wsi') - - if dxvk_wsi == 'sdl2' - lib_sdl2 = cpp.find_library('SDL2') + lib_sdl2 = dependency('SDL2', required: false) + lib_glfw = dependency('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_' + dxvk_name_prefix = 'dxvk_' + dxvk_pkg_prefix = 'dxvk-' link_args += [ '-static-libgcc', @@ -154,7 +163,6 @@ add_project_link_arguments(cpp.get_supported_link_arguments(link_args), language add_project_link_arguments(cc.get_supported_link_arguments(link_args), language: 'c') exe_ext = '' -dll_ext = '' def_spec_ext = '.def' glsl_compiler = find_program('glslang', 'glslangValidator') @@ -179,4 +187,8 @@ dxvk_version = vcs_tag( output: 'version.h', ) +if platform != 'windows' + subdir('include/native') +endif + subdir('src') diff --git a/src/d3d10/meson.build b/src/d3d10/meson.build index 51db067c..6a690c43 100644 --- a/src/d3d10/meson.build +++ b/src/d3d10/meson.build @@ -15,16 +15,23 @@ else d3d10_d3d11_dep = d3d11_dep endif -d3d10_core_dll = shared_library('d3d10core'+dll_ext, d3d10_core_src, d3d10_core_res, - name_prefix : dxvk_name_prefix, +d3d10_core_dll = shared_library(dxvk_name_prefix+'d3d10core', d3d10_core_src, d3d10_core_res, dependencies : [ d3d10_d3d11_dep ], include_directories : dxvk_include_path, install : true, vs_module_defs : 'd3d10core'+def_spec_ext, link_args : d3d10_core_ld_args, link_depends : [ d3d10_core_link_depends ], + kwargs : dxvk_so_version, ) d3d10_core_dep = declare_dependency( link_with : [ d3d10_core_dll ], ) + +if platform != 'windows' + pkg.generate(d3d10_core_dll, + filebase: dxvk_pkg_prefix + 'd3d10core', + subdirs: 'dxvk', + ) +endif diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index 9b51e6ea..20bec082 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -77,18 +77,25 @@ else d3d11_dxgi_dep = dxgi_dep endif -d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src, +d3d11_dll = shared_library(dxvk_name_prefix+'d3d11', dxgi_common_src + d3d11_src + d3d10_src, glsl_generator.process(d3d11_shaders), d3d11_res, - name_prefix : dxvk_name_prefix, dependencies : [ d3d11_dxgi_dep, dxbc_dep, dxvk_dep ], include_directories : dxvk_include_path, install : true, vs_module_defs : 'd3d11'+def_spec_ext, link_args : d3d11_ld_args, link_depends : [ d3d11_link_depends ], + kwargs : dxvk_so_version, ) d3d11_dep = declare_dependency( link_with : [ d3d11_dll ], include_directories : [ dxvk_include_path ], ) + +if platform != 'windows' + pkg.generate(d3d11_dll, + filebase: dxvk_pkg_prefix + 'd3d11', + subdirs: 'dxvk', + ) +endif diff --git a/src/d3d9/meson.build b/src/d3d9/meson.build index dd6b2316..bc3eac42 100644 --- a/src/d3d9/meson.build +++ b/src/d3d9/meson.build @@ -57,17 +57,24 @@ if platform != 'windows' d3d9_link_depends += files('d3d9.sym') endif -d3d9_dll = shared_library('d3d9'+dll_ext, d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res, - name_prefix : dxvk_name_prefix, +d3d9_dll = shared_library(dxvk_name_prefix+'d3d9', d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res, dependencies : [ dxso_dep, dxvk_dep ], include_directories : dxvk_include_path, install : true, vs_module_defs : 'd3d9'+def_spec_ext, link_args : d3d9_ld_args, link_depends : [ d3d9_link_depends ], + kwargs : dxvk_so_version, ) d3d9_dep = declare_dependency( link_with : [ d3d9_dll ], include_directories : [ dxvk_include_path ], ) + +if platform != 'windows' + pkg.generate(d3d9_dll, + filebase: dxvk_pkg_prefix + 'd3d9', + subdirs: 'dxvk', + ) +endif diff --git a/src/dxgi/meson.build b/src/dxgi/meson.build index a6e83b54..7c3f4320 100644 --- a/src/dxgi/meson.build +++ b/src/dxgi/meson.build @@ -21,17 +21,24 @@ if platform != 'windows' dxgi_link_depends += files('dxgi.sym') endif -dxgi_dll = shared_library('dxgi'+dll_ext, dxgi_src, dxgi_res, - name_prefix : dxvk_name_prefix, +dxgi_dll = shared_library(dxvk_name_prefix+'dxgi', dxgi_src, dxgi_res, dependencies : [ dxvk_dep ], include_directories : dxvk_include_path, install : true, vs_module_defs : 'dxgi'+def_spec_ext, link_args : dxgi_ld_args, link_depends : [ dxgi_link_depends ], + kwargs : dxvk_so_version, ) dxgi_dep = declare_dependency( link_with : [ dxgi_dll ], include_directories : [ dxvk_include_path ], ) + +if platform != 'windows' + pkg.generate(dxgi_dll, + filebase: dxvk_pkg_prefix + 'dxgi', + subdirs: 'dxvk', + ) +endif diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index bc204d3a..76ba78c5 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/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_monitor_glfw.cpp b/src/wsi/glfw/wsi_monitor_glfw.cpp index e450f83c..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" @@ -11,22 +13,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 +48,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool GlfwWsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { const int32_t displayId = fromHmonitor(hMonitor); @@ -97,7 +99,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool GlfwWsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t ModeNumber, WsiMode* pMode) { @@ -121,7 +123,7 @@ namespace dxvk::wsi { } - bool getCurrentDisplayMode( + bool GlfwWsiDriver::getCurrentDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -141,7 +143,7 @@ namespace dxvk::wsi { } - bool getDesktopDisplayMode( + bool GlfwWsiDriver::getDesktopDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -159,9 +161,11 @@ 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 {}; } } + +#endif diff --git a/src/wsi/glfw/wsi_platform_glfw.cpp b/src/wsi/glfw/wsi_platform_glfw.cpp new file mode 100644 index 00000000..ee818bb2 --- /dev/null +++ b/src/wsi/glfw/wsi_platform_glfw.cpp @@ -0,0 +1,71 @@ +#if defined(DXVK_WSI_GLFW) + +#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!")); + + 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; + } + + 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_platform_glfw.h b/src/wsi/glfw/wsi_platform_glfw.h index 25753494..849ce4f5 100644 --- a/src/wsi/glfw/wsi_platform_glfw.h +++ b/src/wsi/glfw/wsi_platform_glfw.h @@ -3,21 +3,108 @@ #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 { + 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(); + + // 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) { - int32_t displayCount = 0; - glfwGetMonitors(&displayCount); - return displayId < displayCount && displayId >= 0; - } - -} \ No newline at end of file +} 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/glfw/wsi_window_glfw.cpp b/src/wsi/glfw/wsi_window_glfw.cpp index 70031250..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" @@ -12,7 +14,7 @@ namespace dxvk::wsi { - void getWindowSize( + void GlfwWsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -29,7 +31,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void GlfwWsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t Width, @@ -40,7 +42,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool GlfwWsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& pMode) { @@ -67,7 +69,7 @@ namespace dxvk::wsi { return true; } - bool enterFullscreenMode( + bool GlfwWsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, @@ -89,7 +91,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool GlfwWsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -103,13 +105,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 +121,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 +143,6 @@ namespace dxvk::wsi { return glfwCreateWindowSurface(instance, window, nullptr, pSurface); } -} \ No newline at end of file +} + +#endif diff --git a/src/wsi/meson.build b/src/wsi/meson.build index 27603cea..4cfb13a8 100644 --- a/src/wsi/meson.build +++ b/src/wsi/meson.build @@ -1,33 +1,24 @@ -wsi_common_src = [ +wsi_src = [ 'wsi_edid.cpp', -] - -wsi_win32_src = [ + 'wsi_platform.cpp', '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 - 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') +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, diff --git a/src/wsi/sdl2/wsi_monitor_sdl2.cpp b/src/wsi/sdl2/wsi_monitor_sdl2.cpp index f0de7cd6..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" @@ -12,22 +14,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 +49,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool Sdl2WsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { const int32_t displayId = fromHmonitor(hMonitor); @@ -90,7 +92,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool Sdl2WsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t ModeNumber, WsiMode* pMode) { @@ -109,7 +111,7 @@ namespace dxvk::wsi { } - bool getCurrentDisplayMode( + bool Sdl2WsiDriver::getCurrentDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -129,7 +131,7 @@ namespace dxvk::wsi { } - bool getDesktopDisplayMode( + bool Sdl2WsiDriver::getDesktopDisplayMode( HMONITOR hMonitor, WsiMode* pMode) { const int32_t displayId = fromHmonitor(hMonitor); @@ -148,9 +150,11 @@ 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 {}; } } + +#endif diff --git a/src/wsi/sdl2/wsi_platform_sdl2.cpp b/src/wsi/sdl2/wsi_platform_sdl2.cpp new file mode 100644 index 00000000..9223b598 --- /dev/null +++ b/src/wsi/sdl2/wsi_platform_sdl2.cpp @@ -0,0 +1,69 @@ +#if defined(DXVK_WSI_SDL2) + +#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); + + 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; + } + + 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_platform_sdl2.h b/src/wsi/sdl2/wsi_platform_sdl2.h index 411fe8f6..1a6ac8aa 100644 --- a/src/wsi/sdl2/wsi_platform_sdl2.h +++ b/src/wsi/sdl2/wsi_platform_sdl2.h @@ -1,21 +1,108 @@ #pragma once -#include +#include -#include "../wsi_monitor.h" +#include "../wsi_platform.h" namespace dxvk::wsi { - /** - * \brief Impl-dependent state - */ - struct DxvkWindowState { + 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(); + + // 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) { - const int32_t displayCount = SDL_GetNumVideoDisplays(); - - return displayId < displayCount && displayId >= 0; - } -} \ No newline at end of file +} 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 diff --git a/src/wsi/sdl2/wsi_window_sdl2.cpp b/src/wsi/sdl2/wsi_window_sdl2.cpp index 1280b6c1..33084dc3 100644 --- a/src/wsi/sdl2/wsi_window_sdl2.cpp +++ b/src/wsi/sdl2/wsi_window_sdl2.cpp @@ -1,17 +1,19 @@ +#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" #include "../../util/log/log.h" #include -#include +#include namespace dxvk::wsi { - void getWindowSize( + void Sdl2WsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -28,7 +30,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void Sdl2WsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t Width, @@ -39,7 +41,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool Sdl2WsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& pMode) { @@ -73,7 +75,7 @@ namespace dxvk::wsi { - bool enterFullscreenMode( + bool Sdl2WsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, @@ -99,7 +101,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool Sdl2WsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -114,13 +116,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 +130,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 +144,7 @@ namespace dxvk::wsi { } - VkResult createSurface( + VkResult Sdl2WsiDriver::createSurface( HWND hWindow, PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, VkInstance instance, @@ -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 ae4a0ff3..0387d87f 100644 --- a/src/wsi/win32/wsi_monitor_win32.cpp +++ b/src/wsi/win32/wsi_monitor_win32.cpp @@ -1,4 +1,6 @@ -#include "../wsi_monitor.h" +#if defined(DXVK_WSI_WIN32) + +#include "wsi_platform_win32.h" #include "../../util/util_string.h" #include "../../util/log/log.h" @@ -13,7 +15,7 @@ namespace dxvk::wsi { - HMONITOR getDefaultMonitor() { + HMONITOR Win32WsiDriver::getDefaultMonitor() { return ::MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY); } @@ -45,7 +47,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 +60,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 +134,7 @@ namespace dxvk::wsi { } - bool getDisplayName( + bool Win32WsiDriver::getDisplayName( HMONITOR hMonitor, WCHAR (&Name)[32]) { // Query monitor info to get the device name @@ -150,7 +152,7 @@ namespace dxvk::wsi { } - bool getDesktopCoordinates( + bool Win32WsiDriver::getDesktopCoordinates( HMONITOR hMonitor, RECT* pRect) { ::MONITORINFOEXW monInfo; @@ -200,7 +202,7 @@ namespace dxvk::wsi { } - bool getDisplayMode( + bool Win32WsiDriver::getDisplayMode( HMONITOR hMonitor, uint32_t modeNumber, WsiMode* pMode) { @@ -208,14 +210,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 +310,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")); @@ -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 new file mode 100644 index 00000000..03bf40a5 --- /dev/null +++ b/src/wsi/win32/wsi_platform_win32.cpp @@ -0,0 +1,23 @@ +#if defined(DXVK_WSI_WIN32) + +#include "wsi_platform_win32.h" + +namespace dxvk::wsi { + + std::vector Win32WsiDriver::getInstanceExtensions() { + return { VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; + } + + static bool createWin32WsiDriver(WsiDriver **driver) { + *driver = new Win32WsiDriver(); + return true; + } + + WsiBootstrap Win32WSI = { + "Win32", + createWin32WsiDriver + }; + +} + +#endif 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..894da8e7 100644 --- a/src/wsi/win32/wsi_window_win32.cpp +++ b/src/wsi/win32/wsi_window_win32.cpp @@ -1,5 +1,6 @@ -#include "../wsi_window.h" -#include "../wsi_monitor.h" +#if defined(DXVK_WSI_WIN32) + +#include "wsi_platform_win32.h" #include "../../util/util_string.h" #include "../../util/log/log.h" @@ -94,7 +95,7 @@ namespace dxvk::wsi { } - void getWindowSize( + void Win32WsiDriver::getWindowSize( HWND hWindow, uint32_t* pWidth, uint32_t* pHeight) { @@ -109,7 +110,7 @@ namespace dxvk::wsi { } - void resizeWindow( + void Win32WsiDriver::resizeWindow( HWND hWindow, DxvkWindowState* pState, uint32_t width, @@ -130,7 +131,7 @@ namespace dxvk::wsi { } - bool setWindowMode( + bool Win32WsiDriver::setWindowMode( HMONITOR hMonitor, HWND hWindow, const WsiMode& mode) { @@ -163,21 +164,21 @@ namespace dxvk::wsi { } - bool enterFullscreenMode( + bool Win32WsiDriver::enterFullscreenMode( HMONITOR hMonitor, HWND hWindow, DxvkWindowState* pState, [[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; @@ -196,7 +197,7 @@ namespace dxvk::wsi { } - bool leaveFullscreenMode( + bool Win32WsiDriver::leaveFullscreenMode( HWND hWindow, DxvkWindowState* pState, bool restoreCoordinates) { @@ -205,27 +206,27 @@ 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; } - bool restoreDisplayMode() { + bool Win32WsiDriver::restoreDisplayMode() { bool success = true; bool result = ::EnumDisplayMonitors(nullptr, nullptr, &restoreDisplayModeCallback, @@ -235,7 +236,7 @@ namespace dxvk::wsi { } - HMONITOR getWindowMonitor(HWND hWindow) { + HMONITOR Win32WsiDriver::getWindowMonitor(HWND hWindow) { RECT windowRect = { 0, 0, 0, 0 }; ::GetWindowRect(hWindow, &windowRect); @@ -248,12 +249,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 +275,7 @@ namespace dxvk::wsi { } - VkResult createSurface( + VkResult Win32WsiDriver::createSurface( HWND hWindow, PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr, VkInstance instance, @@ -296,3 +297,5 @@ namespace dxvk::wsi { } } + +#endif diff --git a/src/wsi/wsi_platform.cpp b/src/wsi/wsi_platform.cpp new file mode 100644 index 00000000..27a342b2 --- /dev/null +++ b/src/wsi/wsi_platform.cpp @@ -0,0 +1,169 @@ +#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; + + 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."); + } + + 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 38b5c5aa..8c37bc94 100644 --- a/src/wsi/wsi_platform.h +++ b/src/wsi/wsi_platform.h @@ -1,9 +1,114 @@ #pragma once +#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; + }; + + struct WsiBootstrap { + const std::string name; + bool (*createDriver)(WsiDriver **driver); + }; + #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" + 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(); + +} diff --git a/src/wsi/wsi_window.h b/src/wsi/wsi_window.h index e0587a0f..ceb14923 100644 --- a/src/wsi/wsi_window.h +++ b/src/wsi/wsi_window.h @@ -3,12 +3,30 @@ #include #include "wsi_monitor.h" -#include "wsi_platform.h" #include "../vulkan/vulkan_loader.h" namespace dxvk::wsi { + /** + * \brief Impl-dependent state + */ + struct DxvkWindowState { +#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 + }; + /** * \brief The size of the window *