From 7e4ae2e2263bf229bd22d5e14f22c111be4ef0bd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 2 Jul 2024 12:41:32 +0200 Subject: [PATCH] drm/atomic: add support for gamma ramps --- include/aquamarine/backend/DRM.hpp | 4 ++++ src/backend/drm/DRM.cpp | 21 +++++++++++++++++--- src/backend/drm/impl/Atomic.cpp | 32 ++++++++++++++++++++++++------ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index dbe63a0..85e31c3 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -162,6 +162,7 @@ namespace Aquamarine { virtual void scheduleFrame(); virtual void setCursorVisible(bool visible); virtual Hyprutils::Math::Vector2D cursorPlaneSize(); + virtual size_t getGammaSize(); Hyprutils::Memory::CWeakPointer self; bool cursorVisible = true; @@ -199,6 +200,7 @@ namespace Aquamarine { uint32_t fbDamage = 0; uint32_t modeBlob = 0; bool blobbed = false; + bool gammad = false; } atomic; void calculateMode(Hyprutils::Memory::CSharedPointer connector); @@ -321,6 +323,8 @@ namespace Aquamarine { std::vector> connectors; std::vector formats; + bool atomic = false; + struct { Hyprutils::Math::Vector2D cursorSize; bool supportsAsyncCommit = false; diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 1a06d59..7c49bef 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -315,9 +315,8 @@ bool Aquamarine::CDRMBackend::checkFeatures() { drmProps.supportsAsyncCommit = drmGetCap(gpu->fd, DRM_CAP_ASYNC_PAGE_FLIP, &cap) == 0 && cap == 1; drmProps.supportsAddFb2Modifiers = drmGetCap(gpu->fd, DRM_CAP_ADDFB2_MODIFIERS, &cap) == 0 && cap == 1; - // FIXME: move to NO_ATOMIC when this piece of shit works - if (!envEnabled("AQ_ATOMIC")) { - backend->log(AQ_LOG_WARNING, "drm: AQ_ATOMIC not enabled, using the legacy drm iface"); + if (envEnabled("AQ_NO_ATOMIC")) { + backend->log(AQ_LOG_WARNING, "drm: AQ_NO_ATOMIC enabled, using the legacy drm iface"); impl = makeShared(self.lock()); } else if (drmSetClientCap(gpu->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { backend->log(AQ_LOG_WARNING, "drm: failed to set DRM_CLIENT_CAP_ATOMIC, falling back to legacy"); @@ -326,6 +325,7 @@ bool Aquamarine::CDRMBackend::checkFeatures() { backend->log(AQ_LOG_DEBUG, "drm: Atomic supported, using atomic for modesetting"); impl = makeShared(self.lock()); drmProps.supportsAsyncCommit = drmGetCap(gpu->fd, DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP, &cap) == 0 && cap == 1; + atomic = true; } backend->log(AQ_LOG_DEBUG, std::format("drm: drmProps.supportsAsyncCommit: {}", drmProps.supportsAsyncCommit)); @@ -1206,6 +1206,21 @@ Vector2D Aquamarine::CDRMOutput::cursorPlaneSize() { return backend->drmProps.cursorSize; } +size_t Aquamarine::CDRMOutput::getGammaSize() { + if (!backend->atomic) { + backend->log(AQ_LOG_ERROR, "No support for gamma on the legacy iface"); + return 0; + } + + uint64_t size = 0; + if (!getDRMProp(backend->gpu->fd, connector->crtc->id, connector->crtc->props.gamma_lut_size, &size)) { + backend->log(AQ_LOG_ERROR, "Couldn't get the gamma_size prop"); + return 0; + } + + return size; +} + Aquamarine::CDRMOutput::CDRMOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer backend_, SP connector_) : backend(backend_), connector(connector_) { name = name_; diff --git a/src/backend/drm/impl/Atomic.cpp b/src/backend/drm/impl/Atomic.cpp index 8b2ad6b..3cfde46 100644 --- a/src/backend/drm/impl/Atomic.cpp +++ b/src/backend/drm/impl/Atomic.cpp @@ -99,7 +99,9 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint add(connector->crtc->id, connector->crtc->props.active, enable); if (enable) { - // TODO: gamma + if (connector->crtc->props.gamma_lut && data.atomic.gammad) + add(connector->crtc->id, connector->crtc->props.gamma_lut, data.atomic.gammaLut); + if (connector->crtc->props.vrr_enabled) add(connector->crtc->id, connector->crtc->props.vrr_enabled, (uint64_t)STATE.adaptiveSync); @@ -184,8 +186,7 @@ void Aquamarine::CDRMAtomicRequest::rollback(SDRMConnectorCommitData& data) { conn->crtc->atomic.ownModeID = true; if (data.atomic.blobbed) rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); - // TODO: gamma - //rollbackBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); + rollbackBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut); destroyBlob(data.atomic.fbDamage); } @@ -199,8 +200,7 @@ void Aquamarine::CDRMAtomicRequest::apply(SDRMConnectorCommitData& data) { conn->crtc->atomic.ownModeID = true; if (data.atomic.blobbed) commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); - // TODO: gamma - //commitBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); + commitBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut); destroyBlob(data.atomic.fbDamage); } @@ -227,7 +227,27 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin } } - // TODO: gamma + if (STATE.committed & COutputState::AQ_OUTPUT_STATE_GAMMA_LUT) { + if (!connector->crtc->props.gamma_lut) // TODO: allow this with legacy gamma, perhaps. + connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to commit gamma: no gamma_lut prop"); + else { + std::vector lut; + lut.resize(STATE.gammaLut.size() / 3); // [r,g,b]+ + + for (size_t i = 0; i < lut.size(); ++i) { + lut.at(i).red = STATE.gammaLut.at(i * 3 + 0); + lut.at(i).green = STATE.gammaLut.at(i * 3 + 1); + lut.at(i).blue = STATE.gammaLut.at(i * 3 + 2); + lut.at(i).reserved = 0; + } + + if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, lut.data(), lut.size() * sizeof(drm_color_lut), &data.atomic.gammaLut)) { + connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a gamma blob"); + data.atomic.gammaLut = 0; + } else + data.atomic.gammad = true; + } + } if (STATE.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE && connector->crtc->primary->props.fb_damage_clips) { if (STATE.damage.empty())