From 3cf0280b11f370c11e6839275e547779a33f4a19 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Wed, 3 Dec 2025 04:30:43 +0300 Subject: [PATCH] renderer: add quirks:prefer_hdr to fix HDR activation for some clients (#12436) --- src/Compositor.cpp | 21 +++++++++++++++++++++ src/Compositor.hpp | 1 + src/config/ConfigDescriptions.hpp | 12 ++++++++++++ src/config/ConfigManager.cpp | 2 ++ src/protocols/core/Compositor.cpp | 4 ++++ 5 files changed, 40 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c8bd45fec..643aad1b3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2899,6 +2899,27 @@ SImageDescription CCompositor::getPreferredImageDescription() { return m_monitors.size() == 1 ? m_monitors[0]->m_imageDescription : SImageDescription{.primaries = NColorPrimaries::BT709}; } +SImageDescription CCompositor::getHDRImageDescription() { + if (!PROTO::colorManagement) { + Debug::log(ERR, "FIXME: color management protocol is not enabled, returning empty image description"); + return SImageDescription{}; + } + + return m_monitors.size() == 1 && m_monitors[0]->m_output && m_monitors[0]->m_output->parsedEDID.hdrMetadata.has_value() ? + SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), + .luminances = {.min = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMinLuminance, + .max = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredContentMaxLuminance, + .reference = m_monitors[0]->m_output->parsedEDID.hdrMetadata->desiredMaxFrameAverageLuminance}} : + SImageDescription{.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ, + .primariesNameSet = true, + .primariesNamed = NColorManagement::CM_PRIMARIES_BT2020, + .primaries = NColorManagement::getPrimaries(NColorManagement::CM_PRIMARIES_BT2020), + .luminances = {.min = 0, .max = 10000, .reference = 203}}; +} + bool CCompositor::shouldChangePreferredImageDescription() { Debug::log(WARN, "FIXME: color management protocol is enabled and outputs changed, check preferred image description changes"); return false; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 3e1e37f2a..77627a843 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -160,6 +160,7 @@ class CCompositor { std::optional getVTNr(); NColorManagement::SImageDescription getPreferredImageDescription(); + NColorManagement::SImageDescription getHDRImageDescription(); bool shouldChangePreferredImageDescription(); bool supportsDrmSyncobjTimeline() const; diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 6ef7c2634..a30b7b3d4 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -1993,4 +1993,16 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{false}, }, + + /* + * Quirks + */ + + SConfigOptionDescription{ + .value = "quirks:prefer_hdr", + .description = "Prefer HDR mode. 0 - off, 1 - always, 2 - gamescope only", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{.value = 0, .min = 0, .max = 2}, + }, + }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b6b52d345..8724e6611 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -770,6 +770,8 @@ CConfigManager::CConfigManager() { registerConfigVar("experimental:xx_color_management_v4", Hyprlang::INT{0}); + registerConfigVar("quirks:prefer_hdr", Hyprlang::INT{0}); + // devices m_config->addSpecialCategory("device", {"name"}); m_config->addSpecialConfigValue("device", "sensitivity", {0.F}); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 541eae928..efdbff50d 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -557,6 +557,10 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) { } SImageDescription CWLSurfaceResource::getPreferredImageDescription() { + static const auto PFORCE_HDR = CConfigValue("quirks:prefer_hdr"); + if (*PFORCE_HDR == 1 || (*PFORCE_HDR == 2 && m_hlSurface && m_hlSurface->getWindow() && m_hlSurface->getWindow()->m_class == "gamescope")) + return g_pCompositor->getHDRImageDescription(); + auto parent = m_self; if (parent->m_role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = sc(parent->m_role.get())->m_subsurface.lock();