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
Show file tree
Hide file tree
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
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
Loading