core: add a TransferFunction class and move transfer function functions in there

This way it's more obvious where to find them, and the class can be extended with more
functionality later, like transfer functions with parameters
This commit is contained in:
Xaver Hugl 2024-07-04 15:16:48 +02:00
parent 372ea85326
commit de85867675
15 changed files with 135 additions and 116 deletions

View file

@ -39,24 +39,24 @@ static const double s_resolution10bit = std::pow(1.0 / 2.0, 10);
void TestColorspaces::roundtripConversion_data()
{
QTest::addColumn<NamedColorimetry>("srcColorimetry");
QTest::addColumn<NamedTransferFunction>("srcTransferFunction");
QTest::addColumn<TransferFunction::Type>("srcTransferFunction");
QTest::addColumn<NamedColorimetry>("dstColorimetry");
QTest::addColumn<NamedTransferFunction>("dstTransferFunction");
QTest::addColumn<TransferFunction::Type>("dstTransferFunction");
QTest::addColumn<double>("requiredAccuracy");
QTest::addRow("BT709 (sRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::sRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (gamma 2.2) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::gamma22 << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (scRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::scRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (linear) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::linear << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (PQ) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::PerceptualQuantizer << NamedColorimetry::BT2020 << NamedTransferFunction::linear << 3 * s_resolution10bit;
QTest::addRow("BT709 (sRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << TransferFunction::sRGB << NamedColorimetry::BT2020 << TransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (gamma 2.2) <-> BT2020 (linear)") << NamedColorimetry::BT709 << TransferFunction::gamma22 << NamedColorimetry::BT2020 << TransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (scRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << TransferFunction::scRGB << NamedColorimetry::BT2020 << TransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (linear) <-> BT2020 (linear)") << NamedColorimetry::BT709 << TransferFunction::linear << NamedColorimetry::BT2020 << TransferFunction::linear << s_resolution10bit;
QTest::addRow("BT709 (PQ) <-> BT2020 (linear)") << NamedColorimetry::BT709 << TransferFunction::PerceptualQuantizer << NamedColorimetry::BT2020 << TransferFunction::linear << 3 * s_resolution10bit;
}
void TestColorspaces::roundtripConversion()
{
QFETCH(NamedColorimetry, srcColorimetry);
QFETCH(NamedTransferFunction, srcTransferFunction);
QFETCH(TransferFunction::Type, srcTransferFunction);
QFETCH(NamedColorimetry, dstColorimetry);
QFETCH(NamedTransferFunction, dstTransferFunction);
QFETCH(TransferFunction::Type, dstTransferFunction);
QFETCH(double, requiredAccuracy);
const auto src = ColorDescription(srcColorimetry, srcTransferFunction, 100, 0, 100, 100);

View file

@ -115,7 +115,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
m_surface->iccShader.reset();
}
if (enableColormanagement) {
m_surface->intermediaryColorDescription = ColorDescription(colorDescription.containerColorimetry(), NamedTransferFunction::linear,
m_surface->intermediaryColorDescription = ColorDescription(colorDescription.containerColorimetry(), TransferFunction::linear,
colorDescription.referenceLuminance(), colorDescription.minLuminance(),
colorDescription.maxAverageLuminance(), colorDescription.maxHdrLuminance(),
colorDescription.containerColorimetry(), colorDescription.sdrColorimetry());
@ -199,8 +199,8 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame
ctm(1, 1) = m_surface->adaptedChannelFactors.y() * brightnessFactor;
ctm(2, 2) = m_surface->adaptedChannelFactors.z() * brightnessFactor;
binder.shader()->setUniform(GLShader::Mat4Uniform::ColorimetryTransformation, ctm);
binder.shader()->setUniform(GLShader::IntUniform::SourceNamedTransferFunction, int(m_surface->intermediaryColorDescription.transferFunction()));
binder.shader()->setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, int(m_surface->targetColorDescription.transferFunction()));
binder.shader()->setUniform(GLShader::IntUniform::SourceNamedTransferFunction, m_surface->intermediaryColorDescription.transferFunction().type);
binder.shader()->setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, m_surface->targetColorDescription.transferFunction().type);
binder.shader()->setUniform(GLShader::FloatUniform::SourceReferenceLuminance, m_surface->intermediaryColorDescription.referenceLuminance());
binder.shader()->setUniform(GLShader::FloatUniform::DestinationReferenceLuminance, m_surface->intermediaryColorDescription.referenceLuminance());
binder.shader()->setUniform(GLShader::FloatUniform::MaxDestinationLuminance, m_surface->intermediaryColorDescription.maxHdrLuminance().value_or(800));

View file

@ -359,7 +359,7 @@ ColorDescription DrmOutput::createColorDescription(const std::shared_ptr<OutputC
const auto iccProfile = props->iccProfile.value_or(m_state.iccProfile);
if (colorSource == ColorProfileSource::ICC && !hdr && !wcg && iccProfile) {
const double brightness = iccProfile->brightness().value_or(200);
return ColorDescription(iccProfile->colorimetry(), NamedTransferFunction::gamma22, brightness, 0, brightness, brightness);
return ColorDescription(iccProfile->colorimetry(), TransferFunction::gamma22, brightness, 0, brightness, brightness);
}
const bool screenSupportsHdr = m_connector->edid()->isValid() && m_connector->edid()->supportsBT2020() && m_connector->edid()->supportsPQ();
const bool driverSupportsHdr = m_connector->colorspace.isValid() && m_connector->hdrMetadata.isValid() && (m_connector->colorspace.hasEnum(DrmConnector::Colorspace::BT2020_RGB) || m_connector->colorspace.hasEnum(DrmConnector::Colorspace::BT2020_YCC));
@ -371,7 +371,7 @@ ColorDescription DrmOutput::createColorDescription(const std::shared_ptr<OutputC
const Colorimetry masteringColorimetry = (effectiveWcg || colorSource == ColorProfileSource::EDID) ? nativeColorimetry : Colorimetry::fromName(NamedColorimetry::BT709);
const Colorimetry sdrColorimetry = effectiveWcg ? Colorimetry::fromName(NamedColorimetry::BT709).interpolateGamutTo(nativeColorimetry, props->sdrGamutWideness.value_or(m_state.sdrGamutWideness)) : Colorimetry::fromName(NamedColorimetry::BT709);
// TODO the EDID can contain a gamma value, use that when available and colorSource == ColorProfileSource::EDID
const NamedTransferFunction transferFunction = effectiveHdr ? NamedTransferFunction::PerceptualQuantizer : NamedTransferFunction::gamma22;
const TransferFunction transferFunction = effectiveHdr ? TransferFunction::PerceptualQuantizer : TransferFunction::gamma22;
const double minBrightness = effectiveHdr ? props->minBrightnessOverride.value_or(m_state.minBrightnessOverride).value_or(m_connector->edid()->desiredMinLuminance()) : 0;
const double maxAverageBrightness = effectiveHdr ? props->maxAverageBrightnessOverride.value_or(m_state.maxAverageBrightnessOverride).value_or(m_connector->edid()->desiredMaxFrameAverageLuminance().value_or(m_state.referenceLuminance)) : 200;
const double maxPeakBrightness = effectiveHdr ? props->maxPeakBrightnessOverride.value_or(m_state.maxPeakBrightnessOverride).value_or(m_connector->edid()->desiredMaxLuminance().value_or(800)) : 200;
@ -458,12 +458,12 @@ bool DrmOutput::doSetChannelFactors(const QVector3D &rgb)
if (!m_pipeline->activePending()) {
return false;
}
const auto inGamma22 = ColorDescription::nitsToEncoded(rgb, NamedTransferFunction::gamma22, 1);
const auto inOutputSpace = m_state.colorDescription.transferFunction().nitsToEncoded(rgb, 1);
if (m_pipeline->hasCTM()) {
QMatrix3x3 ctm;
ctm(0, 0) = inGamma22.x();
ctm(1, 1) = inGamma22.y();
ctm(2, 2) = inGamma22.z();
ctm(0, 0) = inOutputSpace.x();
ctm(1, 1) = inOutputSpace.y();
ctm(2, 2) = inOutputSpace.z();
m_pipeline->setCTM(ctm);
m_pipeline->setGammaRamp(nullptr);
if (DrmPipeline::commitPipelines({m_pipeline}, DrmPipeline::CommitMode::Test) == DrmPipeline::Error::None) {
@ -476,7 +476,7 @@ bool DrmOutput::doSetChannelFactors(const QVector3D &rgb)
}
}
if (m_pipeline->hasGammaRamp()) {
auto lut = ColorTransformation::createScalingTransform(inGamma22);
auto lut = ColorTransformation::createScalingTransform(inOutputSpace);
if (lut) {
m_pipeline->setGammaRamp(std::move(lut));
if (DrmPipeline::commitPipelines({m_pipeline}, DrmPipeline::CommitMode::Test) == DrmPipeline::Error::None) {

View file

@ -310,7 +310,7 @@ bool DrmPipeline::prepareAtomicModeset(DrmAtomicCommit *commit)
}
if (m_connector->hdrMetadata.isValid()) {
commit->addBlob(m_connector->hdrMetadata, createHdrMetadata(m_pending.colorDescription.transferFunction()));
} else if (m_pending.colorDescription.transferFunction() != NamedTransferFunction::gamma22) {
} else if (m_pending.colorDescription.transferFunction() != TransferFunction::gamma22) {
return false;
}
if (m_pending.colorDescription.containerColorimetry() == NamedColorimetry::BT2020) {
@ -724,9 +724,9 @@ void DrmPipeline::setIccProfile(const std::shared_ptr<IccProfile> &profile)
}
}
std::shared_ptr<DrmBlob> DrmPipeline::createHdrMetadata(NamedTransferFunction transferFunction) const
std::shared_ptr<DrmBlob> DrmPipeline::createHdrMetadata(TransferFunction transferFunction) const
{
if (transferFunction != NamedTransferFunction::PerceptualQuantizer) {
if (transferFunction != TransferFunction::PerceptualQuantizer) {
// for sRGB / gamma 2.2, don't send any metadata, to ensure the non-HDR experience stays the same
return nullptr;
}

View file

@ -144,7 +144,7 @@ private:
bool isBufferForDirectScanout() const;
uint32_t calculateUnderscan();
static Error errnoToError();
std::shared_ptr<DrmBlob> createHdrMetadata(NamedTransferFunction transferFunction) const;
std::shared_ptr<DrmBlob> createHdrMetadata(TransferFunction transferFunction) const;
// legacy only
Error presentLegacy(const std::shared_ptr<OutputFrame> &frame);

View file

@ -46,7 +46,7 @@ bool X11Output::setChannelFactors(const QVector3D &rgb)
if (m_crtc == XCB_NONE) {
return true;
}
auto transformation = ColorTransformation::createScalingTransform(ColorDescription::nitsToEncoded(rgb, NamedTransferFunction::gamma22, 1));
auto transformation = ColorTransformation::createScalingTransform(m_state.colorDescription.transferFunction().nitsToEncoded(rgb, 1));
if (!transformation) {
return false;
}

View file

@ -63,7 +63,7 @@ void ColorDevicePrivate::recalculateFactors()
blackbodyColor[blackBodyColorIndex + 5],
blendFactor);
// the values in the blackbodyColor array are "gamma corrected", but we need a linear value
temperatureFactors = ColorDescription::encodedToNits(QVector3D(xWhitePoint, yWhitePoint, zWhitePoint), NamedTransferFunction::gamma22, 1);
temperatureFactors = TransferFunction(TransferFunction::gamma22).encodedToNits(QVector3D(xWhitePoint, yWhitePoint, zWhitePoint), 1);
}
simpleTransformation = brightnessFactors * temperatureFactors;
}

View file

@ -198,19 +198,19 @@ const Colorimetry &Colorimetry::fromName(NamedColorimetry name)
Q_UNREACHABLE();
}
const ColorDescription ColorDescription::sRGB = ColorDescription(NamedColorimetry::BT709, NamedTransferFunction::gamma22, 100, 0, 100, 100);
const ColorDescription ColorDescription::sRGB = ColorDescription(NamedColorimetry::BT709, TransferFunction::gamma22, 100, 0, 100, 100);
ColorDescription::ColorDescription(const Colorimetry &containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance)
ColorDescription::ColorDescription(const Colorimetry &containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance)
: ColorDescription(containerColorimetry, tf, referenceLuminance, minLuminance, maxAverageLuminance, maxHdrLuminance, std::nullopt, Colorimetry::fromName(NamedColorimetry::BT709))
{
}
ColorDescription::ColorDescription(NamedColorimetry containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance)
ColorDescription::ColorDescription(NamedColorimetry containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance)
: ColorDescription(Colorimetry::fromName(containerColorimetry), tf, referenceLuminance, minLuminance, maxAverageLuminance, maxHdrLuminance, std::nullopt, Colorimetry::fromName(NamedColorimetry::BT709))
{
}
ColorDescription::ColorDescription(const Colorimetry &containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry)
ColorDescription::ColorDescription(const Colorimetry &containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry)
: m_containerColorimetry(containerColorimetry)
, m_masteringColorimetry(masteringColorimetry)
, m_transferFunction(tf)
@ -222,7 +222,7 @@ ColorDescription::ColorDescription(const Colorimetry &containerColorimetry, Name
{
}
ColorDescription::ColorDescription(NamedColorimetry containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry)
ColorDescription::ColorDescription(NamedColorimetry containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry)
: ColorDescription(Colorimetry::fromName(containerColorimetry), tf, referenceLuminance, minLuminance, maxAverageLuminance, maxHdrLuminance, masteringColorimetry, sdrColorimetry)
{
}
@ -242,7 +242,7 @@ const Colorimetry &ColorDescription::sdrColorimetry() const
return m_sdrColorimetry;
}
NamedTransferFunction ColorDescription::transferFunction() const
TransferFunction ColorDescription::transferFunction() const
{
return m_transferFunction;
}
@ -312,53 +312,59 @@ static float pqToNits(float pq)
return 10000.0f * std::pow(num / den, m1_inv);
}
static QVector3D clamp(const QVector3D &vect, float min = 0, float max = 1)
{
return QVector3D(std::clamp(vect.x(), min, max), std::clamp(vect.y(), min, max), std::clamp(vect.z(), min, max));
}
QVector3D ColorDescription::encodedToNits(const QVector3D &nits, NamedTransferFunction tf, double referenceLuminance)
{
switch (tf) {
case NamedTransferFunction::sRGB:
return referenceLuminance * QVector3D(srgbToLinear(nits.x()), srgbToLinear(nits.y()), srgbToLinear(nits.z()));
case NamedTransferFunction::gamma22:
return referenceLuminance * QVector3D(std::pow(nits.x(), 2.2), std::pow(nits.y(), 2.2), std::pow(nits.z(), 2.2));
case NamedTransferFunction::linear:
return nits;
case NamedTransferFunction::scRGB:
return nits * 80.0f;
case NamedTransferFunction::PerceptualQuantizer:
return QVector3D(pqToNits(nits.x()), pqToNits(nits.y()), pqToNits(nits.z()));
}
Q_UNREACHABLE();
}
QVector3D ColorDescription::nitsToEncoded(const QVector3D &rgb, NamedTransferFunction tf, double referenceLuminance)
{
switch (tf) {
case NamedTransferFunction::sRGB: {
const auto clamped = clamp(rgb / referenceLuminance);
return QVector3D(linearToSRGB(clamped.x()), linearToSRGB(clamped.y()), linearToSRGB(clamped.z()));
}
case NamedTransferFunction::gamma22: {
const auto clamped = clamp(rgb / referenceLuminance);
return QVector3D(std::pow(clamped.x(), 1 / 2.2), std::pow(clamped.y(), 1 / 2.2), std::pow(clamped.z(), 1 / 2.2));
}
case NamedTransferFunction::linear:
return rgb;
case NamedTransferFunction::scRGB:
return rgb / 80.0f;
case NamedTransferFunction::PerceptualQuantizer:
return QVector3D(nitsToPQ(rgb.x()), nitsToPQ(rgb.y()), nitsToPQ(rgb.z()));
}
Q_UNREACHABLE();
}
QVector3D ColorDescription::mapTo(QVector3D rgb, const ColorDescription &dst) const
{
rgb = encodedToNits(rgb, m_transferFunction, m_referenceLuminance);
rgb = m_transferFunction.encodedToNits(rgb, m_referenceLuminance);
rgb = m_containerColorimetry.toOther(dst.containerColorimetry()) * rgb;
return nitsToEncoded(rgb, dst.transferFunction(), dst.referenceLuminance());
return dst.transferFunction().nitsToEncoded(rgb, dst.referenceLuminance());
}
TransferFunction::TransferFunction(Type tf)
: type(tf)
{
}
double TransferFunction::encodedToNits(double encoded, double referenceLuminance) const
{
switch (type) {
case TransferFunction::sRGB:
return referenceLuminance * srgbToLinear(encoded);
case TransferFunction::gamma22:
return referenceLuminance * std::pow(encoded, 2.2);
case TransferFunction::linear:
return encoded;
case TransferFunction::scRGB:
return encoded * 80.0f;
case TransferFunction::PerceptualQuantizer:
return pqToNits(encoded);
}
Q_UNREACHABLE();
}
QVector3D TransferFunction::encodedToNits(const QVector3D &encoded, double referenceLuminance) const
{
return QVector3D(encodedToNits(encoded.x(), referenceLuminance), encodedToNits(encoded.y(), referenceLuminance), encodedToNits(encoded.z(), referenceLuminance));
}
double TransferFunction::nitsToEncoded(double nits, double referenceLuminance) const
{
switch (type) {
case TransferFunction::sRGB:
return linearToSRGB(std::clamp(nits / referenceLuminance, 0.0, 1.0));
case TransferFunction::gamma22:
return std::pow(std::clamp(nits / referenceLuminance, 0.0, 1.0), 1.0 / 2.2);
case TransferFunction::linear:
return nits;
case TransferFunction::scRGB:
return nits / 80.0f;
case TransferFunction::PerceptualQuantizer:
return nitsToPQ(nits);
}
Q_UNREACHABLE();
}
QVector3D TransferFunction::nitsToEncoded(const QVector3D &nits, double referenceLuminance) const
{
return QVector3D(nitsToEncoded(nits.x(), referenceLuminance), nitsToEncoded(nits.y(), referenceLuminance), nitsToEncoded(nits.z(), referenceLuminance));
}
}

View file

@ -85,14 +85,29 @@ private:
};
/**
* Describes an EOTF, that is, how encoded brightness values are converted to light
* Describes an EOTF - how encoded values are converted to light
*/
enum class NamedTransferFunction {
sRGB = 0,
linear = 1,
PerceptualQuantizer = 2,
scRGB = 3,
gamma22 = 4,
class KWIN_EXPORT TransferFunction
{
public:
enum Type {
sRGB = 0,
linear = 1,
PerceptualQuantizer = 2,
scRGB = 3,
gamma22 = 4,
};
TransferFunction(Type tf);
auto operator<=>(const TransferFunction &) const = default;
double encodedToNits(double encoded, double referenceLuminance) const;
double nitsToEncoded(double nits, double referenceLuminance) const;
QVector3D encodedToNits(const QVector3D &encoded, double referenceLuminance) const;
QVector3D nitsToEncoded(const QVector3D &nits, double referenceLuminance) const;
Type type;
};
/**
@ -111,10 +126,10 @@ public:
* @param maxHdrLuminance the maximum brightness of HDR content, for a small part of the screen only
* @param sdrColorimetry
*/
explicit ColorDescription(const Colorimetry &containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance);
explicit ColorDescription(NamedColorimetry containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance);
explicit ColorDescription(const Colorimetry &containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry);
explicit ColorDescription(NamedColorimetry containerColorimetry, NamedTransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry);
explicit ColorDescription(const Colorimetry &containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance);
explicit ColorDescription(NamedColorimetry containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance);
explicit ColorDescription(const Colorimetry &containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry);
explicit ColorDescription(NamedColorimetry containerColorimetry, TransferFunction tf, double referenceLuminance, double minLuminance, std::optional<double> maxAverageLuminance, std::optional<double> maxHdrLuminance, std::optional<Colorimetry> masteringColorimetry, const Colorimetry &sdrColorimetry);
/**
* The primaries and whitepoint that colors are encoded for. This is used to convert between different colorspaces.
@ -128,7 +143,7 @@ public:
*/
const std::optional<Colorimetry> &masteringColorimetry() const;
const Colorimetry &sdrColorimetry() const;
NamedTransferFunction transferFunction() const;
TransferFunction transferFunction() const;
double referenceLuminance() const;
double minLuminance() const;
std::optional<double> maxAverageLuminance() const;
@ -142,13 +157,11 @@ public:
* This color description describes display-referred sRGB, with a gamma22 transfer function
*/
static const ColorDescription sRGB;
static QVector3D encodedToNits(const QVector3D &nits, NamedTransferFunction tf, double referenceLuminance);
static QVector3D nitsToEncoded(const QVector3D &rgb, NamedTransferFunction tf, double referenceLuminance);
private:
Colorimetry m_containerColorimetry;
std::optional<Colorimetry> m_masteringColorimetry;
NamedTransferFunction m_transferFunction;
TransferFunction m_transferFunction;
Colorimetry m_sdrColorimetry;
double m_referenceLuminance;
double m_minLuminance;

View file

@ -457,8 +457,8 @@ bool GLShader::setColorspaceUniforms(const ColorDescription &src, const ColorDes
{
const auto &srcColorimetry = src.containerColorimetry() == NamedColorimetry::BT709 ? dst.sdrColorimetry() : src.containerColorimetry();
return setUniform(GLShader::Mat4Uniform::ColorimetryTransformation, srcColorimetry.toOther(dst.containerColorimetry()))
&& setUniform(GLShader::IntUniform::SourceNamedTransferFunction, int(src.transferFunction()))
&& setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, int(dst.transferFunction()))
&& setUniform(GLShader::IntUniform::SourceNamedTransferFunction, src.transferFunction().type)
&& setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, dst.transferFunction().type)
&& setUniform(FloatUniform::SourceReferenceLuminance, src.referenceLuminance())
&& setUniform(FloatUniform::DestinationReferenceLuminance, dst.referenceLuminance())
&& setUniform(FloatUniform::MaxDestinationLuminance, dst.maxHdrLuminance().value_or(10'000));

View file

@ -65,7 +65,7 @@ void ColorPickerEffect::paintScreen(const RenderTarget &renderTarget, const Rend
std::array<float, 4> data;
constexpr GLsizei PIXEL_SIZE = 1;
const QPoint texturePosition = viewport.mapToRenderTarget(m_scheduledPosition).toPoint();
const ColorDescription sRGBencoding(Colorimetry::fromName(NamedColorimetry::BT709), NamedTransferFunction::gamma22, renderTarget.colorDescription().referenceLuminance(), 0, renderTarget.colorDescription().referenceLuminance(), renderTarget.colorDescription().referenceLuminance());
const ColorDescription sRGBencoding(Colorimetry::fromName(NamedColorimetry::BT709), TransferFunction::gamma22, renderTarget.colorDescription().referenceLuminance(), 0, renderTarget.colorDescription().referenceLuminance(), renderTarget.colorDescription().referenceLuminance());
glReadPixels(texturePosition.x(), renderTarget.size().height() - texturePosition.y() - PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE, GL_RGBA, GL_FLOAT, data.data());
QVector3D sRGB = 255 * renderTarget.colorDescription().mapTo(QVector3D(data[0], data[1], data[2]), sRGBencoding);

View file

@ -50,18 +50,18 @@ FrogColorManagementSurfaceV1::~FrogColorManagementSurfaceV1()
}
}
static QtWaylandServer::frog_color_managed_surface::transfer_function kwinToFrogTransferFunction(NamedTransferFunction tf)
static QtWaylandServer::frog_color_managed_surface::transfer_function kwinToFrogTransferFunction(TransferFunction tf)
{
switch (tf) {
case NamedTransferFunction::sRGB:
switch (tf.type) {
case TransferFunction::sRGB:
return QtWaylandServer::frog_color_managed_surface::transfer_function_srgb;
case NamedTransferFunction::gamma22:
case TransferFunction::gamma22:
return QtWaylandServer::frog_color_managed_surface::transfer_function_gamma_22;
case NamedTransferFunction::PerceptualQuantizer:
case TransferFunction::PerceptualQuantizer:
return QtWaylandServer::frog_color_managed_surface::transfer_function_st2084_pq;
case NamedTransferFunction::scRGB:
case TransferFunction::scRGB:
return QtWaylandServer::frog_color_managed_surface::transfer_function_scrgb_linear;
case NamedTransferFunction::linear:
case TransferFunction::linear:
return QtWaylandServer::frog_color_managed_surface::transfer_function_scrgb_linear;
}
return QtWaylandServer::frog_color_managed_surface::transfer_function_undefined;
@ -91,13 +91,13 @@ void FrogColorManagementSurfaceV1::frog_color_managed_surface_set_known_transfer
case transfer_function_undefined:
case transfer_function_srgb:
case transfer_function_gamma_22:
m_transferFunction = NamedTransferFunction::gamma22;
m_transferFunction = TransferFunction::gamma22;
break;
case transfer_function_st2084_pq:
m_transferFunction = NamedTransferFunction::PerceptualQuantizer;
m_transferFunction = TransferFunction::PerceptualQuantizer;
break;
case transfer_function_scrgb_linear:
m_transferFunction = NamedTransferFunction::scRGB;
m_transferFunction = TransferFunction::scRGB;
break;
}
updateColorDescription();

View file

@ -53,7 +53,7 @@ private:
void updateColorDescription();
const QPointer<SurfaceInterface> m_surface;
NamedTransferFunction m_transferFunction = NamedTransferFunction::sRGB;
TransferFunction m_transferFunction = TransferFunction::sRGB;
NamedColorimetry m_containerColorimetry = NamedColorimetry::BT709;
std::optional<Colorimetry> m_masteringColorimetry;
std::optional<double> m_maxAverageLuminance;

View file

@ -148,7 +148,7 @@ void XXColorParametricCreatorV2::xx_image_description_creator_params_v2_create(R
wl_resource_post_error(resource->handle, error::error_incomplete_set, "colorimetry or transfer function missing");
return;
}
if (m_transferFunction != NamedTransferFunction::PerceptualQuantizer && (m_maxAverageLuminance || m_maxPeakBrightness)) {
if (m_transferFunction != TransferFunction::PerceptualQuantizer && (m_maxAverageLuminance || m_maxPeakBrightness)) {
wl_resource_post_error(resource->handle, error::error_inconsistent_set, "max_cll and max_fall must only be set with the PQ transfer function");
return;
}
@ -166,10 +166,10 @@ void XXColorParametricCreatorV2::xx_image_description_creator_params_v2_set_tf_n
case XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB:
case XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_BT709:
case XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA22:
m_transferFunction = NamedTransferFunction::gamma22;
m_transferFunction = TransferFunction::gamma22;
return;
case XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ:
m_transferFunction = NamedTransferFunction::PerceptualQuantizer;
m_transferFunction = TransferFunction::PerceptualQuantizer;
return;
default:
// TODO add more transfer functions
@ -257,18 +257,18 @@ void XXImageDescriptionV2::xx_image_description_v2_destroy(Resource *resource)
wl_resource_destroy(resource->handle);
}
static uint32_t kwinTFtoProtoTF(NamedTransferFunction tf)
static uint32_t kwinTFtoProtoTF(TransferFunction tf)
{
switch (tf) {
case NamedTransferFunction::sRGB:
switch (tf.type) {
case TransferFunction::sRGB:
return xx_color_manager_v2_transfer_function::XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB;
case NamedTransferFunction::linear:
case TransferFunction::linear:
return xx_color_manager_v2_transfer_function::XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR;
case NamedTransferFunction::PerceptualQuantizer:
case TransferFunction::PerceptualQuantizer:
return xx_color_manager_v2_transfer_function::XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ;
case NamedTransferFunction::scRGB:
case TransferFunction::scRGB:
return xx_color_manager_v2_transfer_function::XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR;
case NamedTransferFunction::gamma22:
case TransferFunction::gamma22:
return xx_color_manager_v2_transfer_function::XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA22;
}
Q_UNREACHABLE();

View file

@ -69,7 +69,7 @@ private:
void xx_image_description_creator_params_v2_set_max_fall(Resource *resource, uint32_t max_fall) override;
std::optional<Colorimetry> m_colorimetry;
std::optional<NamedTransferFunction> m_transferFunction;
std::optional<TransferFunction> m_transferFunction;
std::optional<double> m_maxAverageLuminance;
std::optional<double> m_maxPeakBrightness;
};