DRM/Output: Implement CTM support (#92)

* flake.lock: update hyprutils

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
Vaxry 2024-10-07 19:40:37 +01:00 committed by GitHub
parent b82fdaff91
commit d352c0dd98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 57 additions and 6 deletions

View file

@ -29,7 +29,7 @@ pkg_check_modules(
libinput>=1.26.0
wayland-client
wayland-protocols
hyprutils>=0.1.5
hyprutils>=0.2.3
pixman-1
libdrm
gbm

View file

@ -10,11 +10,11 @@
]
},
"locked": {
"lastModified": 1724966483,
"narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=",
"lastModified": 1727300645,
"narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2",
"rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c",
"type": "github"
},
"original": {

View file

@ -7,6 +7,7 @@
#include <hyprutils/memory/WeakPtr.hpp>
#include <wayland-client.h>
#include <xf86drmMode.h>
#include <optional>
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<SDRMPlane> 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<Hyprutils::Math::Mat3x3> 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<SDRMConnector> connector);

View file

@ -5,6 +5,7 @@
#include <hyprutils/signal/Signal.hpp>
#include <hyprutils/memory/SharedPtr.hpp>
#include <hyprutils/math/Region.hpp>
#include <hyprutils/math/Mat3x3.hpp>
#include <drm_fourcc.h>
#include <xf86drmMode.h>
#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<IBuffer> 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;

View file

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

View file

@ -36,8 +36,10 @@ static const struct prop_info connector_info[] = {
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)},
{"ACTIVE", INDEX(active)}, {"CTM", INDEX(ctm)},
{"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)},
#undef INDEX
};

View file

@ -109,6 +109,9 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
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.ctm && data.atomic.ctmd)
add(connector->crtc->id, connector->crtc->props.ctm, data.atomic.ctmBlob);
if (connector->crtc->props.vrr_enabled)
add(connector->crtc->id, connector->crtc->props.vrr_enabled, (uint64_t)STATE.adaptiveSync);
@ -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,30 @@ 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 {
static auto doubleToS3132Fixed = [](const double val) -> uint64_t {
const uint64_t result = std::abs(val) * (1ULL << 32);
if (val < 0)
return result | 1ULL << 63;
return result;
};
drm_color_ctm ctm = {0};
for (size_t i = 0; i < 9; ++i) {
ctm.matrix[i] = doubleToS3132Fixed(data.ctm->getMatrix()[i]);
}
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;

View file

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