mirror of
https://github.com/hyprwm/aquamarine.git
synced 2024-11-17 02:35:59 +01:00
DRM/Output: Implement CTM support (#92)
* flake.lock: update hyprutils --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
b82fdaff91
commit
d352c0dd98
8 changed files with 57 additions and 6 deletions
|
@ -29,7 +29,7 @@ pkg_check_modules(
|
||||||
libinput>=1.26.0
|
libinput>=1.26.0
|
||||||
wayland-client
|
wayland-client
|
||||||
wayland-protocols
|
wayland-protocols
|
||||||
hyprutils>=0.1.5
|
hyprutils>=0.2.3
|
||||||
pixman-1
|
pixman-1
|
||||||
libdrm
|
libdrm
|
||||||
gbm
|
gbm
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1724966483,
|
"lastModified": 1727300645,
|
||||||
"narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=",
|
"narHash": "sha256-OvAtVLaSRPnbXzOwlR1fVqCXR7i+ICRX3aPMCdIiv+c=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprutils",
|
"repo": "hyprutils",
|
||||||
"rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2",
|
"rev": "3f5293432b6dc6a99f26aca2eba3876d2660665c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <hyprutils/memory/WeakPtr.hpp>
|
#include <hyprutils/memory/WeakPtr.hpp>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace Aquamarine {
|
namespace Aquamarine {
|
||||||
class CDRMBackend;
|
class CDRMBackend;
|
||||||
|
@ -162,6 +163,7 @@ namespace Aquamarine {
|
||||||
bool ownModeID = false;
|
bool ownModeID = false;
|
||||||
uint32_t modeID = 0;
|
uint32_t modeID = 0;
|
||||||
uint32_t gammaLut = 0;
|
uint32_t gammaLut = 0;
|
||||||
|
uint32_t ctm = 0;
|
||||||
} atomic;
|
} atomic;
|
||||||
|
|
||||||
Hyprutils::Memory::CSharedPointer<SDRMPlane> primary;
|
Hyprutils::Memory::CSharedPointer<SDRMPlane> primary;
|
||||||
|
@ -175,6 +177,7 @@ namespace Aquamarine {
|
||||||
uint32_t vrr_enabled;
|
uint32_t vrr_enabled;
|
||||||
uint32_t gamma_lut;
|
uint32_t gamma_lut;
|
||||||
uint32_t gamma_lut_size;
|
uint32_t gamma_lut_size;
|
||||||
|
uint32_t ctm;
|
||||||
|
|
||||||
// atomic-modesetting only
|
// atomic-modesetting only
|
||||||
|
|
||||||
|
@ -242,13 +245,16 @@ namespace Aquamarine {
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
bool test = false;
|
bool test = false;
|
||||||
drmModeModeInfo modeInfo;
|
drmModeModeInfo modeInfo;
|
||||||
|
std::optional<Hyprutils::Math::Mat3x3> ctm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t gammaLut = 0;
|
uint32_t gammaLut = 0;
|
||||||
uint32_t fbDamage = 0;
|
uint32_t fbDamage = 0;
|
||||||
uint32_t modeBlob = 0;
|
uint32_t modeBlob = 0;
|
||||||
|
uint32_t ctmBlob = 0;
|
||||||
bool blobbed = false;
|
bool blobbed = false;
|
||||||
bool gammad = false;
|
bool gammad = false;
|
||||||
|
bool ctmd = false;
|
||||||
} atomic;
|
} atomic;
|
||||||
|
|
||||||
void calculateMode(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
|
void calculateMode(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <hyprutils/signal/Signal.hpp>
|
#include <hyprutils/signal/Signal.hpp>
|
||||||
#include <hyprutils/memory/SharedPtr.hpp>
|
#include <hyprutils/memory/SharedPtr.hpp>
|
||||||
#include <hyprutils/math/Region.hpp>
|
#include <hyprutils/math/Region.hpp>
|
||||||
|
#include <hyprutils/math/Mat3x3.hpp>
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include "../allocator/Swapchain.hpp"
|
#include "../allocator/Swapchain.hpp"
|
||||||
|
@ -51,6 +52,7 @@ namespace Aquamarine {
|
||||||
AQ_OUTPUT_STATE_BUFFER = (1 << 7),
|
AQ_OUTPUT_STATE_BUFFER = (1 << 7),
|
||||||
AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE = (1 << 8),
|
AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE = (1 << 8),
|
||||||
AQ_OUTPUT_STATE_EXPLICIT_OUT_FENCE = (1 << 9),
|
AQ_OUTPUT_STATE_EXPLICIT_OUT_FENCE = (1 << 9),
|
||||||
|
AQ_OUTPUT_STATE_CTM = (1 << 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SInternalState {
|
struct SInternalState {
|
||||||
|
@ -67,6 +69,7 @@ namespace Aquamarine {
|
||||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||||
Hyprutils::Memory::CSharedPointer<IBuffer> buffer;
|
Hyprutils::Memory::CSharedPointer<IBuffer> buffer;
|
||||||
int64_t explicitInFence = -1, explicitOutFence = -1;
|
int64_t explicitInFence = -1, explicitOutFence = -1;
|
||||||
|
Hyprutils::Math::Mat3x3 ctm;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SInternalState& state();
|
const SInternalState& state();
|
||||||
|
@ -84,6 +87,7 @@ namespace Aquamarine {
|
||||||
void setExplicitInFence(int64_t fenceFD); // -1 removes
|
void setExplicitInFence(int64_t fenceFD); // -1 removes
|
||||||
void setExplicitOutFence(int64_t fenceFD); // -1 removes
|
void setExplicitOutFence(int64_t fenceFD); // -1 removes
|
||||||
void resetExplicitFences();
|
void resetExplicitFences();
|
||||||
|
void setCTM(const Hyprutils::Math::Mat3x3& ctm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SInternalState internalState;
|
SInternalState internalState;
|
||||||
|
|
|
@ -1183,6 +1183,8 @@ void Aquamarine::SDRMConnector::recheckCRTCProps() {
|
||||||
output->supportsExplicit = backend->drmProps.supportsTimelines && crtc->props.out_fence_ptr && crtc->primary->props.in_fence_fd;
|
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: 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) {
|
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.blocking = BLOCKING || formatMismatch;
|
||||||
data.modeset = NEEDS_RECONFIG || lastCommitNoBuffer || formatMismatch;
|
data.modeset = NEEDS_RECONFIG || lastCommitNoBuffer || formatMismatch;
|
||||||
data.flags = flags;
|
data.flags = flags;
|
||||||
|
|
|
@ -36,8 +36,10 @@ static const struct prop_info connector_info[] = {
|
||||||
|
|
||||||
static const struct prop_info crtc_info[] = {
|
static const struct prop_info crtc_info[] = {
|
||||||
#define INDEX(name) (offsetof(SDRMCRTC::UDRMCRTCProps, name) / sizeof(uint32_t))
|
#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)},
|
{"ACTIVE", INDEX(active)}, {"CTM", INDEX(ctm)},
|
||||||
{"MODE_ID", INDEX(mode_id)}, {"OUT_FENCE_PTR", INDEX(out_fence_ptr)}, {"VRR_ENABLED", INDEX(vrr_enabled)},
|
{"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
|
#undef INDEX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,9 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
|
||||||
if (connector->crtc->props.gamma_lut && data.atomic.gammad)
|
if (connector->crtc->props.gamma_lut && data.atomic.gammad)
|
||||||
add(connector->crtc->id, connector->crtc->props.gamma_lut, data.atomic.gammaLut);
|
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)
|
if (connector->crtc->props.vrr_enabled)
|
||||||
add(connector->crtc->id, connector->crtc->props.vrr_enabled, (uint64_t)STATE.adaptiveSync);
|
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)
|
if (data.atomic.blobbed)
|
||||||
rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
|
rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
|
||||||
rollbackBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut);
|
rollbackBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut);
|
||||||
|
rollbackBlob(&conn->crtc->atomic.ctm, data.atomic.ctmBlob);
|
||||||
destroyBlob(data.atomic.fbDamage);
|
destroyBlob(data.atomic.fbDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +215,7 @@ void Aquamarine::CDRMAtomicRequest::apply(SDRMConnectorCommitData& data) {
|
||||||
if (data.atomic.blobbed)
|
if (data.atomic.blobbed)
|
||||||
commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
|
commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
|
||||||
commitBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut);
|
commitBlob(&conn->crtc->atomic.gammaLut, data.atomic.gammaLut);
|
||||||
|
commitBlob(&conn->crtc->atomic.ctm, data.atomic.ctmBlob);
|
||||||
destroyBlob(data.atomic.fbDamage);
|
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.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE) && connector->crtc->primary->props.fb_damage_clips && MODE) {
|
||||||
if (STATE.damage.empty())
|
if (STATE.damage.empty())
|
||||||
data.atomic.fbDamage = 0;
|
data.atomic.fbDamage = 0;
|
||||||
|
|
|
@ -115,6 +115,11 @@ void Aquamarine::COutputState::resetExplicitFences() {
|
||||||
internalState.explicitOutFence = -1;
|
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() {
|
void Aquamarine::COutputState::onCommit() {
|
||||||
internalState.committed = 0;
|
internalState.committed = 0;
|
||||||
internalState.damage.clear();
|
internalState.damage.clear();
|
||||||
|
|
Loading…
Reference in a new issue