diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 180cc36d7e..26168cf6d2 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -360,7 +360,8 @@ ColorDescription DrmOutput::createColorDescription(const std::shared_ptrmaxPeakBrightnessOverride.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; } diff --git a/src/core/iccprofile.cpp b/src/core/iccprofile.cpp index f4279647c0..d2c53cd84a 100644 --- a/src/core/iccprofile.cpp +++ b/src/core/iccprofile.cpp @@ -17,19 +17,21 @@ namespace KWin { -IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr &vcgt) +IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr &vcgt, std::optional 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 &inverseEOTF, const std::shared_ptr &vcgt) +IccProfile::IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr &inverseEOTF, const std::shared_ptr &vcgt, std::optional 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 IccProfile::brightness() const +{ + return m_brightness; +} + const Colorimetry &IccProfile::colorimetry() const { return m_colorimetry; @@ -311,6 +318,13 @@ std::unique_ptr IccProfile::load(const QString &path) return nullptr; } + std::optional brightness; + if (cmsCIEXYZ *luminance = static_cast(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::load(const QString &path) // lut based profile, with relative colorimetric intent supported auto data = parseBToATag(handle, cmsSigBToA1Tag); if (data) { - return std::make_unique(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt); + return std::make_unique(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::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(handle, Colorimetry(red, green, blue, white), std::move(*data), vcgt); + return std::make_unique(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::load(const QString &path) std::vector> stages; stages.push_back(std::make_unique(cmsStageAllocToneCurves(nullptr, 3, toneCurves))); const auto inverseEOTF = std::make_shared(std::move(stages)); - return std::make_unique(handle, Colorimetry(red, green, blue, white), inverseEOTF, vcgt); + return std::make_unique(handle, Colorimetry(red, green, blue, white), inverseEOTF, vcgt, brightness); } } diff --git a/src/core/iccprofile.h b/src/core/iccprofile.h index ea528685ff..1aefefce00 100644 --- a/src/core/iccprofile.h +++ b/src/core/iccprofile.h @@ -33,8 +33,8 @@ public: std::unique_ptr A; }; - explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr &vcgt); - explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr &inverseEOTF, const std::shared_ptr &vcgt); + explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, BToATagData &&bToATag, const std::shared_ptr &vcgt, std::optional brightness); + explicit IccProfile(cmsHPROFILE handle, const Colorimetry &colorimetry, const std::shared_ptr &inverseEOTF, const std::shared_ptr &vcgt, std::optional brightness); ~IccProfile(); /** @@ -52,6 +52,10 @@ public: */ std::shared_ptr vcgt() const; const Colorimetry &colorimetry() const; + /** + * The brightness with a completely white output, in nits + */ + std::optional brightness() const; static std::unique_ptr load(const QString &path); @@ -61,6 +65,7 @@ private: const std::optional m_bToATag; const std::shared_ptr m_inverseEOTF; const std::shared_ptr m_vcgt; + const std::optional m_brightness; }; }