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>
// 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
#if !SDL_VERSION_ATLEAST(2, 0, 10)
typedef struct SDL_FRect
@ -65,3 +70,26 @@ typedef struct SDL_FRect
#ifndef SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP
#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP"
#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 += \
SDL_compat.c \
backend/nvaddress.cpp \
backend/nvapp.cpp \
cli/pair.cpp \

View File

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

View File

@ -24,7 +24,6 @@
// HACK: Remove once proper Dark Mode support lands in SDL
#ifdef Q_OS_WIN32
#include <SDL_syswm.h>
#include <dwmapi.h>
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE_OLD
#define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19
@ -1867,23 +1866,20 @@ void Session::execInternal()
darkModeEnabled = FALSE;
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
// If dark mode is enabled, propagate that to our SDL window
if (darkModeEnabled) {
HWND hwnd = (HWND)SDLC_Win32_GetHwnd(m_Window);
if (SDL_GetWindowWMInfo(m_Window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) {
// If dark mode is enabled, propagate that to our SDL window
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));
if (FAILED(DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &darkModeEnabled, sizeof(darkModeEnabled)))) {
DwmSetWindowAttribute(hwnd, 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(hwnd, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
ncPolicy = DWMNCRP_ENABLED;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncPolicy, sizeof(ncPolicy));
}
}
#endif

View File

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

View File

