Abstract SDL_SysWM into compat functions

This commit is contained in:
Cameron Gutman 2025-01-30 21:02:13 -06:00
parent dd2a99a96b
commit 13b2b28c2f
20 changed files with 347 additions and 246 deletions

209
app/SDL_compat.c Normal file
View File

@ -0,0 +1,209 @@
#include "SDL_compat.h"
#include <SDL_syswm.h>
void* SDLC_Win32_GetHwnd(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_WINDOWS
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return NULL;
}
if (info.subsystem == SDL_SYSWM_WINDOWS) {
return info.info.win.window;
}
#else
(void)window;
#endif
return NULL;
}
void* SDLC_MacOS_GetWindow(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_COCOA
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return NULL;
}
if (info.subsystem == SDL_SYSWM_COCOA) {
return info.info.cocoa.window;
}
#else
(void)window;
#endif
return NULL;
}
void* SDLC_X11_GetDisplay(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_X11
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return NULL;
}
if (info.subsystem == SDL_SYSWM_X11) {
return info.info.x11.display;
}
#else
(void)window;
#endif
return NULL;
}
unsigned long SDLC_X11_GetWindow(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_X11
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return 0;
}
if (info.subsystem == SDL_SYSWM_X11) {
return info.info.x11.window;
}
#else
(void)window;
#endif
return 0;
}
void* SDLC_Wayland_GetDisplay(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_WAYLAND
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return NULL;
}
if (info.subsystem == SDL_SYSWM_WAYLAND) {
return info.info.wl.display;
}
#else
(void)window;
#endif
return NULL;
}
void* SDLC_Wayland_GetSurface(SDL_Window* window)
{
#ifdef SDL_VIDEO_DRIVER_WAYLAND
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return NULL;
}
if (info.subsystem == SDL_SYSWM_WAYLAND) {
return info.info.wl.surface;
}
#else
(void)window;
#endif
return NULL;
}
int SDLC_KMSDRM_GetFd(SDL_Window* window)
{
#if defined(SDL_VIDEO_DRIVER_KMSDRM) && SDL_VERSION_ATLEAST(2, 0, 15)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return -1;
}
if (info.subsystem == SDL_SYSWM_KMSDRM) {
return info.info.kmsdrm.drm_fd;
}
#else
(void)window;
#endif
return -1;
}
int SDLC_KMSDRM_GetDevIndex(SDL_Window* window)
{
#if defined(SDL_VIDEO_DRIVER_KMSDRM) && SDL_VERSION_ATLEAST(2, 0, 15)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return -1;
}
if (info.subsystem == SDL_SYSWM_KMSDRM) {
return info.info.kmsdrm.dev_index;
}
#else
(void)window;
#endif
return -1;
}
SDLC_VideoDriver SDLC_GetVideoDriver(void)
{
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
return SDLC_VIDEO_WIN32;
#elif defined(SDL_VIDEO_DRIVER_COCOA)
return SDLC_VIDEO_MACOS;
#else
const char* videoDriver = SDL_GetCurrentVideoDriver();
if (SDL_strcmp(videoDriver, "x11") == 0) {
return SDLC_VIDEO_X11;
}
else if (SDL_strcmp(videoDriver, "wayland") == 0) {
return SDLC_VIDEO_WAYLAND;
}
else if (SDL_strcmp(videoDriver, "kmsdrm") == 0) {
return SDLC_VIDEO_KMSDRM;
}
else {
SDL_assert(0);
return SDLC_VIDEO_UNKNOWN;
}
#endif
}

View File

@ -7,6 +7,11 @@
#include <SDL.h> #include <SDL.h>
// This is a pure C header for compatibility with SDL.h
#ifdef __cplusplus
extern "C" {
#endif
// SDL_FRect wasn't added until 2.0.10 // SDL_FRect wasn't added until 2.0.10
#if !SDL_VERSION_ATLEAST(2, 0, 10) #if !SDL_VERSION_ATLEAST(2, 0, 10)
typedef struct SDL_FRect typedef struct SDL_FRect
@ -65,3 +70,26 @@ typedef struct SDL_FRect
#ifndef SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP #ifndef SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP
#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" #define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP"
#endif #endif
void* SDLC_Win32_GetHwnd(SDL_Window* window);
void* SDLC_MacOS_GetWindow(SDL_Window* window);
void* SDLC_X11_GetDisplay(SDL_Window* window);
unsigned long SDLC_X11_GetWindow(SDL_Window* window);
void* SDLC_Wayland_GetDisplay(SDL_Window* window);
void* SDLC_Wayland_GetSurface(SDL_Window* window);
int SDLC_KMSDRM_GetFd(SDL_Window* window);
int SDLC_KMSDRM_GetDevIndex(SDL_Window* window);
typedef enum {
SDLC_VIDEO_UNKNOWN,
SDLC_VIDEO_WIN32,
SDLC_VIDEO_MACOS,
SDLC_VIDEO_X11,
SDLC_VIDEO_WAYLAND,
SDLC_VIDEO_KMSDRM,
} SDLC_VideoDriver;
SDLC_VideoDriver SDLC_GetVideoDriver();
#ifdef __cplusplus
}
#endif

