From 56e7659ad887fe02528682134c01e3c284b26b8e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 8 Jul 2024 15:57:16 +0200 Subject: [PATCH] drm: recheck CRTCs after launch and reset --- include/aquamarine/backend/DRM.hpp | 1 + include/aquamarine/output/Output.hpp | 2 +- src/allocator/GBM.cpp | 6 +-- src/backend/drm/DRM.cpp | 75 ++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 3f34473..b8a7e5f 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -345,6 +345,7 @@ namespace Aquamarine { void scanConnectors(); void scanLeases(); void restoreAfterVT(); + void recheckCRTCs(); Hyprutils::Memory::CSharedPointer gpu; Hyprutils::Memory::CSharedPointer impl; diff --git a/include/aquamarine/output/Output.hpp b/include/aquamarine/output/Output.hpp index cfbdf81..0a5d017 100644 --- a/include/aquamarine/output/Output.hpp +++ b/include/aquamarine/output/Output.hpp @@ -148,7 +148,7 @@ namespace Aquamarine { AQ_OUTPUT_PRESENT_ZEROCOPY = (1 << 3), }; struct SStateEvent { - Hyprutils::Math::Vector2D size; + Hyprutils::Math::Vector2D size; // if {0,0}, means it needs a reconfigure. }; struct SPresentEvent { diff --git a/src/allocator/GBM.cpp b/src/allocator/GBM.cpp index 5a3757c..312e587 100644 --- a/src/allocator/GBM.cpp +++ b/src/allocator/GBM.cpp @@ -146,9 +146,9 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti auto modName = drmGetFormatModifierName(attrs.modifier); - allocator->backend->log( - AQ_LOG_DEBUG, - std::format("GBM: Allocated a new buffer with size {} and format {} with modifier {}", attrs.size, fourccToName(attrs.format), modName ? modName : "Unknown")); + allocator->backend->log(AQ_LOG_DEBUG, + std::format("GBM: Allocated a new buffer with size {} and format {} with modifier {} aka {}", attrs.size, fourccToName(attrs.format), attrs.modifier, + modName ? modName : "Unknown")); free(modName); } diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index a9e94d9..2592541 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -228,6 +228,8 @@ std::vector> Aquamarine::CDRMBackend::attempt(SP backe drmBackend->scanConnectors(); + drmBackend->recheckCRTCs(); + if (!newPrimary) { backend->log(AQ_LOG_DEBUG, std::format("drm: gpu {} becomes primary drm", gpu->path)); newPrimary = drmBackend; @@ -255,6 +257,7 @@ void Aquamarine::CDRMBackend::restoreAfterVT() { backend->log(AQ_LOG_DEBUG, "drm: Restoring after VT switch"); scanConnectors(); + recheckCRTCs(); backend->log(AQ_LOG_DEBUG, "drm: Rescanned connectors"); @@ -449,6 +452,78 @@ bool Aquamarine::CDRMBackend::initResources() { return true; } +void Aquamarine::CDRMBackend::recheckCRTCs() { + if (connectors.empty() || crtcs.empty()) + return; + + backend->log(AQ_LOG_DEBUG, "drm: Rechecking CRTCs"); + + std::vector> recheck, changed; + for (auto& c : connectors) { + if (c->crtc && c->status == DRM_MODE_CONNECTED) { + backend->log(AQ_LOG_DEBUG, std::format("drm: Skipping connector {}, has crtc {} and is connected", c->szName, c->crtc->id)); + continue; + } + + recheck.emplace_back(c); + backend->log(AQ_LOG_DEBUG, std::format("drm: connector {}, has crtc {}, will be rechecked", c->szName, c->crtc ? c->crtc->id : -1)); + } + + for (size_t i = 0; i < crtcs.size(); ++i) { + bool taken = false; + for (auto& c : connectors) { + if (c->crtc != crtcs.at(i)) + continue; + + if (c->status != DRM_MODE_CONNECTED) + continue; + + backend->log(AQ_LOG_DEBUG, std::format("drm: slot {} crtc {} taken by {}, skipping", i, c->crtc->id, c->szName)); + taken = true; + break; + } + + if (taken) + continue; + + bool assigned = false; + for (auto& c : recheck) { + if (!(c->possibleCrtcs & (1 << i))) + continue; + + // deactivate old output + if (c->output && c->output->state && c->output->state->state().enabled) { + c->output->state->setEnabled(false); + c->output->commit(); + } + + c->crtc = crtcs.at(i); + backend->log(AQ_LOG_DEBUG, std::format("drm: slot {} crtc {} assigned to {} (old {})", i, crtcs.at(i)->id, c->szName, c->crtc ? c->crtc->id : -1)); + assigned = true; + changed.emplace_back(c); + break; + } + + if (!assigned) + backend->log(AQ_LOG_DEBUG, std::format("drm: slot {} crtc {} unassigned", i, crtcs.at(i)->id)); + } + + // if any connectors get a crtc and are connected, we need to rescan to assign them outputs. + bool rescan = false; + for (auto& c : changed) { + if (!c->output && c->status == DRM_MODE_CONNECTED) { + rescan = true; + continue; + } + + // tell the user to re-assign a valid mode etc + c->output->events.state.emit(IOutput::SStateEvent{}); + } + + if (rescan) + scanConnectors(); +} + bool Aquamarine::CDRMBackend::grabFormats() { // FIXME: do this properly maybe? return true;