diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 9c94c67..7418655 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -227,6 +227,7 @@ namespace Aquamarine { class IDRMImplementation { public: virtual bool commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) = 0; + virtual bool reset(Hyprutils::Memory::CSharedPointer connector) = 0; }; class CDRMBackend : public IBackendImplementation { @@ -259,6 +260,7 @@ namespace Aquamarine { bool initResources(); bool grabFormats(); void scanConnectors(); + void restoreAfterVT(); Hyprutils::Memory::CSharedPointer gpu; Hyprutils::Memory::CSharedPointer impl; @@ -277,6 +279,10 @@ namespace Aquamarine { bool supportsAddFb2Modifiers = false; } drmProps; + struct { + Hyprutils::Signal::CHyprSignalListener sessionActivate; + } listeners; + friend class CBackend; friend class CDRMFB; friend class CDRMFBAttachment; diff --git a/include/aquamarine/backend/drm/Legacy.hpp b/include/aquamarine/backend/drm/Legacy.hpp index 9baff38..1f19a6b 100644 --- a/include/aquamarine/backend/drm/Legacy.hpp +++ b/include/aquamarine/backend/drm/Legacy.hpp @@ -7,6 +7,7 @@ namespace Aquamarine { public: CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer backend_); virtual bool commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + virtual bool reset(Hyprutils::Memory::CSharedPointer connector); private: diff --git a/include/aquamarine/output/Output.hpp b/include/aquamarine/output/Output.hpp index 73fe4a3..d2f53be 100644 --- a/include/aquamarine/output/Output.hpp +++ b/include/aquamarine/output/Output.hpp @@ -57,7 +57,7 @@ namespace Aquamarine { bool enabled = false; bool adaptiveSync = false; eOutputPresentationMode presentationMode = AQ_OUTPUT_PRESENTATION_VSYNC; - std::vector gammaLut; + std::vector gammaLut; // Gamma lut in the format [r,g,b]+ Hyprutils::Math::Vector2D lastModeSize; Hyprutils::Memory::CWeakPointer mode; Hyprutils::Memory::CSharedPointer customMode; @@ -109,7 +109,7 @@ namespace Aquamarine { bool enabled = false; bool nonDesktop = false; eSubpixelMode subpixel = AQ_SUBPIXEL_NONE; - bool vrrCapable = false; + bool vrrCapable = false, vrrActive = false; bool needsFrame = false; // diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 888ab6a..92a9ffb 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -23,7 +23,12 @@ using namespace Hyprutils::Math; #define SP CSharedPointer Aquamarine::CDRMBackend::CDRMBackend(SP backend_) : backend(backend_) { - ; + listeners.sessionActivate = backend->session->events.changeActive.registerListener([this](std::any d) { + if (backend->session->active) { + // session got activated, we need to restore + restoreAfterVT(); + } + }); } static udev_enumerate* enumDRMCards(udev* udev) { @@ -206,6 +211,45 @@ bool Aquamarine::CDRMBackend::sessionActive() { return backend->session->active; } +void Aquamarine::CDRMBackend::restoreAfterVT() { + backend->log(AQ_LOG_DEBUG, "drm: Restoring after VT switch"); + + for (auto& c : connectors) { + if (!c->crtc) + continue; + + backend->log(AQ_LOG_DEBUG, std::format("drm: Resetting crtc {}", c->crtc->id)); + + if (!impl->reset(c)) + backend->log(AQ_LOG_ERROR, std::format("drm: crtc {} failed reset", c->crtc->id)); + } + + for (auto& c : connectors) { + if (!c->crtc) + continue; + + SDRMConnectorCommitData data = { + .mainFB = nullptr, + .modeset = true, + .blocking = true, + .flags = 0, + .test = false, + }; + + if (c->output->state->state().mode && c->output->state->state().mode->modeInfo.has_value()) + data.modeInfo = *c->output->state->state().mode->modeInfo; + else + data.calculateMode(c); + + backend->log(AQ_LOG_DEBUG, + std::format("drm: Restoring crtc {} with clock {} hdisplay {} vdisplay {} vrefresh {}", c->crtc->id, data.modeInfo.clock, data.modeInfo.hdisplay, + data.modeInfo.vdisplay, data.modeInfo.vrefresh)); + + if (!impl->commit(c, data)) + backend->log(AQ_LOG_ERROR, std::format("drm: crtc {} failed restore", c->crtc->id)); + } +} + bool Aquamarine::CDRMBackend::checkFeatures() { uint64_t curW = 0, curH = 0; if (drmGetCap(gpu->fd, DRM_CAP_CURSOR_WIDTH, &curW)) diff --git a/src/backend/drm/impl/Legacy.cpp b/src/backend/drm/impl/Legacy.cpp index 389cfa5..368fee9 100644 --- a/src/backend/drm/impl/Legacy.cpp +++ b/src/backend/drm/impl/Legacy.cpp @@ -41,7 +41,6 @@ bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointe mode = (drmModeModeInfo*)&data.modeInfo; } - connector->backend->backend->log(AQ_LOG_DEBUG, std::format("legacy drm: Modesetting CRTC, connectors: {}", connectors.size())); connector->backend->backend->log( AQ_LOG_DEBUG, std::format("legacy drm: Modesetting CRTC, mode: clock {} hdisplay {} vdisplay {} vrefresh {}", mode->clock, mode->hdisplay, mode->vdisplay, mode->vrefresh)); @@ -52,9 +51,25 @@ bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointe } } - // TODO: gamma + if (STATE.committed & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_ADAPTIVE_SYNC) { + if (STATE.adaptiveSync && !connector->canDoVrr) { + connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: connector {} can't do vrr", connector->id)); + return false; + } - // TODO: Adaptive sync + if (connector->crtc->props.vrr_enabled) { + if (auto ret = drmModeObjectSetProperty(backend->gpu->fd, connector->crtc->id, DRM_MODE_OBJECT_CRTC, connector->crtc->props.vrr_enabled, (uint64_t)STATE.adaptiveSync); + ret) { + connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModeObjectSetProperty: vrr -> {} failed: {}", STATE.adaptiveSync, strerror(-ret))); + return false; + } + } + + connector->output->vrrActive = STATE.adaptiveSync; + connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: connector {} vrr -> {}", connector->id, STATE.adaptiveSync)); + } + + // TODO: gamma // TODO: cursor plane if (drmModeSetCursor(connector->backend->gpu->fd, connector->crtc->id, 0, 0, 0)) @@ -85,4 +100,16 @@ bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer connector) { + if (!connector->crtc) + return true; + + if (int ret = drmModeSetCrtc(backend->gpu->fd, connector->crtc->id, 0, 0, 0, nullptr, 0, nullptr); ret) { + connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: reset failed: {}", strerror(-ret))); + return false; + } + + return true; } \ No newline at end of file