[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));