Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRM: Implement CTM #92

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
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
@@ -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);
4 changes: 4 additions & 0 deletions include/aquamarine/output/Output.hpp
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions src/backend/drm/DRM.cpp
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 4 additions & 2 deletions src/backend/drm/Props.cpp
Original file line number Diff line number Diff line change
@@ -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
};

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