mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 02:24:14 -05:00
render/cm: re-send HDR metadata when its content changes (#15761)
Compare the metadata we would send against what is already committed and send if there is any difference. Found this testing whether MaxCLL influences in-panel tonemapping. setHDRMetadata was only called when the monitor entered or left HDR or in some cases surrounding direct scanout. Changes to the metadata itself while the monitor stayed in HDR was computed and stored in the image description, but never sent. This particularly effects mastering data and min/max/max_avg luminance changes. Signed-off-by: Will Temple <will@wtemple.net>
This commit is contained in:
+23
-11
@@ -4,6 +4,8 @@
|
||||
#include <algorithm>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <drm_mode.h>
|
||||
#include <filesystem>
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
@@ -2297,6 +2299,14 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, P
|
||||
};
|
||||
}
|
||||
|
||||
static bool hdrMetadataEqual(const hdr_output_metadata& a, const hdr_output_metadata& b) {
|
||||
if (a.metadata_type != b.metadata_type)
|
||||
return false;
|
||||
|
||||
static_assert(std::has_unique_object_representations_v<hdr_metadata_infoframe>);
|
||||
return std::memcmp(&a.hdmi_metadata_type1, &b.hdmi_metadata_type1, sizeof(a.hdmi_metadata_type1));
|
||||
}
|
||||
|
||||
void IHyprRenderer::handleFullscreenSettings(PHLMONITOR pMonitor) {
|
||||
static auto PCT = CConfigValue<Config::INTEGER>("render:send_content_type");
|
||||
static auto PAUTOHDR = CConfigValue<Config::INTEGER>("render:cm_auto_hdr");
|
||||
@@ -2350,18 +2360,20 @@ void IHyprRenderer::handleFullscreenSettings(PHLMONITOR pMonitor) {
|
||||
if (!hdrIsHandled) {
|
||||
const bool HDR_CHANGED = pMonitor->inHDR() != wantHDR;
|
||||
|
||||
if (HDR_CHANGED || pMonitor->m_hdrMetadataFromSurface) {
|
||||
if (HDR_CHANGED && *PAUTOHDR && !(pMonitor->inHDR() && configuredHDR)) {
|
||||
// modify or restore monitor image description for auto-hdr
|
||||
// FIXME ok for now, will need some other logic if monitor image description can be modified some other way
|
||||
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
|
||||
const auto targetSDREOTF = pMonitor->m_sdrEotf;
|
||||
Log::logger->log(Log::INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
|
||||
pMonitor->applyCMType(targetCM, targetSDREOTF);
|
||||
pMonitor->m_previousFSWindow.reset(); // trigger CTM update
|
||||
}
|
||||
if (HDR_CHANGED && *PAUTOHDR && !(pMonitor->inHDR() && configuredHDR)) {
|
||||
const auto targetCM = wantHDR ? (*PAUTOHDR == 2 ? NCMType::CM_HDR_EDID : NCMType::CM_HDR) : pMonitor->m_cmType;
|
||||
const auto targetSDREOTF = pMonitor->m_sdrEotf;
|
||||
Log::logger->log(Log::INFO, "[CM] Auto HDR: changing monitor cm to {}", sc<uint8_t>(targetCM));
|
||||
pMonitor->applyCMType(targetCM, targetSDREOTF);
|
||||
pMonitor->m_previousFSWindow.reset(); // trigger CTM update
|
||||
}
|
||||
|
||||
const auto WANTED = wantHDR ? createHDRMetadata(pMonitor->m_imageDescription->value(), pMonitor) : NO_HDR_METADATA;
|
||||
const auto CURRENT = pMonitor->m_output->state->state().hdrMetadata;
|
||||
|
||||
if (HDR_CHANGED || pMonitor->m_hdrMetadataFromSurface || (wantHDR && !hdrMetadataEqual(WANTED, CURRENT))) {
|
||||
Log::logger->log(Log::INFO, wantHDR ? "[CM] Updating HDR metadata from monitor" : "[CM] Restoring SDR mode");
|
||||
pMonitor->m_output->state->setHDRMetadata(wantHDR ? createHDRMetadata(pMonitor->m_imageDescription->value(), pMonitor) : NO_HDR_METADATA);
|
||||
pMonitor->m_output->state->setHDRMetadata(WANTED);
|
||||
pMonitor->m_hdrMetadataFromSurface = false;
|
||||
}
|
||||
pMonitor->m_needsHDRupdate = true;
|
||||
|
||||
Reference in New Issue
Block a user