drm: add vt restore code and adaptive sync

This commit is contained in:
Vaxry 2024-06-25 13:23:31 +02:00
parent 2e0052a21d
commit d44aaec26f
5 changed files with 84 additions and 6 deletions

View file

@ -227,6 +227,7 @@ namespace Aquamarine {
class IDRMImplementation {
public:
virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) = 0;
virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) = 0;
};
class CDRMBackend : public IBackendImplementation {
@ -259,6 +260,7 @@ namespace Aquamarine {
bool initResources();
bool grabFormats();
void scanConnectors();
void restoreAfterVT();
Hyprutils::Memory::CSharedPointer<CSessionDevice> gpu;
Hyprutils::Memory::CSharedPointer<IDRMImplementation> 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;

View file

@ -7,6 +7,7 @@ namespace Aquamarine {
public:
CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_);
virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data);
virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
private:

View file

@ -57,7 +57,7 @@ namespace Aquamarine {
bool enabled = false;
bool adaptiveSync = false;
eOutputPresentationMode presentationMode = AQ_OUTPUT_PRESENTATION_VSYNC;
std::vector<uint16_t> gammaLut;
std::vector<uint16_t> gammaLut; // Gamma lut in the format [r,g,b]+
Hyprutils::Math::Vector2D lastModeSize;
Hyprutils::Memory::CWeakPointer<SOutputMode> mode;
Hyprutils::Memory::CSharedPointer<SOutputMode> 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;
//

View file

@ -23,7 +23,12 @@ using namespace Hyprutils::Math;
#define SP CSharedPointer
Aquamarine::CDRMBackend::CDRMBackend(SP<CBackend> 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))

View file

@ -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<SDRMCo
return false;
return commitInternal(connector, data);
}
bool Aquamarine::CDRMLegacyImpl::reset(SP<SDRMConnector> 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;
}