View File

@ -174,6 +174,7 @@ macx {
} }
SOURCES += \ SOURCES += \
SDL_compat.c \
backend/nvaddress.cpp \ backend/nvaddress.cpp \
backend/nvapp.cpp \ backend/nvapp.cpp \
cli/pair.cpp \ cli/pair.cpp \

View File

@ -2,9 +2,13 @@
#include <Limelight.h> #include <Limelight.h>
#include "SDL_compat.h" #include "SDL_compat.h"
#include <SDL_syswm.h>
#include "streaming/streamutils.h" #include "streaming/streamutils.h"
#ifdef Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include <QtMath> #include <QtMath>
// How long the fingers must be stationary to start a right click // How long the fingers must be stationary to start a right click
@ -30,33 +34,27 @@ Uint32 SdlInputHandler::longPressTimerCallback(Uint32, void*)
void SdlInputHandler::disableTouchFeedback() void SdlInputHandler::disableTouchFeedback()
{ {
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(m_Window, &info);
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
if (info.subsystem == SDL_SYSWM_WINDOWS) { auto fnSetWindowFeedbackSetting = (decltype(SetWindowFeedbackSetting)*)GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetWindowFeedbackSetting");
auto fnSetWindowFeedbackSetting = (decltype(SetWindowFeedbackSetting)*)GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetWindowFeedbackSetting"); if (fnSetWindowFeedbackSetting) {
if (fnSetWindowFeedbackSetting) { constexpr FEEDBACK_TYPE feedbackTypes[] = {
constexpr FEEDBACK_TYPE feedbackTypes[] = { FEEDBACK_TOUCH_CONTACTVISUALIZATION,
FEEDBACK_TOUCH_CONTACTVISUALIZATION, FEEDBACK_PEN_BARRELVISUALIZATION,
FEEDBACK_PEN_BARRELVISUALIZATION, FEEDBACK_PEN_TAP,
FEEDBACK_PEN_TAP, FEEDBACK_PEN_DOUBLETAP,
FEEDBACK_PEN_DOUBLETAP, FEEDBACK_PEN_PRESSANDHOLD,
FEEDBACK_PEN_PRESSANDHOLD, FEEDBACK_PEN_RIGHTTAP,
FEEDBACK_PEN_RIGHTTAP, FEEDBACK_TOUCH_TAP,
FEEDBACK_TOUCH_TAP, FEEDBACK_TOUCH_DOUBLETAP,
FEEDBACK_TOUCH_DOUBLETAP, FEEDBACK_TOUCH_PRESSANDHOLD,
FEEDBACK_TOUCH_PRESSANDHOLD, FEEDBACK_TOUCH_RIGHTTAP,
FEEDBACK_TOUCH_RIGHTTAP, FEEDBACK_GESTURE_PRESSANDTAP,
FEEDBACK_GESTURE_PRESSANDTAP, };
};
for (FEEDBACK_TYPE ft : feedbackTypes) { HWND window = (HWND)SDLC_Win32_GetHwnd(m_Window);
BOOL val = FALSE; for (FEEDBACK_TYPE ft : feedbackTypes) {
fnSetWindowFeedbackSetting(info.info.win.window, ft, 0, sizeof(val), &val); BOOL val = FALSE;
} fnSetWindowFeedbackSetting(window, ft, 0, sizeof(val), &val);
} }
} }
#endif #endif

View File

@ -24,7 +24,6 @@
// HACK: Remove once proper Dark Mode support lands in SDL // HACK: Remove once proper Dark Mode support lands in SDL
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
#include <SDL_syswm.h>
#include <dwmapi.h> #include <dwmapi.h>
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE_OLD #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE_OLD
#define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19 #define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19
@ -1867,23 +1866,20 @@ void Session::execInternal()
darkModeEnabled = FALSE; darkModeEnabled = FALSE;
} }
SDL_SysWMinfo info; // If dark mode is enabled, propagate that to our SDL window
SDL_VERSION(&info.version); if (darkModeEnabled) {
HWND hwnd = (HWND)SDLC_Win32_GetHwnd(m_Window);
if (SDL_GetWindowWMInfo(m_Window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) { if (FAILED(DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &darkModeEnabled, sizeof(darkModeEnabled)))) {
// If dark mode is enabled, propagate that to our SDL window DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE_OLD, &darkModeEnabled, sizeof(darkModeEnabled));
if (darkModeEnabled) {
if (FAILED(DwmSetWindowAttribute(info.info.win.window, DWMWA_USE_IMMERSIVE_DARK_MODE, &darkModeEnabled, sizeof(darkModeEnabled)))) {
DwmSetWindowAttribute(info.info.win.window, DWMWA_USE_IMMERSIVE_DARK_MODE_OLD, &darkModeEnabled, sizeof(darkModeEnabled));
}
// Toggle non-client rendering off and back on to ensure dark mode takes effect on Windows 10.
// DWM doesn't seem to correctly invalidate the non-client area after enabling dark mode.
DWMNCRENDERINGPOLICY ncPolicy = DWMNCRP_DISABLED;
DwmSetWindowAttribute(info.info.win.window, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
ncPolicy = DWMNCRP_ENABLED;
DwmSetWindowAttribute(info.info.win.window, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
} }
// Toggle non-client rendering off and back on to ensure dark mode takes effect on Windows 10.
// DWM doesn't seem to correctly invalidate the non-client area after enabling dark mode.
DWMNCRENDERINGPOLICY ncPolicy = DWMNCRP_DISABLED;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
ncPolicy = DWMNCRP_ENABLED;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
} }
} }
#endif #endif

