From 9ea6f311ead4566feb4d94db23a815230302e5c9 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Thu, 21 Dec 2023 03:23:29 +0100 Subject: [PATCH] backends/drm: force a modeset when connectors are unplugged And turn off unused CRTCs with legacy BUG: 478476 --- src/backends/drm/drm_gpu.cpp | 12 ++++++------ src/backends/drm/drm_gpu.h | 1 + src/backends/drm/drm_pipeline.cpp | 2 +- src/backends/drm/drm_pipeline.h | 2 +- src/backends/drm/drm_pipeline_legacy.cpp | 7 ++++++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 4137351103..62afaf9191 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -578,6 +578,8 @@ void DrmGpu::removeOutput(DrmOutput *output) m_drmOutputs.removeOne(output); Q_EMIT outputRemoved(output); output->unref(); + // force a modeset to make sure unused objects are cleaned up + m_forceModeset = true; } DrmBackend *DrmGpu::platform() const @@ -740,9 +742,9 @@ bool DrmGpu::isActive() const bool DrmGpu::needsModeset() const { - return std::any_of(m_pipelines.constBegin(), m_pipelines.constEnd(), [](const auto &pipeline) { - return pipeline->needsModeset(); - }); + return m_forceModeset || std::any_of(m_pipelines.constBegin(), m_pipelines.constEnd(), [](const auto &pipeline) { + return pipeline->needsModeset(); + }); } bool DrmGpu::maybeModeset() @@ -771,6 +773,7 @@ bool DrmGpu::maybeModeset() } } } + m_forceModeset = false; if (err == DrmPipeline::Error::None) { return true; } else { @@ -783,9 +786,6 @@ bool DrmGpu::maybeModeset() QList DrmGpu::unusedObjects() const { - if (!m_atomicModeSetting) { - return {}; - } QList ret = m_allObjects; for (const auto &pipeline : m_pipelines) { ret.removeOne(pipeline->connector()); diff --git a/src/backends/drm/drm_gpu.h b/src/backends/drm/drm_gpu.h index 7caa841b9e..656c435fa2 100644 --- a/src/backends/drm/drm_gpu.h +++ b/src/backends/drm/drm_gpu.h @@ -143,6 +143,7 @@ private: bool m_asyncPageflipSupported = false; bool m_isRemoved = false; bool m_isActive = true; + bool m_forceModeset = false; clockid_t m_presentationClock; gbm_device *m_gbmDevice; FileDescriptor m_gbmFd; diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index 1a1b759ca9..93fda5f520 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -118,7 +118,7 @@ DrmPipeline::Error DrmPipeline::commitPipelines(const QList &pipe if (pipelines[0]->gpu()->atomicModeSetting()) { return commitPipelinesAtomic(pipelines, mode, unusedObjects); } else { - return commitPipelinesLegacy(pipelines, mode); + return commitPipelinesLegacy(pipelines, mode, unusedObjects); } } diff --git a/src/backends/drm/drm_pipeline.h b/src/backends/drm/drm_pipeline.h index e7b588e5d8..5ba6aa240a 100644 --- a/src/backends/drm/drm_pipeline.h +++ b/src/backends/drm/drm_pipeline.h @@ -153,7 +153,7 @@ private: Error legacyModeset(); Error applyPendingChangesLegacy(); bool setCursorLegacy(); - static Error commitPipelinesLegacy(const QList &pipelines, CommitMode mode); + static Error commitPipelinesLegacy(const QList &pipelines, CommitMode mode, const QList &unusedObjects); // atomic modesetting only Error prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode); diff --git a/src/backends/drm/drm_pipeline_legacy.cpp b/src/backends/drm/drm_pipeline_legacy.cpp index 9ed43966e3..c7962339d2 100644 --- a/src/backends/drm/drm_pipeline_legacy.cpp +++ b/src/backends/drm/drm_pipeline_legacy.cpp @@ -57,7 +57,7 @@ DrmPipeline::Error DrmPipeline::legacyModeset() return Error::None; } -DrmPipeline::Error DrmPipeline::commitPipelinesLegacy(const QList &pipelines, CommitMode mode) +DrmPipeline::Error DrmPipeline::commitPipelinesLegacy(const QList &pipelines, CommitMode mode, const QList &unusedObjects) { Error err = Error::None; for (const auto &pipeline : pipelines) { @@ -79,6 +79,11 @@ DrmPipeline::Error DrmPipeline::commitPipelinesLegacy(const QList pipeline->pageFlipped(std::chrono::steady_clock::now().time_since_epoch(), PageflipType::Normal, PresentationMode::VSync); } } + for (const auto &obj : unusedObjects) { + if (auto crtc = dynamic_cast(obj)) { + drmModeSetCrtc(pipelines.front()->gpu()->fd(), crtc->id(), 0, 0, 0, nullptr, 0, nullptr); + } + } } return err; }