diff --git a/src/backends/drm/drm_commit_thread.cpp b/src/backends/drm/drm_commit_thread.cpp index 65601e1870..46d91af283 100644 --- a/src/backends/drm/drm_commit_thread.cpp +++ b/src/backends/drm/drm_commit_thread.cpp @@ -30,19 +30,20 @@ DrmCommitThread::DrmCommitThread() return; } std::unique_lock lock(m_mutex); - if (!m_commit) { + if (m_commits.empty()) { m_commitPending.wait(lock); } - if (m_commit) { + if (!m_commits.empty()) { const auto now = std::chrono::steady_clock::now(); if (m_targetPageflipTime > now + s_safetyMargin) { lock.unlock(); std::this_thread::sleep_until(m_targetPageflipTime - s_safetyMargin); lock.lock(); } - // the other thread may replace the commit, but not erase it - Q_ASSERT(m_commit); - if (!m_commit->areBuffersReadable()) { + const auto it = std::find_if(m_commits.rbegin(), m_commits.rend(), [](const auto &commit) { + return commit->areBuffersReadable(); + }); + if (it == m_commits.rend()) { // reschedule, this commit would not hit the pageflip deadline anyways if (m_vrr) { m_targetPageflipTime += 50us; @@ -51,17 +52,23 @@ DrmCommitThread::DrmCommitThread() } continue; } - const bool vrr = m_commit->isVrr(); - if (m_commit->commit()) { + auto &commit = *it; + const bool vrr = commit->isVrr(); + const bool success = commit->commit(); + if (success) { m_vrr = vrr; // the atomic commit takes ownership of the object - m_commit.release(); - } else { - qCWarning(KWIN_DRM) << "atomic commit failed:" << strerror(errno); - m_droppedCommits.push_back(std::move(m_commit)); - QMetaObject::invokeMethod(this, &DrmCommitThread::commitFailed, Qt::ConnectionType::QueuedConnection); - QMetaObject::invokeMethod(this, &DrmCommitThread::clearDroppedCommits, Qt::ConnectionType::QueuedConnection); + commit.release(); } + for (auto &commit : m_commits) { + m_droppedCommits.push_back(std::move(commit)); + } + m_commits.clear(); + if (!success) { + qCWarning(KWIN_DRM) << "atomic commit failed:" << strerror(errno); + QMetaObject::invokeMethod(this, &DrmCommitThread::commitFailed, Qt::ConnectionType::QueuedConnection); + } + QMetaObject::invokeMethod(this, &DrmCommitThread::clearDroppedCommits, Qt::ConnectionType::QueuedConnection); } } })); @@ -75,10 +82,10 @@ DrmCommitThread::~DrmCommitThread() m_thread->wait(); } -void DrmCommitThread::setCommit(std::unique_ptr &&commit) +void DrmCommitThread::addCommit(std::unique_ptr &&commit) { std::unique_lock lock(m_mutex); - m_commit = std::move(commit); + m_commits.push_back(std::move(commit)); const auto now = std::chrono::steady_clock::now(); if (m_vrr && now >= m_lastPageflip + m_minVblankInterval) { m_targetPageflipTime = now; @@ -88,12 +95,11 @@ void DrmCommitThread::setCommit(std::unique_ptr &&commit) m_commitPending.notify_all(); } -bool DrmCommitThread::replaceCommit(std::unique_ptr &&commit) +bool DrmCommitThread::updateCommit(std::unique_ptr &&commit) { std::unique_lock lock(m_mutex); - if (m_commit) { - m_commit = std::move(commit); - m_commitPending.notify_all(); + if (!m_commits.empty()) { + m_commits.push_back(std::move(commit)); return true; } else { return false; diff --git a/src/backends/drm/drm_commit_thread.h b/src/backends/drm/drm_commit_thread.h index 2333e89b1a..5f308bbbe1 100644 --- a/src/backends/drm/drm_commit_thread.h +++ b/src/backends/drm/drm_commit_thread.h @@ -29,8 +29,8 @@ public: explicit DrmCommitThread(); ~DrmCommitThread(); - void setCommit(std::unique_ptr &&commit); - bool replaceCommit(std::unique_ptr &&commit); + void addCommit(std::unique_ptr &&commit); + bool updateCommit(std::unique_ptr &&commit); void setRefreshRate(uint32_t maximum); void pageFlipped(std::chrono::nanoseconds timestamp); @@ -42,7 +42,7 @@ private: void clearDroppedCommits(); TimePoint estimateNextVblank(TimePoint now) const; - std::unique_ptr m_commit; + std::vector> m_commits; std::unique_ptr m_thread; std::mutex m_mutex; std::condition_variable m_commitPending; diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index c76b4c4d35..e95e54811c 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -175,7 +175,7 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QVectorm_commitThread->setCommit(std::move(commit)); + pipeline->m_commitThread->addCommit(std::move(commit)); pipeline->atomicCommitSuccessful(); return Error::None; } @@ -186,7 +186,7 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QVectorm_commitThread->replaceCommit(std::move(commit))) { + if (pipeline->m_commitThread->updateCommit(std::move(commit))) { pipeline->atomicCommitSuccessful(); } return Error::None;