[plasma/kwin] src/backends/drm: backends/drm: don't access pipelines in the commit thread

Xaver Hugl <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit e61f57a8888d2b495d4ca70f4c2c7e0751979b22 by Xaver Hugl.
Committed on 20/07/2026 at 15:48.
Pushed by zamundaaa into branch 'master'.

backends/drm: don't access pipelines in the commit thread

All pending state of pipelines may be modified at any time by the main thread,
including the crtc.
To fix that, this more explicitly tracks which crtc a pageflip event should be
delivered for.

M  +13   -4    src/backends/drm/drm_commit.cpp
M  +7    -0    src/backends/drm/drm_commit.h
M  +2    -0    src/backends/drm/drm_pipeline.cpp

https://invent.kde.org/plasma/kwin/-/commit/e61f57a8888d2b495d4ca70f4c2c7e0751979b22

diff --git a/src/backends/drm/drm_commit.cpp b/src/backends/drm/drm_commit.cpp
index b4fa043f2ec..3f51af1cac9 100644
--- a/src/backends/drm/drm_commit.cpp
+++ b/src/backends/drm/drm_commit.cpp
@@ -113,7 +113,10 @@ bool DrmAtomicCommit::testAllowModeset()
 
 bool DrmAtomicCommit::commit()
 {
-    uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT;
+    uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
+    if (m_crtc) {
+        flags |= DRM_MODE_PAGE_FLIP_EVENT;
+    }
     if (isTearing()) {
         flags |= DRM_MODE_PAGE_FLIP_ASYNC;
     }
@@ -164,9 +167,7 @@ bool DrmAtomicCommit::doCommit(uint32_t flags)
     }
     const bool success = drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_ATOMIC, &commitData) == 0;
     if (success && (flags & DRM_MODE_PAGE_FLIP_EVENT)) {
-        for (const DrmPipeline *pipeline : m_pipelines) {
-            m_gpu->registerPendingCommit(lock, pipeline->crtc()->id(), this);
-        }
+        m_gpu->registerPendingCommit(lock, *m_crtc, this);
     }
     return success;
 }
@@ -256,6 +257,9 @@ void DrmAtomicCommit::merge(DrmAtomicCommit *onTop)
     } else {
         m_allowedVrrDelay.reset();
     }
+    if (onTop->m_crtc) {
+        m_crtc = onTop->m_crtc;
+    }
 }
 
 void DrmAtomicCommit::setAllowedVrrDelay(std::optional<std::chrono::nanoseconds> allowedDelay)
@@ -284,6 +288,11 @@ bool DrmAtomicCommit::isTearing() const
     return m_mode == PresentationMode::Async || m_mode == PresentationMode::AdaptiveAsync;
 }
 
+void DrmAtomicCommit::requestPageflipEvent(uint32_t crtcId)
+{
+    m_crtc = crtcId;
+}
+
 DrmLegacyCommit::DrmLegacyCommit(DrmPipeline *pipeline, const std::shared_ptr<DrmFramebuffer> &buffer, const std::shared_ptr<OutputFrame> &frame)
     : DrmCommit(pipeline->gpu())
     , m_pipeline(pipeline)
diff --git a/src/backends/drm/drm_commit.h b/src/backends/drm/drm_commit.h
index d3e5331d063..188f9c745e0 100644
--- a/src/backends/drm/drm_commit.h
+++ b/src/backends/drm/drm_commit.h
@@ -88,6 +88,12 @@ public:
     bool isReadyFor(std::chrono::steady_clock::time_point pageflipTarget) const;
     bool isTearing() const;
 
+    /**
+     * NOTE if this is called multiple times, the pageflip event is only submitted
+     *      to the last crtc
+     */
+    void requestPageflipEvent(uint32_t crtcId);
+
 private:
     bool doCommit(uint32_t flags);
 
@@ -101,6 +107,7 @@ private:
     std::optional<bool> m_vrr;
     std::unordered_map<uint32_t /* object */, std::unordered_map<uint32_t /* property */, uint64_t /* value */>> m_properties;
     bool m_modeset = false;
+    std::optional<uint32_t> m_crtc;
     PresentationMode m_mode = PresentationMode::VSync;
 };
 
diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp
index d038d800252..523ed9867ad 100644
--- a/src/backends/drm/drm_pipeline.cpp
+++ b/src/backends/drm/drm_pipeline.cpp
@@ -68,6 +68,7 @@ DrmPipeline::Error DrmPipeline::present(const QList<OutputLayer *> &layersToUpda
         // NOTE that this assumes testPresentation has been called before and succeeded
         // only give the actual state update to the commit thread, so that it can potentially reorder the commits
         auto partialUpdate = std::make_unique<DrmAtomicCommit>(gpu(), QList{this});
+        partialUpdate->requestPageflipEvent(m_pending.crtc->id());
         if (Error err = prepareAtomicPresentation(partialUpdate.get(), frame); err != Error::None) {
             return err;
         }
@@ -492,6 +493,7 @@ bool DrmPipeline::presentAsync(OutputLayer *layer, std::optional<std::chrono::na
         }
         // only give the actual state update to the commit thread, so that it can potentially reorder the commits
         auto partialUpdate = std::make_unique<DrmAtomicCommit>(gpu(), QList{this});
+        partialUpdate->requestPageflipEvent(m_pending.crtc->id());
         prepareAtomicPlane(partialUpdate.get(), drmLayer->plane(), drmLayer, nullptr);
         partialUpdate->setAllowedVrrDelay(allowedVrrDelay);
         m_commitThread->addCommit(std::move(partialUpdate));
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.