View File

@ -14,8 +14,6 @@
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <SDL_syswm.h>
#endif #endif
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
@ -318,38 +316,28 @@ int StreamUtils::getDrmFdForWindow(SDL_Window* window, bool* mustClose)
{ {
*mustClose = false; *mustClose = false;
#if defined(SDL_VIDEO_DRIVER_KMSDRM) && SDL_VERSION_ATLEAST(2, 0, 15) // If SDL has an FD, share that
SDL_SysWMinfo info; int fd = SDLC_KMSDRM_GetFd(window);
SDL_VERSION(&info.version); if (fd >= 0) {
if (!SDL_GetWindowWMInfo(window, &info)) { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Sharing DRM FD with SDL");
"SDL_GetWindowWMInfo() failed: %s", return fd;
SDL_GetError());
return -1;
} }
if (info.subsystem == SDL_SYSWM_KMSDRM) { #ifdef Q_OS_UNIX
// If SDL has an FD, share that int devIndex = SDLC_KMSDRM_GetDevIndex(window);
if (info.info.kmsdrm.drm_fd >= 0) { if (devIndex >= 0) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, char path[128];
"Sharing DRM FD with SDL"); snprintf(path, sizeof(path), "/dev/dri/card%u", devIndex);
return info.info.kmsdrm.drm_fd; SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
} "Opening DRM FD from SDL by path: %s",
else { path);
char path[128]; int fd = open(path, O_RDWR | O_CLOEXEC);
snprintf(path, sizeof(path), "/dev/dri/card%u", info.info.kmsdrm.dev_index); if (fd >= 0) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, *mustClose = true;
"Opening DRM FD from SDL by path: %s",
path);
int fd = open(path, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
*mustClose = true;
}
return fd;
} }
return fd;
} }
#else
Q_UNUSED(window);
#endif #endif
return -1; return -1;

View File