@ -8,7 +8,6 @@
#include "streaming/streamutils.h"
#include "streaming/session.h"
#include <SDL_syswm.h>
#include <VersionHelpers.h>
#include <dwmapi.h>
@ -435,16 +434,13 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
}
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(params->window, &info);
SDL_assert(info.subsystem == SDL_SYSWM_WINDOWS);
HWND window = (HWND)SDLC_Win32_GetHwnd(params->window);
// 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.
ComPtr<IDXGISwapChain1> swapChain;
hr = m_Factory->CreateSwapChainForHwnd(m_Device.Get(),
info.info.win.window,
window,
&swapChainDesc,
nullptr,
nullptr,
@ -468,7 +464,7 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
// Disable Alt+Enter, PrintScreen, and window message snooping. This makes
// it safe to run the renderer on a separate rendering thread rather than
// 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)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGIFactory::MakeWindowAssociation() failed: %x",

View File

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

View File

@ -11,7 +11,6 @@
#include <unistd.h>
#include <SDL_render.h>
#include <SDL_syswm.h>
// These are extensions, so some platform headers may not provide them
#ifndef EGL_PLATFORM_WAYLAND_KHR
@ -485,12 +484,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
return false;
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(params->window, &info)) {
EGL_LOG(Error, "SDL_GetWindowWMInfo() failed: %s", SDL_GetError());
return false;
}
SDLC_VideoDriver videoDriver = SDLC_GetVideoDriver();
if (!(m_Context = SDL_GL_CreateContext(params->window))) {
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
// to resize the window. This seems to happen significantly more often
// with vsync enabled, so this also mitigates that problem too.
if (params->enableVsync
#ifdef SDL_VIDEO_DRIVER_WAYLAND
&& info.subsystem != SDL_SYSWM_WAYLAND
#endif
) {
if (params->enableVsync && videoDriver != SDLC_VIDEO_WAYLAND) {
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
// SDL_HINT_VIDEO_DOUBLE_BUFFER=1), so calling glFinish() after
// SDL_GL_SwapWindow() will block an extra frame and lock rendering
// at 1/2 the display refresh rate.
if (info.subsystem != SDL_SYSWM_KMSDRM)
#endif
{
if (videoDriver != SDLC_VIDEO_KMSDRM) {
m_BlockingSwapBuffers = true;
}
} else {

View File

@ -5,13 +5,6 @@
#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 <QTextStream>

View File

@ -47,21 +47,7 @@ bool DxVsyncSource::initialize(SDL_Window* window, int)
return false;
}
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 false;
}
// Pacer should only create us on Win32
SDL_assert(info.subsystem == SDL_SYSWM_WINDOWS);
m_Window = info.info.win.window;
m_Window = (HWND)SDLC_Win32_GetHwnd(window);
return true;
}

View File

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

View File

@ -2,18 +2,14 @@
#include "streaming/streamutils.h"
#ifdef Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <VersionHelpers.h>
#include "dxvsyncsource.h"
#include <VersionHelpers.h>
#endif
#ifdef HAS_WAYLAND
#include "waylandvsyncsource.h"
#endif
#include <SDL_syswm.h>
// 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
// 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",
m_DisplayFps, m_MaxVideoFps);
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 false;
}
switch (info.subsystem) {
#ifdef Q_OS_WIN32
case SDL_SYSWM_WINDOWS:
switch (SDLC_GetVideoDriver()) {
case SDLC_VIDEO_WIN32:
#ifdef Q_OS_WIN32
// Don't use D3DKMTWaitForVerticalBlankEvent() on Windows 7, because
// it blocks during other concurrent DX operations (like actually rendering).
if (IsWindows8OrGreater()) {
m_VsyncSource = new DxVsyncSource(this);
}
#endif
break;
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(HAS_WAYLAND)
case SDL_SYSWM_WAYLAND:
case SDLC_VIDEO_WAYLAND:
#if defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(HAS_WAYLAND)
m_VsyncSource = new WaylandVsyncSource(this);
#endif
break;
#endif
default:
// Platforms without a VsyncSource will just render frames

View File

@ -1,7 +1,5 @@
#include "waylandvsyncsource.h"
#include <SDL_syswm.h>
#ifndef SDL_VIDEO_DRIVER_WAYLAND
#warning Unable to use WaylandVsyncSource without SDL support
#else
@ -29,22 +27,8 @@ WaylandVsyncSource::~WaylandVsyncSource()
bool WaylandVsyncSource::initialize(SDL_Window* window, int)
{
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 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;
m_Display = (wl_display*)SDLC_Wayland_GetDisplay(window);
m_Surface = (wl_surface*)SDLC_Wayland_GetSurface(window);
// Enqueue our first frame callback
m_Callback = wl_surface_frame(m_Surface);

View File

@ -5,8 +5,6 @@
#include <Limelight.h>
#include <SDL_syswm.h>
extern "C" {
#include <libavutil/pixdesc.h>
#include <libavutil/opt.h>
@ -140,20 +138,11 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
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.
// Since we don't use V-Sync to pace our frame rate, we want non-blocking
// presents to reduce video latency.
switch (info.subsystem) {
case SDL_SYSWM_WINDOWS:
switch (SDLC_GetVideoDriver()) {
case SDLC_VIDEO_WIN32:
// DWM is always tear-free except in full-screen exclusive mode
if ((SDL_GetWindowFlags(params->window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
if (params->enableVsync) {
@ -161,7 +150,7 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
}
}
break;
case SDL_SYSWM_WAYLAND:
case SDLC_VIDEO_WAYLAND:
// Wayland is always tear-free in all modes
break;
default:

View File

@ -13,8 +13,6 @@
#include <xf86drm.h>
#endif
#include <SDL_syswm.h>
#include <unistd.h>
#include <fcntl.h>
@ -81,23 +79,14 @@ VAAPIRenderer::~VAAPIRenderer()
VADisplay
VAAPIRenderer::openDisplay(SDL_Window* window)
{
SDL_SysWMinfo info;
VADisplay display;
SDL_VERSION(&info.version);
m_WindowSystem = SDLC_GetVideoDriver();
if (!SDL_GetWindowWMInfo(window, &info)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetWindowWMInfo() failed: %s",
SDL_GetError());
return nullptr;
}
m_WindowSystem = info.subsystem;
if (info.subsystem == SDL_SYSWM_X11) {
if (m_WindowSystem == SDLC_VIDEO_X11) {
#ifdef HAVE_LIBVA_X11
m_XWindow = info.info.x11.window;
display = vaGetDisplay(info.info.x11.display);
m_XWindow = (Window)SDLC_X11_GetWindow(window);
display = vaGetDisplay((Display*)SDLC_X11_GetDisplay(window));
if (display == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to open X11 display for VAAPI");
@ -109,9 +98,9 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
return nullptr;
#endif
}
else if (info.subsystem == SDL_SYSWM_WAYLAND) {
else if (m_WindowSystem == SDLC_VIDEO_WAYLAND) {
#ifdef HAVE_LIBVA_WAYLAND
display = vaGetDisplayWl(info.info.wl.display);
display = vaGetDisplayWl((wl_display*)SDLC_Wayland_GetDisplay(window));
if (display == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to open Wayland display for VAAPI");
@ -123,8 +112,8 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
return nullptr;
#endif
}
#if defined(SDL_VIDEO_DRIVER_KMSDRM) && defined(HAVE_LIBVA_DRM) && SDL_VERSION_ATLEAST(2, 0, 15)
else if (info.subsystem == SDL_SYSWM_KMSDRM) {
else if (m_WindowSystem == SDLC_VIDEO_KMSDRM) {
#ifdef HAVE_LIBVA_DRM
// 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.
if (m_DrmFd < 0) {
@ -183,12 +172,16 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
"Unable to open DRM display for VAAPI");
return nullptr;
}
}
#else
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Moonlight not compiled with VAAPI DRM support!");
return nullptr;
#endif
}
else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unsupported VAAPI rendering subsystem: %d",
info.subsystem);
m_WindowSystem);
return nullptr;
}
@ -300,7 +293,7 @@ VAAPIRenderer::initialize(PDECODER_PARAMETERS params)
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,
// 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!
@ -413,7 +406,7 @@ VAAPIRenderer::initialize(PDECODER_PARAMETERS params)
}
// 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,
"Deprioritizing VAAPI for NVIDIA driver on X11/XWayland. Set FORCE_VAAPI=1 to override.");
return false;
@ -557,7 +550,7 @@ VAAPIRenderer::isDirectRenderingSupported()
}
// 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,
"Using indirect rendering due to WM or blacklist");
return false;
@ -773,7 +766,7 @@ VAAPIRenderer::renderFrame(AVFrame* frame)
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
if (m_WindowSystem == SDL_SYSWM_X11) {
if (m_WindowSystem == SDLC_VIDEO_X11) {
#ifdef HAVE_LIBVA_X11
unsigned int flags = 0;
@ -909,7 +902,7 @@ VAAPIRenderer::renderFrame(AVFrame* frame)
SDL_UnlockMutex(m_OverlayMutex);
#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
// never get called there. Many common Wayland compositors don't
// support YUV surfaces, so direct rendering would fail.

View File

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

View File

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

View File

@ -5,7 +5,6 @@
#include "pacer/pacer.h"
#undef AVMediaType
#include <SDL_syswm.h>
#include <Limelight.h>
#include <streaming/session.h>
@ -139,9 +138,8 @@ public:
return kCVReturnSuccess;
}
bool initializeVsyncCallback(SDL_SysWMinfo* info)
bool initializeVsyncCallback(NSScreen* screen)
{
NSScreen* screen = [info->info.cocoa.window screen];
CVReturn status;
if (screen == nullptr) {
// 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 (m_DirectRendering) {
SDL_SysWMinfo info;
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);
NSWindow* window = (NSWindow*)SDLC_MacOS_GetWindow(params->window);
// SDL adds its own content view to listen for events.
// We need to add a subview for our display layer.
NSView* contentView = info.info.cocoa.window.contentView;
m_StreamView = [[VTView alloc] initWithFrame:contentView.bounds];
m_StreamView = [[VTView alloc] initWithFrame:window.contentView.bounds];
m_DisplayLayer = [[AVSampleBufferDisplayLayer alloc] init];
m_DisplayLayer.bounds = m_StreamView.bounds;
@ -453,9 +439,9 @@ public:
if (isAppleSilicon && !(params->videoFormat & VIDEO_FORMAT_MASK_10BIT)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Using layer rasterization workaround");
if (info.info.cocoa.window.screen != nullptr) {
if (window.screen != nullptr) {
m_DisplayLayer.shouldRasterize = YES;
m_DisplayLayer.rasterizationScale = info.info.cocoa.window.screen.backingScaleFactor;
m_DisplayLayer.rasterizationScale = window.screen.backingScaleFactor;
}
else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
@ -471,10 +457,10 @@ public:
m_StreamView.layer = m_DisplayLayer;
m_StreamView.wantsLayer = YES;
[contentView addSubview: m_StreamView];
[window.contentView addSubview: m_StreamView];
if (params->enableFramePacing) {
if (!initializeVsyncCallback(&info)) {
if (!initializeVsyncCallback(window.screen)) {
return false;
}
}

View File

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