From ffad2dd7ada98249ec1f15bd0ca6cf7d89dbfdd5 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Sat, 10 Dec 2022 22:45:27 +0100 Subject: [PATCH] backends/drm: don't break crtc<->plane connections The kernel rejects such commits without the crtc being completely turned off first. BUG: 462214 --- src/backends/drm/drm_gpu.cpp | 37 ++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 9a5916ad0d..19fd3fccc6 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -170,27 +170,44 @@ void DrmGpu::initDrmResources() QVector assignedPlanes; for (int i = 0; i < resources->count_crtcs; ++i) { uint32_t crtcId = resources->crtcs[i]; - DrmPlane *primary = nullptr; - DrmPlane *cursor = nullptr; + QVector primaryCandidates; + QVector cursorCandidates; for (const auto &plane : m_planes) { if (plane->isCrtcSupported(i) && !assignedPlanes.contains(plane.get())) { if (plane->type() == DrmPlane::TypeIndex::Primary) { - if (!primary || primary->getProp(DrmPlane::PropertyIndex::CrtcId)->pending() == crtcId) { - primary = plane.get(); - } + primaryCandidates.push_back(plane.get()); } else if (plane->type() == DrmPlane::TypeIndex::Cursor) { - if (!cursor || cursor->getProp(DrmPlane::PropertyIndex::CrtcId)->pending() == crtcId) { - cursor = plane.get(); - } + cursorCandidates.push_back(plane.get()); } } } - if (m_atomicModeSetting && !primary) { + if (m_atomicModeSetting && primaryCandidates.empty()) { qCWarning(KWIN_DRM) << "Could not find a suitable primary plane for crtc" << resources->crtcs[i]; continue; } + const auto findBestPlane = [crtcId](const QVector &list) { + // if the plane is already used with this crtc, prefer it + const auto connected = std::find_if(list.begin(), list.end(), [crtcId](DrmPlane *plane) { + return plane->getProp(DrmPlane::PropertyIndex::CrtcId)->pending() == crtcId; + }); + if (connected != list.end()) { + return *connected; + } + // don't take away planes from other crtcs. The kernel currently rejects such commits + const auto notconnected = std::find_if(list.begin(), list.end(), [](DrmPlane *plane) { + return plane->getProp(DrmPlane::PropertyIndex::CrtcId)->pending() == 0; + }); + if (notconnected == list.end()) { + return *notconnected; + } + return list.empty() ? nullptr : list.front(); + }; + DrmPlane *primary = findBestPlane(primaryCandidates); + DrmPlane *cursor = findBestPlane(cursorCandidates); assignedPlanes.push_back(primary); - assignedPlanes.push_back(cursor); + if (cursor) { + assignedPlanes.push_back(cursor); + } auto crtc = std::make_unique(this, crtcId, i, primary, cursor); if (!crtc->init()) { continue;