mirror of
https://github.com/hyprwm/aquamarine.git
synced 2025-01-26 06:49:48 +01:00
core/drm: Add HDR Support (#112)
This commit is contained in:
parent
f7082bef81
commit
aeab812e0f
7 changed files with 272 additions and 34 deletions
|
@ -179,6 +179,8 @@ namespace Aquamarine {
|
|||
uint32_t gamma_lut;
|
||||
uint32_t gamma_lut_size;
|
||||
uint32_t ctm;
|
||||
uint32_t degamma_lut;
|
||||
uint32_t degamma_lut_size;
|
||||
|
||||
// atomic-modesetting only
|
||||
|
||||
|
@ -186,7 +188,7 @@ namespace Aquamarine {
|
|||
uint32_t mode_id;
|
||||
uint32_t out_fence_ptr;
|
||||
};
|
||||
uint32_t props[7] = {0};
|
||||
uint32_t props[9] = {0};
|
||||
};
|
||||
UDRMCRTCProps props;
|
||||
};
|
||||
|
@ -203,6 +205,7 @@ namespace Aquamarine {
|
|||
virtual void setCursorVisible(bool visible);
|
||||
virtual Hyprutils::Math::Vector2D cursorPlaneSize();
|
||||
virtual size_t getGammaSize();
|
||||
virtual size_t getDeGammaSize();
|
||||
virtual std::vector<SDRMFormat> getRenderFormats();
|
||||
|
||||
int getConnectorID();
|
||||
|
@ -247,15 +250,20 @@ namespace Aquamarine {
|
|||
bool test = false;
|
||||
drmModeModeInfo modeInfo;
|
||||
std::optional<Hyprutils::Math::Mat3x3> ctm;
|
||||
std::optional<hdr_output_metadata> hdrMetadata;
|
||||
|
||||
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;
|
||||
uint32_t gammaLut = 0;
|
||||
uint32_t degammaLut = 0;
|
||||
uint32_t fbDamage = 0;
|
||||
uint32_t modeBlob = 0;
|
||||
uint32_t ctmBlob = 0;
|
||||
uint32_t hdrBlob = 0;
|
||||
bool blobbed = false;
|
||||
bool gammad = false;
|
||||
bool degammad = false;
|
||||
bool ctmd = false;
|
||||
bool hdrd = false;
|
||||
} atomic;
|
||||
|
||||
void calculateMode(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
|
||||
|
@ -269,7 +277,7 @@ namespace Aquamarine {
|
|||
void disconnect();
|
||||
Hyprutils::Memory::CSharedPointer<SDRMCRTC> getCurrentCRTC(const drmModeConnector* connector);
|
||||
drmModeModeInfo* getCurrentMode();
|
||||
void parseEDID(std::vector<uint8_t> data);
|
||||
IOutput::SParsedEDID parseEDID(std::vector<uint8_t> data);
|
||||
bool commitState(SDRMConnectorCommitData& data);
|
||||
void applyCommit(const SDRMConnectorCommitData& data);
|
||||
void rollbackCommit(const SDRMConnectorCommitData& data);
|
||||
|
@ -315,17 +323,29 @@ namespace Aquamarine {
|
|||
uint32_t vrr_capable; // not guaranteed to exist
|
||||
uint32_t subconnector; // not guaranteed to exist
|
||||
uint32_t non_desktop;
|
||||
uint32_t panel_orientation; // not guaranteed to exist
|
||||
uint32_t content_type; // not guaranteed to exist
|
||||
uint32_t max_bpc; // not guaranteed to exist
|
||||
uint32_t panel_orientation; // not guaranteed to exist
|
||||
uint32_t content_type; // not guaranteed to exist
|
||||
uint32_t max_bpc; // not guaranteed to exist
|
||||
uint32_t Colorspace; // not guaranteed to exist
|
||||
uint32_t hdr_output_metadata; // not guaranteed to exist
|
||||
|
||||
// atomic-modesetting only
|
||||
|
||||
uint32_t crtc_id;
|
||||
};
|
||||
uint32_t props[4] = {0};
|
||||
uint32_t props[13] = {0};
|
||||
};
|
||||
UDRMConnectorProps props;
|
||||
|
||||
union UDRMConnectorColorspace {
|
||||
struct {
|
||||
uint32_t Default;
|
||||
uint32_t BT2020_RGB;
|
||||
uint32_t BT2020_YCC;
|
||||
};
|
||||
uint32_t props[3] = {0};
|
||||
};
|
||||
UDRMConnectorColorspace colorspace;
|
||||
};
|
||||
|
||||
class IDRMImplementation {
|
||||
|
|
|
@ -53,6 +53,8 @@ namespace Aquamarine {
|
|||
AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE = (1 << 8),
|
||||
AQ_OUTPUT_STATE_EXPLICIT_OUT_FENCE = (1 << 9),
|
||||
AQ_OUTPUT_STATE_CTM = (1 << 10),
|
||||
AQ_OUTPUT_STATE_HDR = (1 << 11),
|
||||
AQ_OUTPUT_STATE_DEGAMMA_LUT = (1 << 12),
|
||||
};
|
||||
|
||||
struct SInternalState {
|
||||
|
@ -62,7 +64,8 @@ namespace Aquamarine {
|
|||
bool enabled = false;
|
||||
bool adaptiveSync = false;
|
||||
eOutputPresentationMode presentationMode = AQ_OUTPUT_PRESENTATION_VSYNC;
|
||||
std::vector<uint16_t> gammaLut; // Gamma lut in the format [r,g,b]+
|
||||
std::vector<uint16_t> gammaLut; // Gamma lut in the format [r,g,b]+
|
||||
std::vector<uint16_t> degammaLut; // Gamma lut in the format [r,g,b]+
|
||||
Hyprutils::Math::Vector2D lastModeSize;
|
||||
Hyprutils::Memory::CWeakPointer<SOutputMode> mode;
|
||||
Hyprutils::Memory::CSharedPointer<SOutputMode> customMode;
|
||||
|
@ -70,6 +73,8 @@ namespace Aquamarine {
|
|||
Hyprutils::Memory::CSharedPointer<IBuffer> buffer;
|
||||
int32_t explicitInFence = -1, explicitOutFence = -1;
|
||||
Hyprutils::Math::Mat3x3 ctm;
|
||||
bool wideColorGamut = false;
|
||||
hdr_output_metadata hdrMetadata;
|
||||
};
|
||||
|
||||
const SInternalState& state();
|
||||
|
@ -80,6 +85,7 @@ namespace Aquamarine {
|
|||
void setAdaptiveSync(bool enabled);
|
||||
void setPresentationMode(eOutputPresentationMode mode);
|
||||
void setGammaLut(const std::vector<uint16_t>& lut);
|
||||
void setDeGammaLut(const std::vector<uint16_t>& lut);
|
||||
void setMode(Hyprutils::Memory::CSharedPointer<SOutputMode> mode);
|
||||
void setCustomMode(Hyprutils::Memory::CSharedPointer<SOutputMode> mode);
|
||||
void setFormat(uint32_t drmFormat);
|
||||
|
@ -88,6 +94,8 @@ namespace Aquamarine {
|
|||
void enableExplicitOutFenceForNextCommit();
|
||||
void resetExplicitFences();
|
||||
void setCTM(const Hyprutils::Math::Mat3x3& ctm);
|
||||
void setWideColorGamut(bool wcg);
|
||||
void setHDRMetadata(const hdr_output_metadata& metadata);
|
||||
|
||||
private:
|
||||
SInternalState internalState;
|
||||
|
@ -119,6 +127,32 @@ namespace Aquamarine {
|
|||
AQ_SCHEDULE_ANIMATION_DAMAGE,
|
||||
};
|
||||
|
||||
struct SHDRMetadata {
|
||||
float desiredContentMaxLuminance = 0;
|
||||
float desiredMaxFrameAverageLuminance = 0;
|
||||
float desiredContentMinLuminance = 0;
|
||||
bool supportsPQ = false;
|
||||
};
|
||||
|
||||
struct xy {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
};
|
||||
|
||||
struct SChromaticityCoords {
|
||||
xy red;
|
||||
xy green;
|
||||
xy blue;
|
||||
xy white;
|
||||
};
|
||||
|
||||
struct SParsedEDID {
|
||||
std::string make, serial, model;
|
||||
std::optional<SHDRMetadata> hdrMetadata;
|
||||
std::optional<SChromaticityCoords> chromaticityCoords;
|
||||
bool supportsBT2020 = false;
|
||||
};
|
||||
|
||||
virtual bool commit() = 0;
|
||||
virtual bool test() = 0;
|
||||
virtual Hyprutils::Memory::CSharedPointer<IBackendImplementation> getBackend() = 0;
|
||||
|
@ -130,9 +164,11 @@ namespace Aquamarine {
|
|||
virtual Hyprutils::Math::Vector2D cursorPlaneSize(); // -1, -1 means no set size, 0, 0 means error
|
||||
virtual void scheduleFrame(const scheduleFrameReason reason = AQ_SCHEDULE_UNKNOWN);
|
||||
virtual size_t getGammaSize();
|
||||
virtual size_t getDeGammaSize();
|
||||
virtual bool destroy(); // not all backends allow this!!!
|
||||
|
||||
std::string name, description, make, model, serial;
|
||||
SParsedEDID parsedEDID;
|
||||
Hyprutils::Math::Vector2D physicalSize;
|
||||
bool enabled = false;
|
||||
bool nonDesktop = false;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <aquamarine/backend/drm/Atomic.hpp>
|
||||
#include <aquamarine/allocator/GBM.hpp>
|
||||
#include <aquamarine/allocator/DRMDumb.hpp>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <hyprutils/string/VarList.hpp>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
@ -19,6 +21,7 @@ extern "C" {
|
|||
#include <libudev.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <libdisplay-info/cta.h>
|
||||
#include <libdisplay-info/cvt.h>
|
||||
#include <libdisplay-info/info.h>
|
||||
#include <libdisplay-info/edid.h>
|
||||
|
@ -1101,6 +1104,8 @@ bool Aquamarine::SDRMConnector::init(drmModeConnector* connector) {
|
|||
|
||||
if (!getDRMConnectorProps(backend->gpu->fd, id, &props))
|
||||
return false;
|
||||
if (props.Colorspace)
|
||||
getDRMConnectorColorspace(backend->gpu->fd, props.Colorspace, &colorspace);
|
||||
|
||||
auto name = drmModeGetConnectorTypeName(connector->connector_type);
|
||||
if (!name)
|
||||
|
@ -1166,11 +1171,12 @@ drmModeModeInfo* Aquamarine::SDRMConnector::getCurrentMode() {
|
|||
return modeInfo;
|
||||
}
|
||||
|
||||
void Aquamarine::SDRMConnector::parseEDID(std::vector<uint8_t> data) {
|
||||
auto info = di_info_parse_edid(data.data(), data.size());
|
||||
IOutput::SParsedEDID Aquamarine::SDRMConnector::parseEDID(std::vector<uint8_t> data) {
|
||||
auto info = di_info_parse_edid(data.data(), data.size());
|
||||
IOutput::SParsedEDID parsed = {};
|
||||
if (!info) {
|
||||
backend->backend->log(AQ_LOG_ERROR, "drm: failed to parse edid");
|
||||
return;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
auto edid = di_info_get_edid(info);
|
||||
|
@ -1187,7 +1193,64 @@ void Aquamarine::SDRMConnector::parseEDID(std::vector<uint8_t> data) {
|
|||
model = mod ? mod : "";
|
||||
serial = ser ? ser : "";
|
||||
|
||||
parsed.make = make;
|
||||
parsed.model = model;
|
||||
parsed.serial = serial;
|
||||
|
||||
const auto chromaticity = di_edid_get_chromaticity_coords(edid);
|
||||
if (chromaticity) {
|
||||
parsed.chromaticityCoords = IOutput::SChromaticityCoords{
|
||||
IOutput::xy{chromaticity->red_x, chromaticity->red_y},
|
||||
IOutput::xy{chromaticity->green_x, chromaticity->green_y},
|
||||
IOutput::xy{chromaticity->blue_x, chromaticity->blue_y},
|
||||
IOutput::xy{chromaticity->white_x, chromaticity->white_y},
|
||||
};
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE,
|
||||
std::format("EDID: chromaticity coords {},{} {},{} {},{} {},{}", parsed.chromaticityCoords->red.x, parsed.chromaticityCoords->red.y,
|
||||
parsed.chromaticityCoords->green.x, parsed.chromaticityCoords->green.y, parsed.chromaticityCoords->blue.x,
|
||||
parsed.chromaticityCoords->blue.y, parsed.chromaticityCoords->white.y, parsed.chromaticityCoords->white.y)));
|
||||
}
|
||||
|
||||
auto exts = di_edid_get_extensions(edid);
|
||||
|
||||
for (; *exts != nullptr; exts++) {
|
||||
auto tag = di_edid_ext_get_tag(*exts);
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("EDID: checking ext {}", (uint32_t)tag)));
|
||||
if (tag == DI_EDID_EXT_DISPLAYID)
|
||||
backend->backend->log(AQ_LOG_WARNING, "FIXME: support displayid blocks");
|
||||
|
||||
const auto cta = di_edid_ext_get_cta(*exts);
|
||||
if (cta) {
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE, "EDID: found CTA"));
|
||||
const di_cta_hdr_static_metadata_block* hdr_static_metadata = nullptr;
|
||||
const di_cta_colorimetry_block* colorimetry = nullptr;
|
||||
auto blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (; *blocks != nullptr; blocks++) {
|
||||
if (!hdr_static_metadata && (hdr_static_metadata = di_cta_data_block_get_hdr_static_metadata(*blocks))) {
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("EDID: found HDR {}", hdr_static_metadata->eotfs->pq)));
|
||||
parsed.hdrMetadata = IOutput::SHDRMetadata{
|
||||
.desiredContentMaxLuminance = hdr_static_metadata->desired_content_max_luminance,
|
||||
.desiredMaxFrameAverageLuminance = hdr_static_metadata->desired_content_max_frame_avg_luminance,
|
||||
.desiredContentMinLuminance = hdr_static_metadata->desired_content_min_luminance,
|
||||
.supportsPQ = hdr_static_metadata->eotfs->pq,
|
||||
};
|
||||
continue;
|
||||
}
|
||||
if (!colorimetry && (colorimetry = di_cta_data_block_get_colorimetry(*blocks))) {
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE, std::format("EDID: found colorimetry {}", colorimetry->bt2020_rgb)));
|
||||
parsed.supportsBT2020 = colorimetry->bt2020_rgb;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
di_info_destroy(info);
|
||||
|
||||
TRACE(backend->backend->log(AQ_LOG_TRACE, "EDID: parsed"));
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
void Aquamarine::SDRMConnector::recheckCRTCProps() {
|
||||
|
@ -1207,6 +1270,11 @@ void Aquamarine::SDRMConnector::recheckCRTCProps() {
|
|||
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")));
|
||||
|
||||
backend->backend->log(AQ_LOG_DEBUG,
|
||||
std::format("drm: connector {} crtc {} HDR ({})", szName, (props.hdr_output_metadata ? "supports" : "doesn't support"), props.hdr_output_metadata));
|
||||
|
||||
backend->backend->log(AQ_LOG_DEBUG, std::format("drm: connector {} crtc {} Colorspace ({})", szName, (props.Colorspace ? "supports" : "doesn't support"), props.Colorspace));
|
||||
}
|
||||
|
||||
void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) {
|
||||
|
@ -1289,16 +1357,17 @@ void Aquamarine::SDRMConnector::connect(drmModeConnector* connector) {
|
|||
uint8_t* edidData = (uint8_t*)getDRMPropBlob(backend->gpu->fd, id, props.edid, &edidLen);
|
||||
|
||||
std::vector<uint8_t> edid{edidData, edidData + edidLen};
|
||||
parseEDID(edid);
|
||||
auto parsedEDID = parseEDID(edid);
|
||||
|
||||
free(edidData);
|
||||
edid = {};
|
||||
|
||||
// TODO: subconnectors
|
||||
|
||||
output->make = make;
|
||||
output->model = model;
|
||||
output->serial = serial;
|
||||
output->make = parsedEDID.make;
|
||||
output->model = parsedEDID.model;
|
||||
output->serial = parsedEDID.serial;
|
||||
output->parsedEDID = parsedEDID;
|
||||
output->description = std::format("{} {} {} ({})", make, model, serial, szName);
|
||||
output->needsFrame = true;
|
||||
|
||||
|
@ -1609,6 +1678,9 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) {
|
|||
if (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_CTM)
|
||||
data.ctm = STATE.ctm;
|
||||
|
||||
if (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_HDR)
|
||||
data.hdrMetadata = STATE.hdrMetadata;
|
||||
|
||||
data.blocking = BLOCKING || formatMismatch;
|
||||
data.modeset = NEEDS_RECONFIG || lastCommitNoBuffer || formatMismatch;
|
||||
data.flags = flags;
|
||||
|
@ -1787,6 +1859,21 @@ size_t Aquamarine::CDRMOutput::getGammaSize() {
|
|||
return size;
|
||||
}
|
||||
|
||||
size_t Aquamarine::CDRMOutput::getDeGammaSize() {
|
||||
if (!backend->atomic) {
|
||||
backend->log(AQ_LOG_ERROR, "No support for gamma on the legacy iface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t size = 0;
|
||||
if (!getDRMProp(backend->gpu->fd, connector->crtc->id, connector->crtc->props.degamma_lut_size, &size)) {
|
||||
backend->log(AQ_LOG_ERROR, "Couldn't get the degamma_size prop");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
std::vector<SDRMFormat> Aquamarine::CDRMOutput::getRenderFormats() {
|
||||
if (!connector->crtc || !connector->crtc->primary || connector->crtc->primary->formats.empty()) {
|
||||
backend->log(AQ_LOG_ERROR, "Can't get formats: no crtc");
|
||||
|
|
|
@ -21,8 +21,10 @@ struct prop_info {
|
|||
static const struct prop_info connector_info[] = {
|
||||
#define INDEX(name) (offsetof(SDRMConnector::UDRMConnectorProps, name) / sizeof(uint32_t))
|
||||
{"CRTC_ID", INDEX(crtc_id)},
|
||||
{"Colorspace", INDEX(Colorspace)},
|
||||
{"DPMS", INDEX(dpms)},
|
||||
{"EDID", INDEX(edid)},
|
||||
{"HDR_OUTPUT_METADATA", INDEX(hdr_output_metadata)},
|
||||
{"PATH", INDEX(path)},
|
||||
{"content type", INDEX(content_type)},
|
||||
{"link-status", INDEX(link_status)},
|
||||
|
@ -34,9 +36,18 @@ static const struct prop_info connector_info[] = {
|
|||
#undef INDEX
|
||||
};
|
||||
|
||||
static const struct prop_info colorspace_info[] = {
|
||||
#define INDEX(name) (offsetof(SDRMConnector::UDRMConnectorColorspace, name) / sizeof(uint32_t))
|
||||
{"BT2020_RGB", INDEX(BT2020_RGB)},
|
||||
{"BT2020_YCC", INDEX(BT2020_YCC)},
|
||||
{"Default", INDEX(Default)},
|
||||
#undef INDEX
|
||||
};
|
||||
|
||||
static const struct prop_info crtc_info[] = {
|
||||
#define INDEX(name) (offsetof(SDRMCRTC::UDRMCRTCProps, name) / sizeof(uint32_t))
|
||||
{"ACTIVE", INDEX(active)}, {"CTM", INDEX(ctm)},
|
||||
{"DEGAMMA_LUT", INDEX(degamma_lut)}, {"DEGAMMA_LUT_SIZE", INDEX(degamma_lut_size)},
|
||||
{"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)},
|
||||
|
@ -95,10 +106,30 @@ namespace Aquamarine {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool scanPropertyEnum(int fd, uint32_t propertyId, uint32_t* result, const prop_info* info, size_t info_len) {
|
||||
drmModePropertyRes* prop = drmModeGetProperty(fd, propertyId);
|
||||
if (!prop)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < prop->count_enums; ++i) {
|
||||
const prop_info* p = (prop_info*)bsearch(prop->enums[i].name, info, info_len, sizeof(info[0]), comparePropInfo);
|
||||
if (p)
|
||||
result[p->index] = prop->enums[i].value;
|
||||
}
|
||||
|
||||
drmModeFreeProperty(prop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getDRMConnectorProps(int fd, uint32_t id, SDRMConnector::UDRMConnectorProps* out) {
|
||||
return scanProperties(fd, id, DRM_MODE_OBJECT_CONNECTOR, out->props, connector_info, sizeof(connector_info) / sizeof(connector_info[0]));
|
||||
}
|
||||
|
||||
bool getDRMConnectorColorspace(int fd, uint32_t id, SDRMConnector::UDRMConnectorColorspace* out) {
|
||||
return scanPropertyEnum(fd, id, out->props, colorspace_info, sizeof(colorspace_info) / sizeof(colorspace_info[0]));
|
||||
}
|
||||
|
||||
bool getDRMCRTCProps(int fd, uint32_t id, SDRMCRTC::UDRMCRTCProps* out) {
|
||||
return scanProperties(fd, id, DRM_MODE_OBJECT_CRTC, out->props, crtc_info, sizeof(crtc_info) / sizeof(crtc_info[0]));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace Aquamarine {
|
||||
bool getDRMConnectorProps(int fd, uint32_t id, SDRMConnector::UDRMConnectorProps* out);
|
||||
bool getDRMConnectorColorspace(int fd, uint32_t id, SDRMConnector::UDRMConnectorColorspace* out);
|
||||
bool getDRMCRTCProps(int fd, uint32_t id, SDRMCRTC::UDRMCRTCProps* out);
|
||||
bool getDRMPlaneProps(int fd, uint32_t id, SDRMPlane::UDRMPlaneProps* out);
|
||||
bool getDRMProp(int fd, uint32_t obj, uint32_t prop, uint64_t* ret);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include <aquamarine/backend/drm/Atomic.hpp>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <drm_mode.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -103,12 +105,21 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
|
|||
add(connector->crtc->id, connector->crtc->props.active, enable);
|
||||
|
||||
if (enable) {
|
||||
if (connector->props.Colorspace && connector->colorspace.BT2020_RGB)
|
||||
add(connector->id, connector->props.Colorspace, STATE.wideColorGamut ? connector->colorspace.BT2020_RGB : connector->colorspace.Default);
|
||||
|
||||
if (connector->props.hdr_output_metadata)
|
||||
add(connector->id, connector->props.hdr_output_metadata, data.atomic.hdrd ? data.atomic.hdrBlob : 0);
|
||||
|
||||
if (connector->output->supportsExplicit && STATE.committed & COutputState::AQ_OUTPUT_STATE_EXPLICIT_OUT_FENCE)
|
||||
add(connector->crtc->id, connector->crtc->props.out_fence_ptr, (uintptr_t)&STATE.explicitOutFence);
|
||||
|
||||
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.degamma_lut && data.atomic.degammad)
|
||||
add(connector->crtc->id, connector->crtc->props.degamma_lut, data.atomic.degammaLut);
|
||||
|
||||
if (connector->crtc->props.ctm && data.atomic.ctmd)
|
||||
add(connector->crtc->id, connector->crtc->props.ctm, data.atomic.ctmBlob);
|
||||
|
||||
|
@ -246,30 +257,38 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin
|
|||
}
|
||||
}
|
||||
|
||||
if (STATE.committed & COutputState::AQ_OUTPUT_STATE_GAMMA_LUT) {
|
||||
if (!connector->crtc->props.gamma_lut) // TODO: allow this with legacy gamma, perhaps.
|
||||
auto prepareGammaBlob = [connector](uint32_t prop, const std::vector<uint16_t>& gammaLut, uint32_t* blobId) -> bool {
|
||||
if (!prop) // TODO: allow this with legacy gamma, perhaps.
|
||||
connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to commit gamma: no gamma_lut prop");
|
||||
else if (STATE.gammaLut.empty()) {
|
||||
data.atomic.gammaLut = 0;
|
||||
data.atomic.gammad = true;
|
||||
else if (gammaLut.empty()) {
|
||||
blobId = 0;
|
||||
return true;
|
||||
} else {
|
||||
std::vector<drm_color_lut> lut;
|
||||
lut.resize(STATE.gammaLut.size() / 3); // [r,g,b]+
|
||||
lut.resize(gammaLut.size() / 3); // [r,g,b]+
|
||||
|
||||
for (size_t i = 0; i < lut.size(); ++i) {
|
||||
lut.at(i).red = STATE.gammaLut.at(i * 3 + 0);
|
||||
lut.at(i).green = STATE.gammaLut.at(i * 3 + 1);
|
||||
lut.at(i).blue = STATE.gammaLut.at(i * 3 + 2);
|
||||
lut.at(i).red = gammaLut.at(i * 3 + 0);
|
||||
lut.at(i).green = gammaLut.at(i * 3 + 1);
|
||||
lut.at(i).blue = gammaLut.at(i * 3 + 2);
|
||||
lut.at(i).reserved = 0;
|
||||
}
|
||||
|
||||
if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, lut.data(), lut.size() * sizeof(drm_color_lut), &data.atomic.gammaLut)) {
|
||||
if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, lut.data(), lut.size() * sizeof(drm_color_lut), blobId)) {
|
||||
connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a gamma blob");
|
||||
data.atomic.gammaLut = 0;
|
||||
*blobId = 0;
|
||||
} else
|
||||
data.atomic.gammad = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (STATE.committed & COutputState::AQ_OUTPUT_STATE_GAMMA_LUT)
|
||||
data.atomic.gammad = prepareGammaBlob(connector->crtc->props.gamma_lut, STATE.gammaLut, &data.atomic.gammaLut);
|
||||
|
||||
if (STATE.committed & COutputState::AQ_OUTPUT_STATE_DEGAMMA_LUT)
|
||||
data.atomic.degammad = prepareGammaBlob(connector->crtc->props.degamma_lut, STATE.degammaLut, &data.atomic.degammaLut);
|
||||
|
||||
if ((STATE.committed & COutputState::AQ_OUTPUT_STATE_CTM) && data.ctm.has_value()) {
|
||||
if (!connector->crtc->props.ctm)
|
||||
|
@ -295,6 +314,32 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin
|
|||
}
|
||||
}
|
||||
|
||||
if ((STATE.committed & COutputState::AQ_OUTPUT_STATE_HDR) && data.hdrMetadata.has_value()) {
|
||||
if (!connector->props.hdr_output_metadata)
|
||||
connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to commit hdr metadata: no HDR_OUTPUT_METADATA prop support");
|
||||
else {
|
||||
if (!data.hdrMetadata->hdmi_metadata_type1.eotf) {
|
||||
data.atomic.hdrBlob = 0;
|
||||
data.atomic.hdrd = false;
|
||||
} else if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, &data.hdrMetadata.value(), sizeof(hdr_output_metadata), &data.atomic.hdrBlob)) {
|
||||
connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a hdr metadata blob");
|
||||
data.atomic.hdrBlob = 0;
|
||||
} else {
|
||||
data.atomic.hdrd = true;
|
||||
TRACE(connector->backend->backend->log(
|
||||
AQ_LOG_TRACE,
|
||||
std::format("atomic drm: setting hdr min {}, max {}, avg {}, content {}, primaries {},{} {},{} {},{} {},{}",
|
||||
data.hdrMetadata->hdmi_metadata_type1.min_display_mastering_luminance, data.hdrMetadata->hdmi_metadata_type1.max_display_mastering_luminance,
|
||||
data.hdrMetadata->hdmi_metadata_type1.max_fall, data.hdrMetadata->hdmi_metadata_type1.max_cll,
|
||||
data.hdrMetadata->hdmi_metadata_type1.display_primaries[0].x, data.hdrMetadata->hdmi_metadata_type1.display_primaries[0].y,
|
||||
data.hdrMetadata->hdmi_metadata_type1.display_primaries[1].x, data.hdrMetadata->hdmi_metadata_type1.display_primaries[1].y,
|
||||
data.hdrMetadata->hdmi_metadata_type1.display_primaries[2].x, data.hdrMetadata->hdmi_metadata_type1.display_primaries[2].y,
|
||||
data.hdrMetadata->hdmi_metadata_type1.display_primaries[0].x, data.hdrMetadata->hdmi_metadata_type1.white_point.x,
|
||||
data.hdrMetadata->hdmi_metadata_type1.white_point.y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((STATE.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE) && connector->crtc->primary->props.fb_damage_clips && MODE) {
|
||||
if (STATE.damage.empty())
|
||||
data.atomic.fbDamage = 0;
|
||||
|
|
|
@ -39,6 +39,10 @@ size_t Aquamarine::IOutput::getGammaSize() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t Aquamarine::IOutput::getDeGammaSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Aquamarine::IOutput::destroy() {
|
||||
return false;
|
||||
}
|
||||
|
@ -77,6 +81,11 @@ void Aquamarine::COutputState::setGammaLut(const std::vector<uint16_t>& lut) {
|
|||
internalState.committed |= AQ_OUTPUT_STATE_GAMMA_LUT;
|
||||
}
|
||||
|
||||
void Aquamarine::COutputState::setDeGammaLut(const std::vector<uint16_t>& lut) {
|
||||
internalState.gammaLut = lut;
|
||||
internalState.committed |= AQ_OUTPUT_STATE_DEGAMMA_LUT;
|
||||
}
|
||||
|
||||
void Aquamarine::COutputState::setMode(Hyprutils::Memory::CSharedPointer<SOutputMode> mode) {
|
||||
internalState.mode = mode;
|
||||
internalState.customMode = nullptr;
|
||||
|
@ -119,6 +128,15 @@ void Aquamarine::COutputState::setCTM(const Hyprutils::Math::Mat3x3& ctm) {
|
|||
internalState.committed |= AQ_OUTPUT_STATE_CTM;
|
||||
}
|
||||
|
||||
void Aquamarine::COutputState::setWideColorGamut(bool wcg) {
|
||||
internalState.wideColorGamut = wcg;
|
||||
}
|
||||
|
||||
void Aquamarine::COutputState::setHDRMetadata(const hdr_output_metadata& metadata) {
|
||||
internalState.hdrMetadata = metadata;
|
||||
internalState.committed |= AQ_OUTPUT_STATE_HDR;
|
||||
}
|
||||
|
||||
void Aquamarine::COutputState::onCommit() {
|
||||
internalState.committed = 0;
|
||||
internalState.damage.clear();
|
||||
|
|
Loading…
Reference in a new issue