backends/drm: support HDR content while an ICC profile is set better
The brightness of the screen is read from the luminance tag, and through the color management protocol(s) passed to apps, so that they can adjust their content accordingly
This commit is contained in:
parent
183637502d
commit
d55f012537
3 changed files with 28 additions and 8 deletions
|
@ -360,7 +360,8 @@ ColorDescription DrmOutput::createColorDescription(const std::shared_ptr<OutputC
|
|||
props->maxPeakBrightnessOverride.value_or(m_state.maxPeakBrightnessOverride).value_or(m_connector->edid()->desiredMaxLuminance().value_or(1000)),
|
||||
Colorimetry::fromName(NamedColorimetry::BT709).interpolateGamutTo(nativeColorimetry, props->sdrGamutWideness.value_or(m_state.sdrGamutWideness)));
|
||||
} else if (const auto profile = props->iccProfile.value_or(m_state.iccProfile)) {
|
||||
return ColorDescription(profile->colorimetry(), NamedTransferFunction::gamma22, 200, 0, 200, 200);
|
||||
const double brightness = profile->brightness().value_or(200);
|
||||
return ColorDescription(profile->colorimetry(), NamedTransferFunction::gamma22, brightness, 0, brightness, brightness);
|
||||
} else {
|
||||
return ColorDescription::sRGB;
|
||||
}
|
||||
|
|
|
@ -17,19 +17,21 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr<ColorTransformation> &vcgt)
|
||||
IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr<ColorTransformation> &vcgt, std::optional<double> brightness)
|
||||
: m_handle(handle)
|
||||
, m_colorimetry(colorimetry)
|
||||
, m_bToATag(std::move(bToATag))
|
||||
, m_vcgt(vcgt)
|
||||
, m_brightness(brightness)
|
||||
{
|
||||
}
|
||||
|
||||
IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr<ColorTransformation> &inverseEOTF, const std::shared_ptr<ColorTransformation> &vcgt)
|
||||
IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr<ColorTransformation> &inverseEOTF, const std::shared_ptr<ColorTransformation> &vcgt, std::optional<double> brightness)
|
||||
: m_handle(handle)
|
||||
, m_colorimetry(colorimetry)
|
||||
, m_inverseEOTF(inverseEOTF)
|
||||
, m_vcgt(vcgt)
|
||||
, m_brightness(brightness)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -38,6 +40,11 @@ IccProfile::~IccProfile()
|
|||
cmsCloseProfile(m_handle);
|
||||
}
|
||||
|
||||
std::optional<double> IccProfile::brightness() const
|
||||
{
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
const Colorimetry &IccProfile::colorimetry() const
|
||||
{
|
||||
return m_colorimetry;
|
||||
|
@ -311,6 +318,13 @@ std::unique_ptr<IccProfile> IccProfile::load(const QString &path)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::optional<double> brightness;
|
||||
if (cmsCIEXYZ *luminance = static_cast<cmsCIEXYZ *>(cmsReadTag(handle, cmsSigLuminanceTag))) {
|
||||
// for some reason, lcms exposes the luminance as a XYZ triple...
|
||||
// only Y is non-zero, and it's the brightness in nits
|
||||
brightness = luminance->Y;
|
||||
}
|
||||
|
||||
BToATagData lutData;
|
||||
if (cmsIsTag(handle, cmsSigBToD1Tag) && !cmsIsTag(handle, cmsSigBToA1Tag) && !cmsIsTag(handle, cmsSigBToA0Tag)) {
|
||||
qCWarning(KWIN_CORE, "Profiles with only BToD tags aren't supported yet");
|
||||
|
@ -320,7 +334,7 @@ std::unique_ptr<IccProfile> IccProfile::load(const QString &path)
|
|||
// lut based profile, with relative colorimetric intent supported
|
||||
auto data = parseBToATag(handle, cmsSigBToA1Tag);
|
||||
if (data) {
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt);
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt, brightness);
|
||||
} else {
|
||||
qCWarning(KWIN_CORE, "Parsing BToA1 tag failed");
|
||||
return nullptr;
|
||||
|
@ -330,7 +344,7 @@ std::unique_ptr<IccProfile> IccProfile::load(const QString &path)
|
|||
// lut based profile, with perceptual intent. The ICC docs say to use this as a fallback
|
||||
auto data = parseBToATag(handle, cmsSigBToA0Tag);
|
||||
if (data) {
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt);
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt, brightness);
|
||||
} else {
|
||||
qCWarning(KWIN_CORE, "Parsing BToA0 tag failed");
|
||||
return nullptr;
|
||||
|
@ -353,7 +367,7 @@ std::unique_ptr<IccProfile> IccProfile::load(const QString &path)
|
|||
std::vector<std::unique_ptr<ColorPipelineStage>> stages;
|
||||
stages.push_back(std::make_unique<ColorPipelineStage>(cmsStageAllocToneCurves(nullptr, 3, toneCurves)));
|
||||
const auto inverseEOTF = std::make_shared<ColorTransformation>(std::move(stages));
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), inverseEOTF, vcgt);
|
||||
return std::make_unique<IccProfile>(handle, Colorimetry(red, green, blue, white), inverseEOTF, vcgt, brightness);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public:
|
|||
std::unique_ptr<ColorTransformation> A;
|
||||
};
|
||||
|
||||
explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr<ColorTransformation> &vcgt);
|
||||
explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr<ColorTransformation> &inverseEOTF, const std::shared_ptr<ColorTransformation> &vcgt);
|
||||
explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr<ColorTransformation> &vcgt, std::optional<double> brightness);
|
||||
explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr<ColorTransformation> &inverseEOTF, const std::shared_ptr<ColorTransformation> &vcgt, std::optional<double> brightness);
|
||||
~IccProfile();
|
||||
|
||||
/**
|
||||
|
@ -52,6 +52,10 @@ public:
|
|||
*/
|
||||
std::shared_ptr<ColorTransformation> vcgt() const;
|
||||
const Colorimetry &colorimetry() const;
|
||||
/**
|
||||
* The brightness with a completely white output, in nits
|
||||
*/
|
||||
std::optional<double> brightness() const;
|
||||
|
||||
static std::unique_ptr<IccProfile> load(const QString &path);
|
||||
|
||||
|
@ -61,6 +65,7 @@ private:
|
|||
const std::optional<BToATagData> m_bToATag;
|
||||
const std::shared_ptr<ColorTransformation> m_inverseEOTF;
|
||||
const std::shared_ptr<ColorTransformation> m_vcgt;
|
||||
const std::optional<double> m_brightness;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue