diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 040cad7..40ea97a 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace Aquamarine { class CDRMBackend; @@ -162,6 +163,7 @@ namespace Aquamarine { bool ownModeID = false; uint32_t modeID = 0; uint32_t gammaLut = 0; + uint32_t ctm = 0; } atomic; Hyprutils::Memory::CSharedPointer primary; @@ -175,6 +177,7 @@ namespace Aquamarine { uint32_t vrr_enabled; uint32_t gamma_lut; uint32_t gamma_lut_size; + uint32_t ctm; // atomic-modesetting only @@ -242,13 +245,16 @@ namespace Aquamarine { uint32_t flags = 0; bool test = false; drmModeModeInfo modeInfo; + std::optional ctm; struct { uint32_t gammaLut = 0; uint32_t fbDamage = 0; uint32_t modeBlob = 0; + uint32_t ctmBlob = 0; bool blobbed = false; bool gammad = false; + bool ctmd = false; } atomic; void calculateMode(Hyprutils::Memory::CSharedPointer connector); diff --git a/include/aquamarine/output/Output.hpp b/include/aquamarine/output/Output.hpp index 29e204b..9b0519f 100644 --- a/include/aquamarine/output/Output.hpp +++ b/include/aquamarine/output/Output.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include "../allocator/Swapchain.hpp" @@ -51,6 +52,7 @@ namespace Aquamarine { AQ_OUTPUT_STATE_BUFFER = (1 << 7), AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE = (1 << 8), AQ_OUTPUT_STATE_EXPLICIT_OUT_FENCE = (1 << 9), + AQ_OUTPUT_STATE_CTM = (1 << 10), }; struct SInternalState { @@ -67,6 +69,7 @@ namespace Aquamarine { uint32_t drmFormat = DRM_FORMAT_INVALID; Hyprutils::Memory::CSharedPointer buffer; int64_t explicitInFence = -1, explicitOutFence = -1; + Hyprutils::Math::Mat3x3 ctm; }; const SInternalState& state(); @@ -84,6 +87,7 @@ namespace Aquamarine { void setExplicitInFence(int64_t fenceFD); // -1 removes void setExplicitOutFence(int64_t fenceFD); // -1 removes void resetExplicitFences(); + void setCTM(const Hyprutils::Math::Mat3x3& ctm); private: SInternalState internalState; diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index 26d5c4b..4176083 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -1183,6 +1183,8 @@ void Aquamarine::SDRMConnector::recheckCRTCProps() { output->supportsExplicit = backend->drmProps.supportsTimelines && crtc->props.out_fence_ptr && crtc->primary->props.in_fence_fd; backend->backend->log(AQ_LOG_DEBUG, std::format("drm: Explicit sync {}", output->supportsExplicit ? "supported" : "unsupported")); + + backend->backend->log(AQ_LOG_DEBUG, std::format("drm: connector {} crtc {} CTM", szName, (crtc->props.ctm ? "supports" : "doesn't support"))); } void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) { @@ -1577,6 +1579,9 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { } } + if (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_CTM) + data.ctm = STATE.ctm; + data.blocking = BLOCKING || formatMismatch; data.modeset = NEEDS_RECONFIG || lastCommitNoBuffer || formatMismatch; data.flags = flags; diff --git a/src/backend/drm/Props.cpp b/src/backend/drm/Props.cpp index e31d4d7..5aa298e 100644 --- a/src/backend/drm/Props.cpp +++ b/src/backend/drm/Props.cpp @@ -38,6 +38,7 @@ static const struct prop_info crtc_info[] = { #define INDEX(name) (offsetof(SDRMCRTC::UDRMCRTCProps, name) / sizeof(uint32_t)) {"ACTIVE", INDEX(active)}, {"GAMMA_LUT", INDEX(gamma_lut)}, {"GAMMA_LUT_SIZE", INDEX(gamma_lut_size)}, {"MODE_ID", INDEX(mode_id)}, {"OUT_FENCE_PTR", INDEX(out_fence_ptr)}, {"VRR_ENABLED", INDEX(vrr_enabled)}, + {"CTM", INDEX(ctm)}, #undef INDEX }; diff --git a/src/backend/drm/impl/Atomic.cpp b/src/backend/drm/impl/Atomic.cpp index 9803f21..5aa228f 100644 --- a/src/backend/drm/impl/Atomic.cpp +++ b/src/backend/drm/impl/Atomic.cpp @@ -100,6 +100,9 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint if (data.modeset && enable && connector->props.max_bpc && connector->maxBpcBounds.at(1)) add(connector->id, connector->props.max_bpc, 8); // FIXME: this isnt always 8 + if (data.ctm.has_value() && connector->crtc->props.ctm && data.atomic.ctmBlob && data.atomic.ctmd) + add(connector->crtc->id, connector->crtc->props.ctm, data.atomic.ctmBlob); + add(connector->crtc->id, connector->crtc->props.active, enable); if (enable) { @@ -197,6 +200,7 @@ void Aquamarine::CDRMAtomicRequest::rollback(SDRMConnectorCommitData& data) { if (data.atomic.blobbed) rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); rollbackBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut); + rollbackBlob(&conn->crtc->atomic.ctm, data.atomic.ctmBlob); destroyBlob(data.atomic.fbDamage); } @@ -211,6 +215,7 @@ void Aquamarine::CDRMAtomicRequest::apply(SDRMConnectorCommitData& data) { if (data.atomic.blobbed) commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); commitBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut); + commitBlob(&conn->crtc->atomic.ctm, data.atomic.ctmBlob); destroyBlob(data.atomic.fbDamage); } @@ -263,6 +268,24 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin } } + if ((STATE.committed & COutputState::AQ_OUTPUT_STATE_CTM) && data.ctm.has_value()) { + if (!connector->crtc->props.ctm) + connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to commit ctm: no ctm prop support"); + else { + drm_color_ctm ctm = {0}; + for (size_t i = 0; i < 9; ++i) { + const double val = data.ctm->getMatrix()[i]; + ctm.matrix[i] = static_cast(val * std::pow(2, 32)); + } + + if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, &ctm, sizeof(drm_color_ctm), &data.atomic.ctmBlob)) { + connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a ctm blob"); + data.atomic.ctmBlob = 0; + } else + data.atomic.ctmd = true; + } + } + if ((STATE.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE) && connector->crtc->primary->props.fb_damage_clips && MODE) { if (STATE.damage.empty()) data.atomic.fbDamage = 0; diff --git a/src/output/Output.cpp b/src/output/Output.cpp index 374764e..b5d3f3e 100644 --- a/src/output/Output.cpp +++ b/src/output/Output.cpp @@ -115,6 +115,11 @@ void Aquamarine::COutputState::resetExplicitFences() { internalState.explicitOutFence = -1; } +void Aquamarine::COutputState::setCTM(const Hyprutils::Math::Mat3x3& ctm) { + internalState.ctm = ctm; + internalState.committed |= AQ_OUTPUT_STATE_CTM; +} + void Aquamarine::COutputState::onCommit() { internalState.committed = 0; internalState.damage.clear();