drm: recheck CRTCs after launch and reset

This commit is contained in:
Vaxry 2024-07-08 15:57:16 +02:00
parent dc1181a65e
commit 56e7659ad8
4 changed files with 80 additions and 4 deletions

View file

@ -345,6 +345,7 @@ namespace Aquamarine {
void scanConnectors();
void scanLeases();
void restoreAfterVT();
void recheckCRTCs();
Hyprutils::Memory::CSharedPointer<CSessionDevice> gpu;
Hyprutils::Memory::CSharedPointer<IDRMImplementation> impl;

View file

@ -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 {

View file

@ -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);
}

View file

@ -228,6 +228,8 @@ std::vector<SP<CDRMBackend>> Aquamarine::CDRMBackend::attempt(SP<CBackend> 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<SP<SDRMConnector>> 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;