From c1312a555169c801b2c116a7b333443730092e07 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Wed, 8 Nov 2023 14:39:53 +0100 Subject: [PATCH] backends/drm: fix pageflip events getting lost when outputs get turned off When a display gets turned off while a pageflip event was still pending, the pending state gets changed immediately, without waiting for the pageflip event to arrive first. When this happens, activePending() returns false, and so the pageflip event gets discarded. This commit changes the logic to only check for activePending() when the pageflip is for a modeset, avoiding that issue. BUG: 476340 BUG: 476341 BUG: 476342 BUG: 437520 BUG: 475146 --- src/backends/drm/drm_commit.cpp | 12 ++++++++++-- src/backends/drm/drm_commit.h | 2 ++ src/backends/drm/drm_pipeline.cpp | 7 +++++-- src/backends/drm/drm_pipeline.h | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/backends/drm/drm_commit.cpp b/src/backends/drm/drm_commit.cpp index de1285427d..a60df6e22a 100644 --- a/src/backends/drm/drm_commit.cpp +++ b/src/backends/drm/drm_commit.cpp @@ -83,6 +83,7 @@ bool DrmAtomicCommit::commit() bool DrmAtomicCommit::commitModeset() { + m_modeset = true; return doCommit(DRM_MODE_ATOMIC_ALLOW_MODESET); } @@ -127,8 +128,14 @@ void DrmAtomicCommit::pageFlipped(std::chrono::nanoseconds timestamp) const for (const auto &[plane, buffer] : m_buffers) { plane->setCurrentBuffer(buffer); } + DrmPipeline::PageflipType type = DrmPipeline::PageflipType::Normal; + if (m_modeset) { + type = DrmPipeline::PageflipType::Modeset; + } else if (m_cursorOnly) { + type = DrmPipeline::PageflipType::CursorOnly; + } for (const auto pipeline : std::as_const(m_pipelines)) { - pipeline->pageFlipped(timestamp, m_cursorOnly ? DrmPipeline::PageflipType::CursorOnly : DrmPipeline::PageflipType::Normal); + pipeline->pageFlipped(timestamp, type); } } @@ -190,6 +197,7 @@ DrmLegacyCommit::DrmLegacyCommit(DrmPipeline *pipeline, const std::shared_ptrid(); if (drmModeSetCrtc(gpu()->fd(), m_pipeline->crtc()->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0) { m_pipeline->crtc()->setCurrent(m_buffer); @@ -208,6 +216,6 @@ void DrmLegacyCommit::pageFlipped(std::chrono::nanoseconds timestamp) const { Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread()); m_pipeline->crtc()->setCurrent(m_buffer); - m_pipeline->pageFlipped(timestamp, DrmPipeline::PageflipType::Normal); + m_pipeline->pageFlipped(timestamp, m_modeset ? DrmPipeline::PageflipType::Modeset : DrmPipeline::PageflipType::Normal); } } diff --git a/src/backends/drm/drm_commit.h b/src/backends/drm/drm_commit.h index b9c5a9e792..04548ee13e 100644 --- a/src/backends/drm/drm_commit.h +++ b/src/backends/drm/drm_commit.h @@ -88,6 +88,7 @@ private: std::optional m_vrr; std::unordered_map> m_properties; bool m_cursorOnly = false; + bool m_modeset = false; }; class DrmLegacyCommit : public DrmCommit @@ -102,6 +103,7 @@ public: private: DrmPipeline *const m_pipeline; const std::shared_ptr m_buffer; + bool m_modeset = false; }; } diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index c24fa31c3a..f6b27b99a5 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -424,8 +424,11 @@ void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp, PageflipType t { m_commitThread->pageFlipped(timestamp); m_legacyPageflipPending = false; - if (m_output && activePending()) { - if (type == PageflipType::Normal) { + if (type == PageflipType::Modeset && !activePending()) { + return; + } + if (m_output) { + if (type == PageflipType::Normal || type == PageflipType::Modeset) { m_output->pageFlipped(timestamp); } else { RenderLoopPrivate::get(m_output->renderLoop())->notifyVblank(timestamp); diff --git a/src/backends/drm/drm_pipeline.h b/src/backends/drm/drm_pipeline.h index e1d03788eb..ec4432613f 100644 --- a/src/backends/drm/drm_pipeline.h +++ b/src/backends/drm/drm_pipeline.h @@ -85,7 +85,8 @@ public: enum class PageflipType { Normal, - CursorOnly + CursorOnly, + Modeset, }; void pageFlipped(std::chrono::nanoseconds timestamp, PageflipType type); bool pageflipsPending() const;