diff --git a/app/SDL_compat.c b/app/SDL_compat.c new file mode 100644 index 00000000..da2e9d89 --- /dev/null +++ b/app/SDL_compat.c @@ -0,0 +1,209 @@ +#include "SDL_compat.h" + +#include + +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 +} diff --git a/app/SDL_compat.h b/app/SDL_compat.h index 2bef3a63..d188be15 100644 --- a/app/SDL_compat.h +++ b/app/SDL_compat.h @@ -7,6 +7,11 @@ #include +// 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 diff --git a/app/app.pro b/app/app.pro index 053882c1..538204ac 100644 --- a/app/app.pro +++ b/app/app.pro @@ -174,6 +174,7 @@ macx { } SOURCES += \ + SDL_compat.c \ backend/nvaddress.cpp \ backend/nvapp.cpp \ cli/pair.cpp \ diff --git a/app/streaming/input/abstouch.cpp b/app/streaming/input/abstouch.cpp index 28b33a4c..bd80acb3 100644 --- a/app/streaming/input/abstouch.cpp +++ b/app/streaming/input/abstouch.cpp @@ -2,9 +2,13 @@ #include #include "SDL_compat.h" -#include #include "streaming/streamutils.h" +#ifdef Q_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + #include // 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 diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 6da51f16..21fa0a2c 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -24,7 +24,6 @@ // HACK: Remove once proper Dark Mode support lands in SDL #ifdef Q_OS_WIN32 -#include #include #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 diff --git a/app/streaming/streamutils.cpp b/app/streaming/streamutils.cpp index 2aa5a51d..230ded07 100644 --- a/app/streaming/streamutils.cpp +++ b/app/streaming/streamutils.cpp @@ -14,8 +14,6 @@ #ifdef Q_OS_UNIX #include #include - -#include #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; diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp index 201eb7ac..a5b33c63 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp @@ -8,7 +8,6 @@ #include "streaming/streamutils.h" #include "streaming/session.h" -#include #include #include @@ -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 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", diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.cpp b/app/streaming/video/ffmpeg-renderers/dxva2.cpp index a3e538b0..33f9ba3b 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.cpp +++ b/app/streaming/video/ffmpeg-renderers/dxva2.cpp @@ -9,8 +9,6 @@ #include #include -#include - #define WIN32_LEAN_AND_MEAN #include #include @@ -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 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, ¤tMode, 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) { diff --git a/app/streaming/video/ffmpeg-renderers/eglvid.cpp b/app/streaming/video/ffmpeg-renderers/eglvid.cpp index 57a84942..89c0d4a8 100644 --- a/app/streaming/video/ffmpeg-renderers/eglvid.cpp +++ b/app/streaming/video/ffmpeg-renderers/eglvid.cpp @@ -11,7 +11,6 @@ #include #include -#include // 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 { diff --git a/app/streaming/video/ffmpeg-renderers/mmal.cpp b/app/streaming/video/ffmpeg-renderers/mmal.cpp index 228d8f47..23ce9f65 100644 --- a/app/streaming/video/ffmpeg-renderers/mmal.cpp +++ b/app/streaming/video/ffmpeg-renderers/mmal.cpp @@ -5,13 +5,6 @@ #include -// HACK: Avoid including X11 headers which conflict with QDir -#ifdef SDL_VIDEO_DRIVER_X11 -#undef SDL_VIDEO_DRIVER_X11 -#endif - -#include - #include #include diff --git a/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp b/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp index 2d30aadb..044901bb 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp @@ -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; } diff --git a/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h b/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h index f126df15..c4fc87eb 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h +++ b/app/streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h @@ -2,7 +2,8 @@ #include "pacer.h" -#include +#define WIN32_LEAN_AND_MEAN +#include // from typedef LONG NTSTATUS; diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp index 2686c549..29684e98 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp @@ -2,18 +2,14 @@ #include "streaming/streamutils.h" #ifdef Q_OS_WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include #include "dxvsyncsource.h" +#include #endif #ifdef HAS_WAYLAND #include "waylandvsyncsource.h" #endif -#include - // 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 diff --git a/app/streaming/video/ffmpeg-renderers/pacer/waylandvsyncsource.cpp b/app/streaming/video/ffmpeg-renderers/pacer/waylandvsyncsource.cpp index 13e5e4d4..63f6824c 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/waylandvsyncsource.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/waylandvsyncsource.cpp @@ -1,7 +1,5 @@ #include "waylandvsyncsource.h" -#include - #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); diff --git a/app/streaming/video/ffmpeg-renderers/sdlvid.cpp b/app/streaming/video/ffmpeg-renderers/sdlvid.cpp index 1467ce52..65f701ee 100644 --- a/app/streaming/video/ffmpeg-renderers/sdlvid.cpp +++ b/app/streaming/video/ffmpeg-renderers/sdlvid.cpp @@ -5,8 +5,6 @@ #include -#include - extern "C" { #include #include @@ -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: diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.cpp b/app/streaming/video/ffmpeg-renderers/vaapi.cpp index d8f66074..e73bd441 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.cpp +++ b/app/streaming/video/ffmpeg-renderers/vaapi.cpp @@ -13,8 +13,6 @@ #include #endif -#include - #include #include @@ -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. diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.h b/app/streaming/video/ffmpeg-renderers/vaapi.h index f45a18c4..73f93255 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.h +++ b/app/streaming/video/ffmpeg-renderers/vaapi.h @@ -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; diff --git a/app/streaming/video/ffmpeg-renderers/vdpau.cpp b/app/streaming/video/ffmpeg-renderers/vdpau.cpp index 99244dcf..c6e13374 100644 --- a/app/streaming/video/ffmpeg-renderers/vdpau.cpp +++ b/app/streaming/video/ffmpeg-renderers/vdpau.cpp @@ -3,8 +3,6 @@ #include #include -#include - #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, diff --git a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm index 24584527..5019be31 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm @@ -5,7 +5,6 @@ #include "pacer/pacer.h" #undef AVMediaType -#include #include #include @@ -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; } } diff --git a/app/streaming/video/ffmpeg-renderers/vt_metal.mm b/app/streaming/video/ffmpeg-renderers/vt_metal.mm index 61f15a7f..14a5b5f7 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_metal.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_metal.mm @@ -5,7 +5,6 @@ #include "pacer/pacer.h" #undef AVMediaType -#include #include #include "streaming/session.h" #include "streaming/streamutils.h"