From 9433060760689dd39a6220a42a4d8addd75a80f6 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:33:03 +0300 Subject: [PATCH] renderer: fix screen export back to srgb (#13148) --- src/render/OpenGL.cpp | 44 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b00728ed..e3690ecd 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1374,16 +1374,21 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c tex->setTexParameter(GL_TEXTURE_MIN_FILTER, tex->minFilter); } - const bool isHDRSurface = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? m_renderData.surface->m_colorManagement->isHDR() : false; - const bool canPassHDRSurface = isHDRSurface && !m_renderData.surface->m_colorManagement->isWindowsScRGB(); // windows scRGB requires CM shader + const bool isHDRSurface = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? m_renderData.surface->m_colorManagement->isHDR() : false; + const bool canPassHDRSurface = isHDRSurface && !m_renderData.surface->m_colorManagement->isWindowsScRGB(); // windows scRGB requires CM shader - const auto imageDescription = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? - CImageDescription::from(m_renderData.surface->m_colorManagement->imageDescription()) : - (data.cmBackToSRGB ? data.cmBackToSRGBSource->m_imageDescription : DEFAULT_IMAGE_DESCRIPTION); + const auto imageDescription = m_renderData.surface.valid() && m_renderData.surface->m_colorManagement.valid() ? + CImageDescription::from(m_renderData.surface->m_colorManagement->imageDescription()) : + (data.cmBackToSRGB ? data.cmBackToSRGBSource->m_imageDescription : DEFAULT_IMAGE_DESCRIPTION); - const bool skipCM = !*PENABLECM || !m_cmSupported /* CM unsupported or disabled */ - || m_renderData.pMonitor->doesNoShaderCM() /* no shader needed */ - || (imageDescription->id() == m_renderData.pMonitor->m_imageDescription->id() && !data.cmBackToSRGB) /* Source and target have the same image description */ + static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); + auto chosenSdrEotf = *PSDREOTF != 3 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB; + const auto targetImageDescription = + data.cmBackToSRGB ? CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}) : m_renderData.pMonitor->m_imageDescription; + + const bool skipCM = !*PENABLECM || !m_cmSupported /* CM unsupported or disabled */ + || m_renderData.pMonitor->doesNoShaderCM() /* no shader needed */ + || (imageDescription->id() == targetImageDescription->id() && !data.cmBackToSRGB) /* Source and target have the same image description */ || (((*PPASS && canPassHDRSurface) || (*PPASS == 1 && !isHDRSurface && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR && m_renderData.pMonitor->m_cmType != NCMType::CM_HDR_EDID)) && m_renderData.pMonitor->inFullscreenMode()) /* Fullscreen window with pass cm enabled */; @@ -1401,20 +1406,19 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c if (!skipCM) { shaderFeatures |= SH_FEAT_CM; - const bool needsSDRmod = isSDR2HDR(imageDescription->value(), m_renderData.pMonitor->m_imageDescription->value()); - const bool needsHDRmod = !needsSDRmod && isHDR2SDR(imageDescription->value(), m_renderData.pMonitor->m_imageDescription->value()); - const float maxLuminance = needsHDRmod ? - imageDescription->value().getTFMaxLuminance(-1) : - (imageDescription->value().luminances.max > 0 ? imageDescription->value().luminances.max : imageDescription->value().luminances.reference); - const auto dstMaxLuminance = - m_renderData.pMonitor->m_imageDescription->value().luminances.max > 0 ? m_renderData.pMonitor->m_imageDescription->value().luminances.max : 10000; + const bool needsSDRmod = isSDR2HDR(imageDescription->value(), targetImageDescription->value()); + const bool needsHDRmod = !needsSDRmod && isHDR2SDR(imageDescription->value(), targetImageDescription->value()); + const float maxLuminance = needsHDRmod ? + imageDescription->value().getTFMaxLuminance(-1) : + (imageDescription->value().luminances.max > 0 ? imageDescription->value().luminances.max : imageDescription->value().luminances.reference); + const auto dstMaxLuminance = targetImageDescription->value().luminances.max > 0 ? targetImageDescription->value().luminances.max : 10000; if (maxLuminance >= dstMaxLuminance * 1.01) shaderFeatures |= SH_FEAT_TONEMAP; if (!data.cmBackToSRGB && (imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_SRGB || imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_GAMMA22) && - m_renderData.pMonitor->m_imageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ && + targetImageDescription->value().transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ && ((m_renderData.pMonitor->m_sdrSaturation > 0 && m_renderData.pMonitor->m_sdrSaturation != 1.0f) || (m_renderData.pMonitor->m_sdrBrightness > 0 && m_renderData.pMonitor->m_sdrBrightness != 1.0f))) shaderFeatures |= SH_FEAT_SDR_MOD; @@ -1427,11 +1431,9 @@ void CHyprOpenGLImpl::renderTextureInternal(SP tex, const CBox& box, c shader = useShader(shader); if (!skipCM && !usingFinalShader) { - if (data.cmBackToSRGB) { - static auto PSDREOTF = CConfigValue("render:cm_sdr_eotf"); - auto chosenSdrEotf = *PSDREOTF != 3 ? NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22 : NColorManagement::CM_TRANSFER_FUNCTION_SRGB; - passCMUniforms(shader, imageDescription, CImageDescription::from(NColorManagement::SImageDescription{.transferFunction = chosenSdrEotf}), true, -1, -1); - } else + if (data.cmBackToSRGB) + passCMUniforms(shader, imageDescription, targetImageDescription, true, -1, -1); + else passCMUniforms(shader, imageDescription); }