From 7d02bc17d6d692c4e9f587e22028a2c34c5a6cb6 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Mon, 24 Jul 2023 13:50:56 +0200 Subject: [PATCH] backends/drm: rework how atomic commits are tracked Pending buffers for drm planes and crtcs are no longer tracked in the planes and crtcs themselves, but instead in a DrmCommit object that is used as the user data for the pageflip handler. This way multiple commits can be pending at the same time without causing conflicts, and the handling of pending buffers is simplified as well. --- autotests/drm/CMakeLists.txt | 2 +- src/backends/drm/CMakeLists.txt | 2 +- src/backends/drm/drm_atomic_commit.cpp | 60 --------- src/backends/drm/drm_commit.cpp | 126 ++++++++++++++++++ .../drm/{drm_atomic_commit.h => drm_commit.h} | 45 ++++++- src/backends/drm/drm_commit_thread.cpp | 15 ++- src/backends/drm/drm_commit_thread.h | 4 + src/backends/drm/drm_connector.cpp | 2 +- src/backends/drm/drm_crtc.cpp | 23 +--- src/backends/drm/drm_crtc.h | 6 +- src/backends/drm/drm_gpu.cpp | 9 +- src/backends/drm/drm_object.cpp | 2 +- src/backends/drm/drm_pipeline.cpp | 30 +---- src/backends/drm/drm_pipeline_legacy.cpp | 20 ++- src/backends/drm/drm_plane.cpp | 30 +---- src/backends/drm/drm_plane.h | 11 +- 16 files changed, 217 insertions(+), 170 deletions(-) delete mode 100644 src/backends/drm/drm_atomic_commit.cpp create mode 100644 src/backends/drm/drm_commit.cpp rename src/backends/drm/{drm_atomic_commit.h => drm_commit.h} (52%) diff --git a/autotests/drm/CMakeLists.txt b/autotests/drm/CMakeLists.txt index c5d46b1c58..590d10bcbe 100644 --- a/autotests/drm/CMakeLists.txt +++ b/autotests/drm/CMakeLists.txt @@ -1,10 +1,10 @@ set(mockDRM_SRCS mock_drm.cpp ../../src/backends/drm/drm_abstract_output.cpp - ../../src/backends/drm/drm_atomic_commit.cpp ../../src/backends/drm/drm_backend.cpp ../../src/backends/drm/drm_blob.cpp ../../src/backends/drm/drm_buffer.cpp + ../../src/backends/drm/drm_commit.cpp ../../src/backends/drm/drm_commit_thread.cpp ../../src/backends/drm/drm_connector.cpp ../../src/backends/drm/drm_crtc.cpp diff --git a/src/backends/drm/CMakeLists.txt b/src/backends/drm/CMakeLists.txt index 83b9df31da..ea497ab7e6 100644 --- a/src/backends/drm/CMakeLists.txt +++ b/src/backends/drm/CMakeLists.txt @@ -1,9 +1,9 @@ target_sources(kwin PRIVATE drm_abstract_output.cpp - drm_atomic_commit.cpp drm_backend.cpp drm_blob.cpp drm_buffer.cpp + drm_commit.cpp drm_commit_thread.cpp drm_connector.cpp drm_crtc.cpp diff --git a/src/backends/drm/drm_atomic_commit.cpp b/src/backends/drm/drm_atomic_commit.cpp deleted file mode 100644 index a1da0be148..0000000000 --- a/src/backends/drm/drm_atomic_commit.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2023 Xaver Hugl - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#include "drm_atomic_commit.h" -#include "drm_blob.h" -#include "drm_gpu.h" -#include "drm_object.h" -#include "drm_property.h" - -namespace KWin -{ - -DrmAtomicCommit::DrmAtomicCommit(DrmGpu *gpu) - : m_gpu(gpu) - , m_req(drmModeAtomicAlloc()) -{ -} - -void DrmAtomicCommit::addProperty(const DrmProperty &prop, uint64_t value) -{ - drmModeAtomicAddProperty(m_req.get(), prop.drmObject()->id(), prop.propId(), value); -} - -void DrmAtomicCommit::addBlob(const DrmProperty &prop, const std::shared_ptr &blob) -{ - addProperty(prop, blob ? blob->blobId() : 0); - m_blobs[&prop] = blob; -} - -bool DrmAtomicCommit::test() -{ - return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK, m_gpu) == 0; -} - -bool DrmAtomicCommit::testAllowModeset() -{ - return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, m_gpu) == 0; -} - -bool DrmAtomicCommit::commit() -{ - return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, m_gpu) == 0; -} - -bool DrmAtomicCommit::commitModeset() -{ - return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, m_gpu) == 0; -} - -drmModeAtomicReq *DrmAtomicCommit::req() const -{ - return m_req.get(); -} - -} diff --git a/src/backends/drm/drm_commit.cpp b/src/backends/drm/drm_commit.cpp new file mode 100644 index 0000000000..5f116df13e --- /dev/null +++ b/src/backends/drm/drm_commit.cpp @@ -0,0 +1,126 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#include "drm_commit.h" +#include "drm_blob.h" +#include "drm_buffer.h" +#include "drm_connector.h" +#include "drm_crtc.h" +#include "drm_gpu.h" +#include "drm_object.h" +#include "drm_property.h" + +#include +#include + +namespace KWin +{ + +DrmCommit::DrmCommit(DrmGpu *gpu) + : m_gpu(gpu) +{ +} + +DrmCommit::~DrmCommit() +{ +} + +DrmGpu *DrmCommit::gpu() const +{ + return m_gpu; +} + +DrmAtomicCommit::DrmAtomicCommit(DrmGpu *gpu) + : DrmCommit(gpu) + , m_req(drmModeAtomicAlloc()) +{ +} + +DrmAtomicCommit::~DrmAtomicCommit() +{ + Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread()); + if (m_commitSuccessful) { + for (const auto &[plane, buffer] : m_buffers) { + plane->setCurrentBuffer(buffer); + } + } +} + +void DrmAtomicCommit::addProperty(const DrmProperty &prop, uint64_t value) +{ + drmModeAtomicAddProperty(m_req.get(), prop.drmObject()->id(), prop.propId(), value); +} + +void DrmAtomicCommit::addBlob(const DrmProperty &prop, const std::shared_ptr &blob) +{ + addProperty(prop, blob ? blob->blobId() : 0); + m_blobs[&prop] = blob; +} + +void DrmAtomicCommit::addBuffer(DrmPlane *plane, const std::shared_ptr &buffer) +{ + addProperty(plane->fbId, buffer ? buffer->framebufferId() : 0); + m_buffers[plane] = buffer; +} + +bool DrmAtomicCommit::test() +{ + return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK, this) == 0; +} + +bool DrmAtomicCommit::testAllowModeset() +{ + return drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0; +} + +bool DrmAtomicCommit::commit() +{ + m_commitSuccessful = (drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, this) == 0); + return m_commitSuccessful; +} + +bool DrmAtomicCommit::commitModeset() +{ + m_commitSuccessful = (drmModeAtomicCommit(m_gpu->fd(), m_req.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, this) == 0); + return m_commitSuccessful; +} + +drmModeAtomicReq *DrmAtomicCommit::req() const +{ + return m_req.get(); +} + +DrmLegacyCommit::DrmLegacyCommit(DrmCrtc *crtc, const std::shared_ptr &buffer) + : DrmCommit(crtc->gpu()) + , m_crtc(crtc) + , m_buffer(buffer) +{ +} + +DrmLegacyCommit::~DrmLegacyCommit() +{ + Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread()); + if (m_success) { + m_crtc->setCurrent(m_buffer); + } +} + +bool DrmLegacyCommit::doModeset(DrmConnector *connector, DrmConnectorMode *mode) +{ + uint32_t connectorId = connector->id(); + m_success = (drmModeSetCrtc(gpu()->fd(), m_crtc->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0); + return m_success; +} + +bool DrmLegacyCommit::doPageflip(uint32_t flags) +{ + m_success = (drmModePageFlip(gpu()->fd(), m_crtc->id(), m_buffer->framebufferId(), flags, this) == 0); + return m_success; +} + +} diff --git a/src/backends/drm/drm_atomic_commit.h b/src/backends/drm/drm_commit.h similarity index 52% rename from src/backends/drm/drm_atomic_commit.h rename to src/backends/drm/drm_commit.h index f97354ab57..674c4a08ba 100644 --- a/src/backends/drm/drm_atomic_commit.h +++ b/src/backends/drm/drm_commit.h @@ -12,6 +12,7 @@ #include #include +#include #include "drm_pointer.h" #include "drm_property.h" @@ -19,14 +20,33 @@ namespace KWin { -class DrmGpu; -class DrmProperty; class DrmBlob; +class DrmConnector; +class DrmConnectorMode; +class DrmCrtc; +class DrmFramebuffer; +class DrmGpu; +class DrmPlane; +class DrmProperty; -class DrmAtomicCommit +class DrmCommit +{ +public: + virtual ~DrmCommit(); + + DrmGpu *gpu() const; + +protected: + DrmCommit(DrmGpu *gpu); + + DrmGpu *const m_gpu; +}; + +class DrmAtomicCommit : public DrmCommit { public: DrmAtomicCommit(DrmGpu *gpu); + ~DrmAtomicCommit() override; void addProperty(const DrmProperty &prop, uint64_t value); template @@ -35,6 +55,7 @@ public: addProperty(prop, prop.valueForEnum(enumValue)); } void addBlob(const DrmProperty &prop, const std::shared_ptr &blob); + void addBuffer(DrmPlane *plane, const std::shared_ptr &buffer); bool test(); bool testAllowModeset(); @@ -44,9 +65,25 @@ public: drmModeAtomicReq *req() const; private: - DrmGpu *const m_gpu; DrmUniquePtr m_req; QHash> m_blobs; + std::unordered_map> m_buffers; + bool m_commitSuccessful = false; +}; + +class DrmLegacyCommit : public DrmCommit +{ +public: + DrmLegacyCommit(DrmCrtc *crtc, const std::shared_ptr &buffer); + ~DrmLegacyCommit() override; + + bool doModeset(DrmConnector *connector, DrmConnectorMode *mode); + bool doPageflip(uint32_t flags); + +private: + DrmCrtc *const m_crtc; + const std::shared_ptr m_buffer; + bool m_success = false; }; } diff --git a/src/backends/drm/drm_commit_thread.cpp b/src/backends/drm/drm_commit_thread.cpp index 0fd7230b3b..1dd23eb9db 100644 --- a/src/backends/drm/drm_commit_thread.cpp +++ b/src/backends/drm/drm_commit_thread.cpp @@ -7,7 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "drm_commit_thread.h" -#include "drm_atomic_commit.h" +#include "drm_commit.h" #include "drm_gpu.h" #include "utils/realtime.h" @@ -38,10 +38,14 @@ DrmCommitThread::DrmCommitThread() } // the other thread may replace the commit, but not erase it Q_ASSERT(m_commit); - if (!m_commit->commit()) { + if (m_commit->commit()) { + // the atomic commit takes ownership of the object + m_commit.release(); + } else { + m_droppedCommits.push_back(std::move(m_commit)); QMetaObject::invokeMethod(this, &DrmCommitThread::commitFailed, Qt::ConnectionType::QueuedConnection); + QMetaObject::invokeMethod(this, &DrmCommitThread::clearDroppedCommits, Qt::ConnectionType::QueuedConnection); } - m_commit.reset(); } } })); @@ -75,4 +79,9 @@ bool DrmCommitThread::replaceCommit(std::unique_ptr &&commit) } } +void DrmCommitThread::clearDroppedCommits() +{ + std::unique_lock lock(m_mutex); + m_droppedCommits.clear(); +} } diff --git a/src/backends/drm/drm_commit_thread.h b/src/backends/drm/drm_commit_thread.h index da3d1900d2..156317c4ed 100644 --- a/src/backends/drm/drm_commit_thread.h +++ b/src/backends/drm/drm_commit_thread.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace KWin { @@ -33,11 +34,14 @@ Q_SIGNALS: void commitFailed(); private: + void clearDroppedCommits(); + std::unique_ptr m_commit; std::unique_ptr m_thread; std::mutex m_mutex; std::condition_variable m_commitPending; std::chrono::nanoseconds m_targetPageflipTime; + std::vector> m_droppedCommits; }; } diff --git a/src/backends/drm/drm_connector.cpp b/src/backends/drm/drm_connector.cpp index 79db47f196..4ffc17897c 100644 --- a/src/backends/drm/drm_connector.cpp +++ b/src/backends/drm/drm_connector.cpp @@ -8,7 +8,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "drm_connector.h" -#include "drm_atomic_commit.h" +#include "drm_commit.h" #include "drm_crtc.h" #include "drm_gpu.h" #include "drm_logging.h" diff --git a/src/backends/drm/drm_crtc.cpp b/src/backends/drm/drm_crtc.cpp index d06099e26c..7ec300c1c5 100644 --- a/src/backends/drm/drm_crtc.cpp +++ b/src/backends/drm/drm_crtc.cpp @@ -7,9 +7,9 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "drm_crtc.h" -#include "drm_atomic_commit.h" #include "drm_backend.h" #include "drm_buffer.h" +#include "drm_commit.h" #include "drm_gpu.h" #include "drm_logging.h" #include "drm_output.h" @@ -54,12 +54,6 @@ bool DrmCrtc::updateProperties() return !gpu()->atomicModeSetting() || (modeId.isValid() && active.isValid()); } -void DrmCrtc::flipBuffer() -{ - m_currentBuffer = m_nextBuffer; - m_nextBuffer = nullptr; -} - drmModeModeInfo DrmCrtc::queryCurrentMode() { m_crtc.reset(drmModeGetCrtc(gpu()->fd(), id())); @@ -76,21 +70,11 @@ std::shared_ptr DrmCrtc::current() const return m_currentBuffer; } -std::shared_ptr DrmCrtc::next() const -{ - return m_nextBuffer; -} - void DrmCrtc::setCurrent(const std::shared_ptr &buffer) { m_currentBuffer = buffer; } -void DrmCrtc::setNext(const std::shared_ptr &buffer) -{ - m_nextBuffer = buffer; -} - int DrmCrtc::gammaRampSize() const { if (gpu()->atomicModeSetting()) { @@ -118,11 +102,8 @@ void DrmCrtc::disable(DrmAtomicCommit *commit) commit->addProperty(modeId, 0); } -void DrmCrtc::releaseBuffers() +void DrmCrtc::releaseCurrentBuffer() { - if (m_nextBuffer) { - m_nextBuffer->releaseBuffer(); - } if (m_currentBuffer) { m_currentBuffer->releaseBuffer(); } diff --git a/src/backends/drm/drm_crtc.h b/src/backends/drm/drm_crtc.h index 073456098f..eb53b83e3e 100644 --- a/src/backends/drm/drm_crtc.h +++ b/src/backends/drm/drm_crtc.h @@ -37,11 +37,8 @@ public: drmModeModeInfo queryCurrentMode(); std::shared_ptr current() const; - std::shared_ptr next() const; void setCurrent(const std::shared_ptr &buffer); - void setNext(const std::shared_ptr &buffer); - void flipBuffer(); - void releaseBuffers(); + void releaseCurrentBuffer(); DrmProperty modeId; DrmProperty active; @@ -55,7 +52,6 @@ public: private: DrmUniquePtr m_crtc; std::shared_ptr m_currentBuffer; - std::shared_ptr m_nextBuffer; int m_pipeIndex; DrmPlane *m_primaryPlane; DrmPlane *m_cursorPlane; diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 4cee29bea1..7bb717423c 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -14,6 +14,7 @@ #include "core/session.h" #include "drm_backend.h" #include "drm_buffer.h" +#include "drm_commit.h" #include "drm_connector.h" #include "drm_crtc.h" #include "drm_egl_backend.h" @@ -539,7 +540,8 @@ static std::chrono::nanoseconds convertTimestamp(clockid_t sourceClock, clockid_ void DrmGpu::pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, unsigned int usec, unsigned int crtc_id, void *user_data) { - DrmGpu *gpu = static_cast(user_data); + const auto commit = static_cast(user_data); + const auto gpu = commit->gpu(); // The static_cast<> here are for a 32-bit environment where // sizeof(time_t) == sizeof(unsigned int) == 4 . Putting @p sec @@ -562,6 +564,7 @@ void DrmGpu::pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, un } else { (*it)->pageFlipped(timestamp); } + delete commit; } void DrmGpu::dispatchEvents() @@ -803,10 +806,10 @@ QSize DrmGpu::cursorSize() const void DrmGpu::releaseBuffers() { for (const auto &plane : std::as_const(m_planes)) { - plane->releaseBuffers(); + plane->releaseCurrentBuffer(); } for (const auto &crtc : std::as_const(m_crtcs)) { - crtc->releaseBuffers(); + crtc->releaseCurrentBuffer(); } for (const auto &pipeline : std::as_const(m_pipelines)) { pipeline->primaryLayer()->releaseBuffers(); diff --git a/src/backends/drm/drm_object.cpp b/src/backends/drm/drm_object.cpp index edfe6808df..39bda42505 100644 --- a/src/backends/drm/drm_object.cpp +++ b/src/backends/drm/drm_object.cpp @@ -10,7 +10,7 @@ #include -#include "drm_atomic_commit.h" +#include "drm_commit.h" #include "drm_gpu.h" #include "drm_logging.h" #include "drm_pointer.h" diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index 31ae92e4c0..d14cede697 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -12,9 +12,9 @@ #include #include "core/session.h" -#include "drm_atomic_commit.h" #include "drm_backend.h" #include "drm_buffer.h" +#include "drm_commit.h" #include "drm_commit_thread.h" #include "drm_connector.h" #include "drm_crtc.h" @@ -139,19 +139,12 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QVectorcommitModeset()) { qCCritical(KWIN_DRM) << "Atomic modeset commit failed!" << strerror(errno); return errnoToError(); } std::for_each(pipelines.begin(), pipelines.end(), std::mem_fn(&DrmPipeline::atomicModesetSuccessful)); - for (const auto &obj : unusedObjects) { - if (auto crtc = dynamic_cast(obj)) { - crtc->flipBuffer(); - } else if (auto plane = dynamic_cast(obj)) { - plane->flipBuffer(); - } - } return Error::None; } case CommitMode::Test: { @@ -221,15 +214,15 @@ bool DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commit) return false; } - const auto fb = m_pending.layer->currentBuffer().get(); + const auto fb = m_pending.layer->currentBuffer(); m_pending.crtc->primaryPlane()->set(commit, QPoint(0, 0), fb->buffer()->size(), centerBuffer(fb->buffer()->size(), m_pending.mode->size())); - commit->addProperty(m_pending.crtc->primaryPlane()->fbId, fb->framebufferId()); + commit->addBuffer(m_pending.crtc->primaryPlane(), fb); if (auto plane = m_pending.crtc->cursorPlane()) { const auto layer = cursorLayer(); plane->set(commit, QPoint(0, 0), gpu()->cursorSize(), QRect(layer->position(), gpu()->cursorSize())); commit->addProperty(plane->crtcId, layer->isVisible() ? m_pending.crtc->id() : 0); - commit->addProperty(plane->fbId, layer->isVisible() ? layer->currentBuffer()->framebufferId() : 0); + commit->addBuffer(plane, layer->isVisible() ? layer->currentBuffer() : nullptr); } return true; } @@ -350,12 +343,6 @@ void DrmPipeline::atomicCommitSuccessful() if (activePending()) { m_pageflipPending = true; } - if (m_pending.crtc) { - m_pending.crtc->primaryPlane()->setNext(m_pending.layer->currentBuffer()); - if (m_pending.crtc->cursorPlane()) { - m_pending.crtc->cursorPlane()->setNext(cursorLayer()->currentBuffer()); - } - } m_current = m_pending; } @@ -426,13 +413,6 @@ DrmGpu *DrmPipeline::gpu() const void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp) { - m_current.crtc->flipBuffer(); - if (m_current.crtc->primaryPlane()) { - m_current.crtc->primaryPlane()->flipBuffer(); - } - if (m_current.crtc->cursorPlane()) { - m_current.crtc->cursorPlane()->flipBuffer(); - } m_pageflipPending = false; if (m_output) { m_output->pageFlipped(timestamp); diff --git a/src/backends/drm/drm_pipeline_legacy.cpp b/src/backends/drm/drm_pipeline_legacy.cpp index 8ed66a87c2..181bc7fc7c 100644 --- a/src/backends/drm/drm_pipeline_legacy.cpp +++ b/src/backends/drm/drm_pipeline_legacy.cpp @@ -7,8 +7,9 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "drm_buffer.h" #include "core/graphicsbuffer.h" +#include "drm_buffer.h" +#include "drm_commit.h" #include "drm_connector.h" #include "drm_crtc.h" #include "drm_gpu.h" @@ -35,12 +36,14 @@ DrmPipeline::Error DrmPipeline::presentLegacy() if (m_pending.syncMode == RenderLoopPrivate::SyncMode::Async || m_pending.syncMode == RenderLoopPrivate::SyncMode::AdaptiveAsync) { flags |= DRM_MODE_PAGE_FLIP_ASYNC; } - if (drmModePageFlip(gpu()->fd(), m_pending.crtc->id(), buffer->framebufferId(), flags, gpu()) != 0) { + auto commit = std::make_unique(m_pending.crtc, buffer); + if (!commit->doPageflip(flags)) { qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno); return errnoToError(); } + // the pageflip takes ownership of the object + commit.release(); m_pageflipPending = true; - m_pending.crtc->setNext(buffer); return Error::None; } @@ -51,21 +54,14 @@ void DrmPipeline::forceLegacyModeset() DrmPipeline::Error DrmPipeline::legacyModeset() { - uint32_t connId = m_connector->id(); if (!m_pending.layer->checkTestBuffer()) { return Error::TestBufferFailed; } - const auto buffer = m_pending.layer->currentBuffer(); - if (drmModeSetCrtc(gpu()->fd(), m_pending.crtc->id(), buffer->framebufferId(), 0, 0, &connId, 1, m_pending.mode->nativeMode()) != 0) { + auto commit = std::make_unique(m_pending.crtc, m_pending.layer->currentBuffer()); + if (!commit->doModeset(m_connector, m_pending.mode.get())) { qCWarning(KWIN_DRM) << "Modeset failed!" << strerror(errno); return errnoToError(); } - // make sure the buffer gets kept alive, or the modeset gets reverted by the kernel - if (m_pending.crtc->current()) { - m_pending.crtc->setNext(buffer); - } else { - m_pending.crtc->setCurrent(buffer); - } return Error::None; } diff --git a/src/backends/drm/drm_plane.cpp b/src/backends/drm/drm_plane.cpp index 7e8f71a71d..99da63b40c 100644 --- a/src/backends/drm/drm_plane.cpp +++ b/src/backends/drm/drm_plane.cpp @@ -11,8 +11,8 @@ #include "config-kwin.h" -#include "drm_atomic_commit.h" #include "drm_buffer.h" +#include "drm_commit.h" #include "drm_gpu.h" #include "drm_logging.h" #include "drm_pointer.h" @@ -107,17 +107,6 @@ bool DrmPlane::updateProperties() return true; } -void DrmPlane::setNext(const std::shared_ptr &b) -{ - m_next = b; -} - -void DrmPlane::flipBuffer() -{ - m_current = m_next; - m_next = nullptr; -} - void DrmPlane::set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst) { // Src* are in 16.16 fixed point format @@ -142,17 +131,12 @@ QMap> DrmPlane::formats() const return m_supportedFormats; } -std::shared_ptr DrmPlane::current() const +std::shared_ptr DrmPlane::currentBuffer() const { return m_current; } -std::shared_ptr DrmPlane::next() const -{ - return m_next; -} - -void DrmPlane::setCurrent(const std::shared_ptr &b) +void DrmPlane::setCurrentBuffer(const std::shared_ptr &b) { m_current = b; } @@ -160,15 +144,11 @@ void DrmPlane::setCurrent(const std::shared_ptr &b) void DrmPlane::disable(DrmAtomicCommit *commit) { commit->addProperty(crtcId, 0); - commit->addProperty(fbId, 0); - m_next = nullptr; + commit->addBuffer(this, nullptr); } -void DrmPlane::releaseBuffers() +void DrmPlane::releaseCurrentBuffer() { - if (m_next) { - m_next->releaseBuffer(); - } if (m_current) { m_current->releaseBuffer(); } diff --git a/src/backends/drm/drm_plane.h b/src/backends/drm/drm_plane.h index 921bc71f2f..6daf1dcf3e 100644 --- a/src/backends/drm/drm_plane.h +++ b/src/backends/drm/drm_plane.h @@ -35,16 +35,12 @@ public: bool isCrtcSupported(int pipeIndex) const; QMap> formats() const; - std::shared_ptr current() const; - std::shared_ptr next() const; - void setCurrent(const std::shared_ptr &b); - void setNext(const std::shared_ptr &b); - void flipBuffer(); + std::shared_ptr currentBuffer() const; + void setCurrentBuffer(const std::shared_ptr &b); + void releaseCurrentBuffer(); void set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst); - void releaseBuffers(); - enum class TypeIndex : uint64_t { Overlay = 0, Primary = 1, @@ -86,7 +82,6 @@ public: private: std::shared_ptr m_current; - std::shared_ptr m_next; QMap> m_supportedFormats; uint32_t m_possibleCrtcs;