From 8726c1c7d08b34a2f59558b14c78554dfc3c6a37 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 4 Jan 2026 19:34:13 -0600 Subject: [PATCH] Bring back atomic async page flip support Now that we're referencing the AVFrame to keep the buffers from being reused during scanout, this should hopefully work better. --- app/streaming/video/ffmpeg-renderers/drm.cpp | 2 +- app/streaming/video/ffmpeg-renderers/drm.h | 39 ++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/drm.cpp b/app/streaming/video/ffmpeg-renderers/drm.cpp index f89fac95..6154e86a 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.cpp +++ b/app/streaming/video/ffmpeg-renderers/drm.cpp @@ -494,7 +494,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params) atomic = true; } - m_PropSetter.initialize(m_DrmFd, atomic); + m_PropSetter.initialize(m_DrmFd, atomic, !params->enableVsync); drmModePlaneRes* planeRes = drmModeGetPlaneResources(m_DrmFd); if (planeRes == nullptr) { diff --git a/app/streaming/video/ffmpeg-renderers/drm.h b/app/streaming/video/ffmpeg-renderers/drm.h index 7cdfb4f3..b1ac3321 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.h +++ b/app/streaming/video/ffmpeg-renderers/drm.h @@ -14,6 +14,11 @@ #include #include +// This is only defined in Linux 6.8+ headers +#ifndef DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 +#endif + // Newer libdrm headers have these HDR structs, but some older ones don't. namespace DrmDefs { @@ -234,9 +239,26 @@ class DrmRenderer : public IFFmpegRenderer { DrmPropertySetter(const DrmPropertySetter &) = delete; DrmPropertySetter(DrmPropertySetter &&) = delete; - void initialize(int drmFd, bool wantsAtomic) { + void initialize(int drmFd, bool wantsAtomic, bool wantsAsyncFlip) { m_Fd = drmFd; m_Atomic = wantsAtomic && drmSetClientCap(drmFd, DRM_CLIENT_CAP_ATOMIC, 1) == 0; + + if (wantsAsyncFlip) { + uint64_t val; + if (!m_Atomic) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "V-sync cannot be disabled due to lack of atomic support"); + } + else if (drmGetCap(m_Fd, DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP, &val) < 0 || !val) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "V-sync cannot be disabled due to lack of atomic async page flip support"); + } + else { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Using atomic async page flips with V-sync disabled"); + m_AsyncFlip = true; + } + } } bool set(const DrmProperty& prop, uint64_t value, bool verbose = true) { @@ -429,8 +451,18 @@ class DrmRenderer : public IFFmpegRenderer { return true; } - // We pass DRM_MODE_ATOMIC_ALLOW_MODESET because changing HDR state may require a modeset - bool ret = drmModeAtomicCommit(m_Fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, nullptr) == 0; + // Try an async flip if requested + bool ret = drmModeAtomicCommit(m_Fd, m_AtomicReq, + m_AsyncFlip ? DRM_MODE_PAGE_FLIP_ASYNC : DRM_MODE_ATOMIC_ALLOW_MODESET, + nullptr) == 0; + + // The driver may not support async flips (especially if we changed a non-FB_ID property), + // so try again with a regular flip if we get an error from the async flip attempt. + // + // We pass DRM_MODE_ATOMIC_ALLOW_MODESET because changing HDR state may require a modeset. + if (!ret && m_AsyncFlip) { + ret = drmModeAtomicCommit(m_Fd, m_AtomicReq, DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0; + } if (!ret) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "drmModeAtomicCommit() failed: %d", @@ -496,6 +528,7 @@ class DrmRenderer : public IFFmpegRenderer { private: int m_Fd = -1; bool m_Atomic = false; + bool m_AsyncFlip = false; std::recursive_mutex m_Lock; std::unordered_map m_PlaneBuffers;