Skip to content

Commit

Permalink
DRM/Output: Implement CTM support (#92)
Browse files Browse the repository at this point in the history
* flake.lock: update hyprutils

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
  • Loading branch information
vaxerski and fufexan authored Oct 7, 2024
1 parent b82fdaf commit d352c0d
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 6 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions include/aquamarine/backend/DRM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <hyprutils/memory/WeakPtr.hpp>
#include <wayland-client.h>
#include <xf86drmMode.h>
#include <optional>

namespace Aquamarine {
class CDRMBackend;
Expand Down Expand Up @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions include/aquamarine/output/Output.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/backend/drm/DRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/backend/drm/Props.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down
29 changes: 29 additions & 0 deletions src/backend/drm/impl/Atomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/output/Output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit d352c0d

Please sign in to comment.