@ -8,7 +8,6 @@
#include "streaming/streamutils.h" #include "streaming/streamutils.h"
#include "streaming/session.h" #include "streaming/session.h"
#include <SDL_syswm.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <dwmapi.h> #include <dwmapi.h>
@ -435,16 +434,13 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
} }
} }
SDL_SysWMinfo info; HWND window = (HWND)SDLC_Win32_GetHwnd(params->window);
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(params->window, &info);
SDL_assert(info.subsystem == SDL_SYSWM_WINDOWS);
// Always use windowed or borderless windowed mode.. SDL does mode-setting for us in // Always use windowed or borderless windowed mode.. SDL does mode-setting for us in
// full-screen exclusive mode (SDL_WINDOW_FULLSCREEN), so this actually works out okay. // full-screen exclusive mode (SDL_WINDOW_FULLSCREEN), so this actually works out okay.
ComPtr<IDXGISwapChain1> swapChain; ComPtr<IDXGISwapChain1> swapChain;
hr = m_Factory->CreateSwapChainForHwnd(m_Device.Get(), hr = m_Factory->CreateSwapChainForHwnd(m_Device.Get(),
info.info.win.window, window,
&swapChainDesc, &swapChainDesc,
nullptr, nullptr,
nullptr, nullptr,
@ -468,7 +464,7 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
// Disable Alt+Enter, PrintScreen, and window message snooping. This makes // Disable Alt+Enter, PrintScreen, and window message snooping. This makes
// it safe to run the renderer on a separate rendering thread rather than // it safe to run the renderer on a separate rendering thread rather than
// requiring the main (message loop) thread. // requiring the main (message loop) thread.
hr = m_Factory->MakeWindowAssociation(info.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES); hr = m_Factory->MakeWindowAssociation(window, DXGI_MWA_NO_WINDOW_CHANGES);
if (FAILED(hr)) { if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGIFactory::MakeWindowAssociation() failed: %x", "IDXGIFactory::MakeWindowAssociation() failed: %x",

View File

@ -9,8 +9,6 @@
#include <streaming/streamutils.h> #include <streaming/streamutils.h>
#include <streaming/session.h> #include <streaming/session.h>
#include <SDL_syswm.h>
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
@ -541,11 +539,6 @@ bool DXVA2Renderer::isDecoderBlacklisted()
bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync) bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
{ {
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(window, &info);
ComPtr<IDirect3D9Ex> d3d9ex; ComPtr<IDirect3D9Ex> d3d9ex;
HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex); HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
if (FAILED(hr)) { if (FAILED(hr)) {
@ -572,7 +565,7 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
d3d9ex->GetAdapterDisplayModeEx(adapterIndex, &currentMode, nullptr); d3d9ex->GetAdapterDisplayModeEx(adapterIndex, &currentMode, nullptr);
D3DPRESENT_PARAMETERS d3dpp = {}; D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.hDeviceWindow = info.info.win.window; d3dpp.hDeviceWindow = (HWND)SDLC_Win32_GetHwnd(window);
d3dpp.Flags = D3DPRESENTFLAG_VIDEO; d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
if (m_VideoFormat & VIDEO_FORMAT_MASK_10BIT) { if (m_VideoFormat & VIDEO_FORMAT_MASK_10BIT) {

View File

@ -11,7 +11,6 @@
#include <unistd.h> #include <unistd.h>
#include <SDL_render.h> #include <SDL_render.h>
#include <SDL_syswm.h>
// These are extensions, so some platform headers may not provide them // These are extensions, so some platform headers may not provide them
#ifndef EGL_PLATFORM_WAYLAND_KHR #ifndef EGL_PLATFORM_WAYLAND_KHR
@ -485,12 +484,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
return false; return false;
} }
SDL_SysWMinfo info; SDLC_VideoDriver videoDriver = SDLC_GetVideoDriver();
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(params->window, &info)) {
EGL_LOG(Error, "SDL_GetWindowWMInfo() failed: %s", SDL_GetError());
return false;
}
if (!(m_Context = SDL_GL_CreateContext(params->window))) { if (!(m_Context = SDL_GL_CreateContext(params->window))) {
EGL_LOG(Error, "Cannot create OpenGL context: %s", SDL_GetError()); EGL_LOG(Error, "Cannot create OpenGL context: %s", SDL_GetError());
@ -597,21 +591,14 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
// the Wayland viewport can be stale when using Super+Left/Right/Up // the Wayland viewport can be stale when using Super+Left/Right/Up
// to resize the window. This seems to happen significantly more often // to resize the window. This seems to happen significantly more often
// with vsync enabled, so this also mitigates that problem too. // with vsync enabled, so this also mitigates that problem too.
if (params->enableVsync if (params->enableVsync && videoDriver != SDLC_VIDEO_WAYLAND) {
#ifdef SDL_VIDEO_DRIVER_WAYLAND
&& info.subsystem != SDL_SYSWM_WAYLAND
#endif
) {
SDL_GL_SetSwapInterval(1); SDL_GL_SetSwapInterval(1);
#if SDL_VERSION_ATLEAST(2, 0, 15) && defined(SDL_VIDEO_DRIVER_KMSDRM)
// The SDL KMSDRM backend already enforces double buffering (due to // The SDL KMSDRM backend already enforces double buffering (due to
// SDL_HINT_VIDEO_DOUBLE_BUFFER=1), so calling glFinish() after // SDL_HINT_VIDEO_DOUBLE_BUFFER=1), so calling glFinish() after
// SDL_GL_SwapWindow() will block an extra frame and lock rendering // SDL_GL_SwapWindow() will block an extra frame and lock rendering
// at 1/2 the display refresh rate. // at 1/2 the display refresh rate.
if (info.subsystem != SDL_SYSWM_KMSDRM) if (videoDriver != SDLC_VIDEO_KMSDRM) {
#endif
{
m_BlockingSwapBuffers = true; m_BlockingSwapBuffers = true;
} }
} else { } else {

View File

@ -5,13 +5,6 @@
#include <Limelight.h> #include <Limelight.h>
// HACK: Avoid including X11 headers which conflict with QDir
#ifdef SDL_VIDEO_DRIVER_X11
#undef SDL_VIDEO_DRIVER_X11
#endif
#include <SDL_syswm.h>
#include <QDir> #include <QDir>
#include <QTextStream> #include <QTextStream>

View File

@ -47,21 +47,7 @@ bool DxVsyncSource::initialize(SDL_Window* window, int)
return false; return false;
} }
SDL_SysWMinfo info; m_Window = (HWND)SDLC_Win32_GetHwnd(window);
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
// Pacer should only create us on Win32
SDL_assert(info.subsystem == SDL_SYSWM_WINDOWS);
m_Window = info.info.win.window;
return true; return true;
} }

View File

@ -2,7 +2,8 @@
#include "pacer.h" #include "pacer.h"
#include <SDL_syswm.h> #define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// from <D3dkmthk.h> // from <D3dkmthk.h>
typedef LONG NTSTATUS; typedef LONG NTSTATUS;

View File

@ -2,18 +2,14 @@
#include "streaming/streamutils.h" #include "streaming/streamutils.h"
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <VersionHelpers.h>
#include "dxvsyncsource.h" #include "dxvsyncsource.h"
#include <VersionHelpers.h>
#endif #endif
#ifdef HAS_WAYLAND #ifdef HAS_WAYLAND
#include "waylandvsyncsource.h" #include "waylandvsyncsource.h"
#endif #endif
#include <SDL_syswm.h>
// Limit the number of queued frames to prevent excessive memory consumption // Limit the number of queued frames to prevent excessive memory consumption
// if the V-Sync source or renderer is blocked for a while. It's important // if the V-Sync source or renderer is blocked for a while. It's important
// that the sum of all queued frames between both pacing and rendering queues // that the sum of all queued frames between both pacing and rendering queues
@ -267,31 +263,22 @@ bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enablePacing)
"Frame pacing: target %d Hz with %d FPS stream", "Frame pacing: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps); m_DisplayFps, m_MaxVideoFps);
SDL_SysWMinfo info; switch (SDLC_GetVideoDriver()) {
SDL_VERSION(&info.version); case SDLC_VIDEO_WIN32:
if (!SDL_GetWindowWMInfo(window, &info)) { #ifdef Q_OS_WIN32
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
switch (info.subsystem) {
#ifdef Q_OS_WIN32
case SDL_SYSWM_WINDOWS:
// Don't use D3DKMTWaitForVerticalBlankEvent() on Windows 7, because // Don't use D3DKMTWaitForVerticalBlankEvent() on Windows 7, because
// it blocks during other concurrent DX operations (like actually rendering). // it blocks during other concurrent DX operations (like actually rendering).
if (IsWindows8OrGreater()) { if (IsWindows8OrGreater()) {
m_VsyncSource = new DxVsyncSource(this); m_VsyncSource = new DxVsyncSource(this);
} }
#endif
break; break;
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(HAS_WAYLAND) case SDLC_VIDEO_WAYLAND:
case SDL_SYSWM_WAYLAND: #if defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(HAS_WAYLAND)
m_VsyncSource = new WaylandVsyncSource(this); m_VsyncSource = new WaylandVsyncSource(this);
#endif
break; break;
#endif
default: default:
// Platforms without a VsyncSource will just render frames // Platforms without a VsyncSource will just render frames

View File

@ -1,7 +1,5 @@
#include "waylandvsyncsource.h" #include "waylandvsyncsource.h"
#include <SDL_syswm.h>
#ifndef SDL_VIDEO_DRIVER_WAYLAND #ifndef SDL_VIDEO_DRIVER_WAYLAND
#warning Unable to use WaylandVsyncSource without SDL support #warning Unable to use WaylandVsyncSource without SDL support
#else #else
@ -29,22 +27,8 @@ WaylandVsyncSource::~WaylandVsyncSource()
bool WaylandVsyncSource::initialize(SDL_Window* window, int) bool WaylandVsyncSource::initialize(SDL_Window* window, int)
{ {
SDL_SysWMinfo info; m_Display = (wl_display*)SDLC_Wayland_GetDisplay(window);
m_Surface = (wl_surface*)SDLC_Wayland_GetSurface(window);
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
// Pacer should not create us for non-Wayland windows
SDL_assert(info.subsystem == SDL_SYSWM_WAYLAND);
m_Display = info.info.wl.display;
m_Surface = info.info.wl.surface;
// Enqueue our first frame callback // Enqueue our first frame callback
m_Callback = wl_surface_frame(m_Surface); m_Callback = wl_surface_frame(m_Surface);

View File

@ -5,8 +5,6 @@
#include <Limelight.h> #include <Limelight.h>
#include <SDL_syswm.h>
extern "C" { extern "C" {
#include <libavutil/pixdesc.h> #include <libavutil/pixdesc.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
@ -140,20 +138,11 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
return false; return false;
} }
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(params->window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
// Only set SDL_RENDERER_PRESENTVSYNC if we know we'll get tearing otherwise. // Only set SDL_RENDERER_PRESENTVSYNC if we know we'll get tearing otherwise.
// Since we don't use V-Sync to pace our frame rate, we want non-blocking // Since we don't use V-Sync to pace our frame rate, we want non-blocking
// presents to reduce video latency. // presents to reduce video latency.
switch (info.subsystem) { switch (SDLC_GetVideoDriver()) {
case SDL_SYSWM_WINDOWS: case SDLC_VIDEO_WIN32:
// DWM is always tear-free except in full-screen exclusive mode // DWM is always tear-free except in full-screen exclusive mode
if ((SDL_GetWindowFlags(params->window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) { if ((SDL_GetWindowFlags(params->window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
if (params->enableVsync) { if (params->enableVsync) {
@ -161,7 +150,7 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
} }
} }
break; break;
case SDL_SYSWM_WAYLAND: case SDLC_VIDEO_WAYLAND:
// Wayland is always tear-free in all modes // Wayland is always tear-free in all modes
break; break;
default: default:

View File

@ -13,8 +13,6 @@
#include <xf86drm.h> #include <xf86drm.h>
#endif #endif
#include <SDL_syswm.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -81,23 +79,14 @@ VAAPIRenderer::~VAAPIRenderer()
VADisplay VADisplay
VAAPIRenderer::openDisplay(SDL_Window* window) VAAPIRenderer::openDisplay(SDL_Window* window)
{ {
SDL_SysWMinfo info;
VADisplay display; VADisplay display;
SDL_VERSION(&info.version); m_WindowSystem = SDLC_GetVideoDriver();
if (!SDL_GetWindowWMInfo(window, &info)) { if (m_WindowSystem == SDLC_VIDEO_X11) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return nullptr;
}
m_WindowSystem = info.subsystem;
if (info.subsystem == SDL_SYSWM_X11) {
#ifdef HAVE_LIBVA_X11 #ifdef HAVE_LIBVA_X11
m_XWindow = info.info.x11.window; m_XWindow = (Window)SDLC_X11_GetWindow(window);
display = vaGetDisplay(info.info.x11.display); display = vaGetDisplay((Display*)SDLC_X11_GetDisplay(window));
if (display == nullptr) { if (display == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to open X11 display for VAAPI"); "Unable to open X11 display for VAAPI");
@ -109,9 +98,9 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
return nullptr; return nullptr;
#endif #endif
} }
else if (info.subsystem == SDL_SYSWM_WAYLAND) { else if (m_WindowSystem == SDLC_VIDEO_WAYLAND) {
#ifdef HAVE_LIBVA_WAYLAND #ifdef HAVE_LIBVA_WAYLAND
display = vaGetDisplayWl(info.info.wl.display); display = vaGetDisplayWl((wl_display*)SDLC_Wayland_GetDisplay(window));
if (display == nullptr) { if (display == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to open Wayland display for VAAPI"); "Unable to open Wayland display for VAAPI");
@ -123,8 +112,8 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
return nullptr; return nullptr;
#endif #endif
} }
#if defined(SDL_VIDEO_DRIVER_KMSDRM) && defined(HAVE_LIBVA_DRM) && SDL_VERSION_ATLEAST(2, 0, 15) else if (m_WindowSystem == SDLC_VIDEO_KMSDRM) {
else if (info.subsystem == SDL_SYSWM_KMSDRM) { #ifdef HAVE_LIBVA_DRM
// It's possible to enter this function several times as we're probing VA drivers. // It's possible to enter this function several times as we're probing VA drivers.
// Make sure to only duplicate the DRM FD the first time through. // Make sure to only duplicate the DRM FD the first time through.
if (m_DrmFd < 0) { if (m_DrmFd < 0) {
@ -183,12 +172,16 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
"Unable to open DRM display for VAAPI"); "Unable to open DRM display for VAAPI");
return nullptr; return nullptr;
} }
} #else
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Moonlight not compiled with VAAPI DRM support!");
return nullptr;
#endif #endif
}
else { else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unsupported VAAPI rendering subsystem: %d", "Unsupported VAAPI rendering subsystem: %d",
info.subsystem); m_WindowSystem);
return nullptr; return nullptr;
} }
@ -300,7 +293,7 @@ VAAPIRenderer::initialize(PDECODER_PARAMETERS params)
status = tryVaInitialize(vaDeviceContext, params, &major, &minor); status = tryVaInitialize(vaDeviceContext, params, &major, &minor);
} }
if (status != VA_STATUS_SUCCESS && (m_WindowSystem != SDL_SYSWM_X11 || m_DecoderSelectionPass > 0)) { if (status != VA_STATUS_SUCCESS && (m_WindowSystem != SDLC_VIDEO_X11 || m_DecoderSelectionPass > 0)) {
// The unofficial nvidia VAAPI driver over NVDEC/CUDA works well on Wayland, // The unofficial nvidia VAAPI driver over NVDEC/CUDA works well on Wayland,
// but we'd rather use CUDA for XWayland and VDPAU for regular X11. // but we'd rather use CUDA for XWayland and VDPAU for regular X11.
// NB: Remember to update the VA-API NVDEC condition below when modifying this! // NB: Remember to update the VA-API NVDEC condition below when modifying this!
@ -413,7 +406,7 @@ VAAPIRenderer::initialize(PDECODER_PARAMETERS params)
} }
// Prefer CUDA for XWayland and VDPAU for regular X11. // Prefer CUDA for XWayland and VDPAU for regular X11.
if (m_WindowSystem == SDL_SYSWM_X11 && vendorStr.contains("VA-API NVDEC", Qt::CaseInsensitive)) { if (m_WindowSystem == SDLC_VIDEO_X11 && vendorStr.contains("VA-API NVDEC", Qt::CaseInsensitive)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Deprioritizing VAAPI for NVIDIA driver on X11/XWayland. Set FORCE_VAAPI=1 to override."); "Deprioritizing VAAPI for NVIDIA driver on X11/XWayland. Set FORCE_VAAPI=1 to override.");
return false; return false;
@ -557,7 +550,7 @@ VAAPIRenderer::isDirectRenderingSupported()
} }
// We only support direct rendering on X11 with VAEntrypointVideoProc support // We only support direct rendering on X11 with VAEntrypointVideoProc support
if (m_WindowSystem != SDL_SYSWM_X11 || m_BlacklistedForDirectRendering) { if (m_WindowSystem != SDLC_VIDEO_X11 || m_BlacklistedForDirectRendering) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Using indirect rendering due to WM or blacklist"); "Using indirect rendering due to WM or blacklist");
return false; return false;
@ -773,7 +766,7 @@ VAAPIRenderer::renderFrame(AVFrame* frame)
StreamUtils::scaleSourceToDestinationSurface(&src, &dst); StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
if (m_WindowSystem == SDL_SYSWM_X11) { if (m_WindowSystem == SDLC_VIDEO_X11) {
#ifdef HAVE_LIBVA_X11 #ifdef HAVE_LIBVA_X11
unsigned int flags = 0; unsigned int flags = 0;
@ -909,7 +902,7 @@ VAAPIRenderer::renderFrame(AVFrame* frame)
SDL_UnlockMutex(m_OverlayMutex); SDL_UnlockMutex(m_OverlayMutex);
#endif #endif
} }
else if (m_WindowSystem == SDL_SYSWM_WAYLAND) { else if (m_WindowSystem == SDLC_VIDEO_WAYLAND) {
// We don't support direct rendering on Wayland, so we should // We don't support direct rendering on Wayland, so we should
// never get called there. Many common Wayland compositors don't // never get called there. Many common Wayland compositors don't
// support YUV surfaces, so direct rendering would fail. // support YUV surfaces, so direct rendering would fail.

View File

@ -92,7 +92,7 @@ private:
#endif #endif
int m_DecoderSelectionPass; int m_DecoderSelectionPass;
int m_WindowSystem; SDLC_VideoDriver m_WindowSystem;
AVBufferRef* m_HwContext; AVBufferRef* m_HwContext;
bool m_BlacklistedForDirectRendering; bool m_BlacklistedForDirectRendering;
bool m_HasRfiLatencyBug; bool m_HasRfiLatencyBug;

View File

@ -3,8 +3,6 @@
#include <streaming/streamutils.h> #include <streaming/streamutils.h>
#include <utils.h> #include <utils.h>
#include <SDL_syswm.h>
#define BAIL_ON_FAIL(status, something) if ((status) != VDP_STATUS_OK) { \ #define BAIL_ON_FAIL(status, something) if ((status) != VDP_STATUS_OK) { \
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, \ SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, \
#something " failed: %d", (status)); \ #something " failed: %d", (status)); \
@ -78,7 +76,6 @@ bool VDPAURenderer::initialize(PDECODER_PARAMETERS params)
{ {
int err; int err;
VdpStatus status; VdpStatus status;
SDL_SysWMinfo info;
// Avoid initializing VDPAU on this window on the first selection pass if: // Avoid initializing VDPAU on this window on the first selection pass if:
// a) We know we want HDR compatibility // a) We know we want HDR compatibility
@ -97,24 +94,16 @@ bool VDPAURenderer::initialize(PDECODER_PARAMETERS params)
} }
} }
SDL_VERSION(&info.version); SDLC_VideoDriver videoDriver = SDLC_GetVideoDriver();
if (videoDriver == SDLC_VIDEO_WAYLAND) {
if (!SDL_GetWindowWMInfo(params->window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
if (info.subsystem == SDL_SYSWM_WAYLAND) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"VDPAU is not supported on Wayland"); "VDPAU is not supported on Wayland");
return false; return false;
} }
else if (info.subsystem != SDL_SYSWM_X11) { else if (videoDriver != SDLC_VIDEO_X11) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"VDPAU is not supported on the current subsystem: %d", "VDPAU is not supported on the current subsystem: %d",
info.subsystem); videoDriver);
return false; return false;
} }
else if (qgetenv("VDPAU_XWAYLAND") != "1" && WMUtils::isRunningWayland()) { else if (qgetenv("VDPAU_XWAYLAND") != "1" && WMUtils::isRunningWayland()) {
@ -216,12 +205,10 @@ bool VDPAURenderer::initialize(PDECODER_PARAMETERS params)
SDL_GetWindowSize(params->window, (int*)&m_DisplayWidth, (int*)&m_DisplayHeight); SDL_GetWindowSize(params->window, (int*)&m_DisplayWidth, (int*)&m_DisplayHeight);
SDL_assert(info.subsystem == SDL_SYSWM_X11);
GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, GET_PROC_ADDRESS(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
&m_VdpPresentationQueueTargetCreateX11); &m_VdpPresentationQueueTargetCreateX11);
status = m_VdpPresentationQueueTargetCreateX11(m_Device, status = m_VdpPresentationQueueTargetCreateX11(m_Device,
info.info.x11.window, SDLC_X11_GetWindow(params->window),
&m_PresentationQueueTarget); &m_PresentationQueueTarget);
if (status != VDP_STATUS_OK) { if (status != VDP_STATUS_OK) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,

View File

@ -5,7 +5,6 @@
#include "pacer/pacer.h" #include "pacer/pacer.h"
#undef AVMediaType #undef AVMediaType
#include <SDL_syswm.h>
#include <Limelight.h> #include <Limelight.h>
#include <streaming/session.h> #include <streaming/session.h>
@ -139,9 +138,8 @@ public:
return kCVReturnSuccess; return kCVReturnSuccess;
} }
bool initializeVsyncCallback(SDL_SysWMinfo* info) bool initializeVsyncCallback(NSScreen* screen)
{ {
NSScreen* screen = [info->info.cocoa.window screen];
CVReturn status; CVReturn status;
if (screen == nullptr) { if (screen == nullptr) {
// Window not visible on any display, so use a // Window not visible on any display, so use a
@ -418,23 +416,11 @@ public:
// If we're using direct rendering, set up the AVSampleBufferDisplayLayer // If we're using direct rendering, set up the AVSampleBufferDisplayLayer
if (m_DirectRendering) { if (m_DirectRendering) {
SDL_SysWMinfo info; NSWindow* window = (NSWindow*)SDLC_MacOS_GetWindow(params->window);
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(params->window, &info)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return false;
}
SDL_assert(info.subsystem == SDL_SYSWM_COCOA);
// SDL adds its own content view to listen for events. // SDL adds its own content view to listen for events.
// We need to add a subview for our display layer. // We need to add a subview for our display layer.
NSView* contentView = info.info.cocoa.window.contentView; m_StreamView = [[VTView alloc] initWithFrame:window.contentView.bounds];
m_StreamView = [[VTView alloc] initWithFrame:contentView.bounds];
m_DisplayLayer = [[AVSampleBufferDisplayLayer alloc] init]; m_DisplayLayer = [[AVSampleBufferDisplayLayer alloc] init];
m_DisplayLayer.bounds = m_StreamView.bounds; m_DisplayLayer.bounds = m_StreamView.bounds;
@ -453,9 +439,9 @@ public:
if (isAppleSilicon && !(params->videoFormat & VIDEO_FORMAT_MASK_10BIT)) { if (isAppleSilicon && !(params->videoFormat & VIDEO_FORMAT_MASK_10BIT)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Using layer rasterization workaround"); "Using layer rasterization workaround");
if (info.info.cocoa.window.screen != nullptr) { if (window.screen != nullptr) {
m_DisplayLayer.shouldRasterize = YES; m_DisplayLayer.shouldRasterize = YES;
m_DisplayLayer.rasterizationScale = info.info.cocoa.window.screen.backingScaleFactor; m_DisplayLayer.rasterizationScale = window.screen.backingScaleFactor;
} }
else { else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
@ -471,10 +457,10 @@ public:
m_StreamView.layer = m_DisplayLayer; m_StreamView.layer = m_DisplayLayer;
m_StreamView.wantsLayer = YES; m_StreamView.wantsLayer = YES;
[contentView addSubview: m_StreamView]; [window.contentView addSubview: m_StreamView];
if (params->enableFramePacing) { if (params->enableFramePacing) {
if (!initializeVsyncCallback(&info)) { if (!initializeVsyncCallback(window.screen)) {
return false; return false;
} }
} }

View File

@ -5,7 +5,6 @@
#include "pacer/pacer.h" #include "pacer/pacer.h"
#undef AVMediaType #undef AVMediaType
#include <SDL_syswm.h>
#include <Limelight.h> #include <Limelight.h>
#include "streaming/session.h" #include "streaming/session.h"
#include "streaming/streamutils.h" #include "streaming/streamutils.h"