Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ As an alternative for the default wine based build DXMT can be built natively on
meson setup --native-file build-osx.txt -Ddxmt_native=true -Dnative_llvm_path=toolchains/llvm-darwin build
meson compile -C build
```
The following WSI backends are present: headless, SDL2 and SDL3. You can hint which one to use at compile-time via the `-Ddxmt_wsi_sdl2=true` or `-Ddxmt_wsi_sdl3=true` flags. (headless is selected by default).
10 changes: 10 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ add_project_arguments('-DDXMT_NATIVE=1', language: 'cpp')
add_project_arguments('-DDXMT_NATIVE=1', language: 'c')
endif

if get_option('dxmt_wsi_sdl2') == true
add_project_arguments('-DDXMT_WSI_SDL2=1', language: 'cpp')
add_project_arguments('-DDXMT_WSI_SDL2=1', language: 'c')
endif

if get_option('dxmt_wsi_sdl3') == true
add_project_arguments('-DDXMT_WSI_SDL3=1', language: 'cpp')
add_project_arguments('-DDXMT_WSI_SDL3=1', language: 'c')
endif

add_project_arguments('-DDXMT_PAGE_SIZE=4096', language: 'cpp')

dxmt_version = vcs_tag(
Expand Down
2 changes: 2 additions & 0 deletions meson.options
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ option('native_llvm_path', type : 'string', value: '/usr/local/opt/llvm@15')
option('build_airconv_for_windows', type : 'boolean', value : false)
option('dxmt_debug', type : 'boolean', value : false)
option('dxmt_native', type : 'boolean', value : false)
option('dxmt_wsi_sdl2', type : 'boolean', value : false)
option('dxmt_wsi_sdl3', type : 'boolean', value : false)
option('wine_build_path', type : 'string')
option('wine_install_path', type : 'string')
option('wine_builtin_dll', type : 'boolean', value : false)
Expand Down
8 changes: 8 additions & 0 deletions src/d3d11/d3d11_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,21 @@ class MTLD3D11SwapChain final : public MTLDXGISubObject<IDXGISwapChain4, MTLD3D1
hWnd(hWnd),
monitor_(wsi::getWindowMonitor(hWnd)),
hud(WMT::DeveloperHUDProperties::instance()) {
#if defined(DXMT_WSI_SDL2) || defined(DXMT_WSI_SDL3)
native_view_ = wsi::createMetalViewFromHWND((intptr_t)hWnd, pDevice->GetMTLDevice(), layer_weak_);

if (!native_view_) {
ERR("Failed to create metal view.");
abort();
}
#else
native_view_ = WMT::CreateMetalViewFromHWND((intptr_t)hWnd, pDevice->GetMTLDevice(), layer_weak_);

if (!native_view_) {
ERR("Failed to create metal view, it seems like your Wine has no exported symbols needed by DXMT.");
abort();
}
#endif

if constexpr (EnableMetalFX) {
scale_factor = std::max(Config::getInstance().getOption<float>("d3d11.metalSpatialUpscaleFactor", 2), 1.0f);
Expand Down
35 changes: 30 additions & 5 deletions src/util/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,36 @@ util_src = files([
'sha1/sha1_util.cpp',
])

wsi_deps = []

if dxmt_native
util_src += files([
'wsi_monitor_headless.cpp',
'wsi_window_headless.cpp',
'wsi_platform_darwin.cpp',
])
if get_option('dxmt_wsi_sdl2') == true
lib_sdl2 = dependency('SDL2', required: true)

util_src += files([
'wsi_monitor_sdl2.cpp',
'wsi_window_sdl2.cpp',
'wsi_platform_sdl2.cpp',
])

wsi_deps += [ lib_sdl2.partial_dependency(compile_args: true, includes: true)]
elif get_option('dxmt_wsi_sdl3') == true
lib_sdl3 = dependency('SDL3', required: true)

util_src += files([
'wsi_monitor_sdl3.cpp',
'wsi_window_sdl3.cpp',
'wsi_platform_sdl3.cpp',
])

wsi_deps += [ lib_sdl3.partial_dependency(compile_args: true, includes: true)]
else
util_src += files([
'wsi_monitor_headless.cpp',
'wsi_window_headless.cpp',
])
endif
util_src += files(['wsi_platform_darwin.cpp'])
else
util_src += files([
'wsi_monitor_win32.cpp',
Expand All @@ -38,6 +62,7 @@ else
endif

util_lib = static_library('util', util_src,
dependencies: wsi_deps,
include_directories : [ dxmt_include_path ],
)

Expand Down
6 changes: 5 additions & 1 deletion src/util/wsi_monitor_headless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* See <https://github.com/doitsujin/dxvk/blob/master/LICENSE>
*/

#if !defined(DXMT_WSI_SDL2) && !defined(DXMT_WSI_SDL3)

#include "wsi_monitor.hpp"

namespace dxmt::wsi {
Expand Down Expand Up @@ -45,4 +47,6 @@ bool getDesktopDisplayMode(HMONITOR hMonitor, WsiMode *pMode) {
return retrieveDisplayMode(hMonitor, ENUM_REGISTRY_SETTINGS, pMode);
}

} // namespace dxmt::wsi
} // namespace dxmt::wsi

#endif // !defined(DXMT_WSI_SDL2) && !defined(DXMT_WSI_SDL3)
120 changes: 120 additions & 0 deletions src/util/wsi_monitor_sdl2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#if defined(DXMT_WSI_SDL2)

#include "wsi_monitor.hpp"
#include "wsi_platform_sdl2.hpp"

#include "log/log.hpp"
#include "util_string.hpp"

#include <SDL.h>

#include <cstring>

namespace dxmt::wsi {

HMONITOR enumMonitors(uint32_t index) {
if (!isValidDisplay(index)) {
Logger::err(str::format("SDL2 WSI: Failed to get display for index ", index));
return nullptr;
}
return toHmonitor((int32_t)index);
}

HMONITOR getDefaultMonitor() {
return enumMonitors(0);
}

bool getDisplayName(HMONITOR hMonitor, WCHAR (&Name)[32]) {
int32_t display_id = fromHmonitor(hMonitor);
if (!isValidDisplay(display_id)) {
Logger::err("SDL2 WSI: Invalid display ID for monitor");
return false;
}

std::wstringstream display_name;
display_name << L"\\\\.\\DISPLAY" << display_id;
std::wstring display_name_str = display_name.str();

std::memset(Name, 0, sizeof(WCHAR) * 32);
if (display_name_str.length() >= 32) {
Logger::err("SDL2 WSI: Display name exceeds maximum length of 32 characters");
return false;
}
display_name_str.copy(Name, display_name_str.length(), 0);

return true;
}

bool getDesktopCoordinates(HMONITOR hMonitor, RECT *pRect) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

SDL_Rect rect = { };
SDL2Initializer::get().SDL_GetDisplayBounds(displayId, &rect);

pRect->left = rect.x;
pRect->top = rect.y;
pRect->right = rect.x + rect.w;
pRect->bottom = rect.y + rect.h;

return true;
}

bool getDisplayMode(HMONITOR hMonitor, uint32_t modeNumber, WsiMode *pMode) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

SDL_DisplayMode mode = { };
if (SDL2Initializer::get().SDL_GetDisplayMode(displayId, modeNumber, &mode) != 0)
return false;

pMode->width = uint32_t(mode.w);
pMode->height = uint32_t(mode.h);
pMode->refreshRate = WsiRational{ uint32_t(mode.refresh_rate) * 1000, 1000 };
pMode->bitsPerPixel = roundToNextPow2(SDL_BITSPERPIXEL(mode.format));
pMode->interlaced = false;

return true;
}

bool getCurrentDisplayMode(HMONITOR hMonitor, WsiMode *pMode) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

SDL_DisplayMode mode = { };
if (SDL2Initializer::get().SDL_GetCurrentDisplayMode(displayId, &mode) != 0) {
Logger::err(str::format("SDL_GetCurrentDisplayMode: ", SDL2Initializer::get().SDL_GetError()));
return false;
}

convertMode(mode, pMode);

return true;
}

bool getDesktopDisplayMode(HMONITOR hMonitor, WsiMode *pMode) {
const int32_t displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

SDL_DisplayMode mode = { };
if (SDL2Initializer::get().SDL_GetDesktopDisplayMode(displayId, &mode) != 0) {
Logger::err(str::format("SDL_GetCurrentDisplayMode: ", SDL2Initializer::get().SDL_GetError()));
return false;
}

convertMode(mode, pMode);

return true;
}

} // namespace dxmt::wsi

#endif // defined(DXMT_WSI_SDL2)
133 changes: 133 additions & 0 deletions src/util/wsi_monitor_sdl3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#if defined(DXMT_WSI_SDL3)

#include "wsi_monitor.hpp"
#include "wsi_platform_sdl3.hpp"

#include "log/log.hpp"
#include "util_string.hpp"

#include <SDL3/SDL.h>

#include <cstring>

namespace dxmt::wsi {

HMONITOR enumMonitors(uint32_t index) {
int count = 0;
SDL_DisplayID *displays = SDL3Initializer::get().SDL_GetDisplays(&count);
if (!displays || int(index) >= count) {
Logger::err(str::format("SDL3 WSI: Failed to get display for index ", index));
if (displays)
SDL3Initializer::get().SDL_free(displays);
return nullptr;
}
SDL_DisplayID displayId = displays[index];
SDL3Initializer::get().SDL_free(displays);
return toHmonitor(displayId);
}

HMONITOR getDefaultMonitor() {
return enumMonitors(0);
}

bool getDisplayName(HMONITOR hMonitor, WCHAR (&Name)[32]) {
SDL_DisplayID displayId = fromHmonitor(hMonitor);
if (!isValidDisplay(displayId)) {
Logger::err("SDL3 WSI: Invalid display ID for monitor");
return false;
}

std::wstringstream display_name;
display_name << L"\\\\.\\DISPLAY" << displayId;
std::wstring display_name_str = display_name.str();

std::memset(Name, 0, sizeof(WCHAR) * 32);
if (display_name_str.length() >= 32) {
Logger::err("SDL3 WSI: Display name exceeds maximum length of 32 characters");
return false;
}
display_name_str.copy(Name, display_name_str.length(), 0);

return true;
}

bool getDesktopCoordinates(HMONITOR hMonitor, RECT *pRect) {
const SDL_DisplayID displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

SDL_Rect rect = { };
SDL3Initializer::get().SDL_GetDisplayBounds(displayId, &rect);

pRect->left = rect.x;
pRect->top = rect.y;
pRect->right = rect.x + rect.w;
pRect->bottom = rect.y + rect.h;

return true;
}

bool getDisplayMode(HMONITOR hMonitor, uint32_t modeNumber, WsiMode *pMode) {
const SDL_DisplayID displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

int count = 0;
SDL_DisplayMode **modes = SDL3Initializer::get().SDL_GetFullscreenDisplayModes(displayId, &count);
if (!modes || int(modeNumber) >= count) {
if (modes)
SDL3Initializer::get().SDL_free(modes);
return false;
}

const SDL_DisplayMode *mode = modes[modeNumber];
pMode->width = uint32_t(mode->w);
pMode->height = uint32_t(mode->h);
pMode->refreshRate = WsiRational{ uint32_t(mode->refresh_rate) * 1000, 1000 };
pMode->bitsPerPixel = roundToNextPow2(SDL_BITSPERPIXEL(mode->format));
pMode->interlaced = false;

SDL3Initializer::get().SDL_free(modes);

return true;
}

bool getCurrentDisplayMode(HMONITOR hMonitor, WsiMode *pMode) {
const SDL_DisplayID displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

const SDL_DisplayMode *mode = SDL3Initializer::get().SDL_GetCurrentDisplayMode(displayId);
if (!mode) {
Logger::err(str::format("SDL_GetCurrentDisplayMode: ", SDL3Initializer::get().SDL_GetError()));
return false;
}

convertMode(*mode, pMode);

return true;
}

bool getDesktopDisplayMode(HMONITOR hMonitor, WsiMode *pMode) {
const SDL_DisplayID displayId = fromHmonitor(hMonitor);

if (!isValidDisplay(displayId))
return false;

const SDL_DisplayMode *mode = SDL3Initializer::get().SDL_GetDesktopDisplayMode(displayId);
if (!mode) {
Logger::err(str::format("SDL_GetDesktopDisplayMode: ", SDL3Initializer::get().SDL_GetError()));
return false;
}

convertMode(*mode, pMode);

return true;
}

} // namespace dxmt::wsi

#endif // defined(DXMT_WSI_SDL3)
Loading