From 49974d5e34292ede24351c8638fe060b382bbda0 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Tue, 29 Apr 2025 22:29:40 +0300 Subject: [PATCH] cm: Use precomputed primaries conversion (#9814) --- src/protocols/ColorManagement.cpp | 22 ++-- src/protocols/types/ColorManagement.cpp | 28 ++++- src/protocols/types/ColorManagement.hpp | 62 ++++++++--- src/render/OpenGL.cpp | 31 ++++-- src/render/Shader.hpp | 4 +- src/render/shaders/glsl/CM.frag | 3 +- src/render/shaders/glsl/CM.glsl | 128 +++++++++-------------- src/render/shaders/glsl/blurprepare.frag | 16 +-- src/render/shaders/glsl/border.frag | 3 +- src/render/shaders/glsl/shadow.frag | 3 +- 10 files changed, 164 insertions(+), 136 deletions(-) diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index 91dc0eac9..29d9d2487 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -8,8 +8,6 @@ using namespace NColorManagement; -static uint64_t lastImageID = 0; // FIXME use for deduplication - CColorManager::CColorManager(SP resource) : m_resource(resource) { if UNLIKELY (!good()) return; @@ -191,14 +189,13 @@ CColorManager::CColorManager(SP resource) : m_resource(resour } RESOURCE->self = RESOURCE; - RESOURCE->settings.id = ++lastImageID; RESOURCE->settings.windowsScRGB = true; RESOURCE->settings.primariesNamed = NColorManagement::CM_PRIMARIES_SRGB; RESOURCE->settings.primariesNameSet = true; RESOURCE->settings.primaries = NColorPrimaries::BT709; RESOURCE->settings.transferFunction = NColorManagement::CM_TRANSFER_FUNCTION_EXT_LINEAR; RESOURCE->settings.luminances.reference = 203; - RESOURCE->resource()->sendReady(RESOURCE->settings.id); + RESOURCE->resource()->sendReady(RESOURCE->settings.updateId()); }); m_resource->setOnDestroy([this](CWpColorManagerV1* r) { PROTO::colorManagement->destroyResource(this); }); @@ -239,9 +236,7 @@ CColorManagementOutput::CColorManagementOutput(SP re RESOURCE->m_resource->sendFailed(WP_IMAGE_DESCRIPTION_V1_CAUSE_NO_OUTPUT, "No output"); else { RESOURCE->settings = m_monitor->imageDescription; - if (RESOURCE->settings.id) - RESOURCE->settings.id = ++lastImageID; - RESOURCE->m_resource->sendReady(RESOURCE->settings.id); // FIXME: create correct id + RESOURCE->m_resource->sendReady(RESOURCE->settings.updateId()); } }); } @@ -383,10 +378,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPsettings = g_pCompositor->getPreferredImageDescription(); - if (!m_currentPreferred->settings.id) - m_currentPreferred->settings.id = ++lastImageID; - - RESOURCE->resource()->sendReady(++lastImageID); // FIXME: create correct id + RESOURCE->resource()->sendReady(m_currentPreferred->settings.updateId()); }); m_resource->setGetPreferredParametric([this](CWpColorManagementSurfaceFeedbackV1* r, uint32_t id) { @@ -419,7 +411,7 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPresource()->sendReady(++lastImageID); // FIXME: create correct id + RESOURCE->resource()->sendReady(m_currentPreferred->settings.updateId()); }); } @@ -467,8 +459,7 @@ CColorManagementIccCreator::CColorManagementIccCreator(SPself = RESOURCE; RESOURCE->settings = settings; - settings.id = ++lastImageID; - RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id + RESOURCE->resource()->sendReady(settings.updateId()); PROTO::colorManagement->destroyResource(this); }); @@ -522,8 +513,7 @@ CColorManagementParametricCreator::CColorManagementParametricCreator(SPself = RESOURCE; RESOURCE->settings = settings; - settings.id = ++lastImageID; - RESOURCE->resource()->sendReady(settings.id); // FIXME: create correct id + RESOURCE->resource()->sendReady(settings.updateId()); PROTO::colorManagement->destroyResource(this); }); diff --git a/src/protocols/types/ColorManagement.cpp b/src/protocols/types/ColorManagement.cpp index 9daff1e2f..e6b470d0a 100644 --- a/src/protocols/types/ColorManagement.cpp +++ b/src/protocols/types/ColorManagement.cpp @@ -1,7 +1,11 @@ #include "ColorManagement.hpp" +#include namespace NColorManagement { - const SPCPRimaries& getPrimaries(ePrimaries name) { + static uint32_t lastImageID = 0; + static std::map knownDescriptionIds; // expected to be small + + const SPCPRimaries& getPrimaries(ePrimaries name) { switch (name) { case CM_PRIMARIES_SRGB: return NColorPrimaries::BT709; case CM_PRIMARIES_BT2020: return NColorPrimaries::BT2020; @@ -17,4 +21,26 @@ namespace NColorManagement { } } + // TODO make image descriptions immutable and always set an id + + uint32_t SImageDescription::findId() const { + for (auto it = knownDescriptionIds.begin(); it != knownDescriptionIds.end(); ++it) { + if (it->second == *this) + return it->first; + } + + const auto newId = ++lastImageID; + knownDescriptionIds.insert(std::make_pair(newId, *this)); + return newId; + } + + uint32_t SImageDescription::getId() const { + return id > 0 ? id : findId(); + } + + uint32_t SImageDescription::updateId() { + id = 0; + id = findId(); + return id; + } } \ No newline at end of file diff --git a/src/protocols/types/ColorManagement.hpp b/src/protocols/types/ColorManagement.hpp index 143f47ca7..48d8dd31b 100644 --- a/src/protocols/types/ColorManagement.hpp +++ b/src/protocols/types/ColorManagement.hpp @@ -1,6 +1,13 @@ #pragma once #include "color-management-v1.hpp" +#include + +#define SDR_MIN_LUMINANCE 0.2 +#define SDR_MAX_LUMINANCE 80.0 +#define HDR_MIN_LUMINANCE 0.005 +#define HDR_MAX_LUMINANCE 10000.0 +#define HLG_MAX_LUMINANCE 1000.0 namespace NColorManagement { enum ePrimaries : uint8_t { @@ -47,19 +54,7 @@ namespace NColorManagement { return (eTransferFunction)tf; } - struct SPCPRimaries { - struct xy { //NOLINT(readability-identifier-naming) - float x = 0; - float y = 0; - - bool operator==(const xy& p2) const { - return x == p2.x && y == p2.y; - } - } red, green, blue, white; - bool operator==(const SPCPRimaries& p2) const { - return red == p2.red && green == p2.green && blue == p2.blue && white == p2.white; - } - }; + typedef Hyprgraphics::SPCPRimaries SPCPRimaries; namespace NColorPrimaries { static const auto DEFAULT_PRIMARIES = SPCPRimaries{}; @@ -185,5 +180,46 @@ namespace NColorManagement { return NColorManagement::getPrimaries(primariesNamed); return primaries; } + + float getTFMinLuminance() const { + switch (transferFunction) { + case CM_TRANSFER_FUNCTION_EXT_LINEAR: return 0; + case CM_TRANSFER_FUNCTION_ST2084_PQ: + case CM_TRANSFER_FUNCTION_HLG: return HDR_MIN_LUMINANCE; + case CM_TRANSFER_FUNCTION_GAMMA22: + case CM_TRANSFER_FUNCTION_GAMMA28: + case CM_TRANSFER_FUNCTION_BT1886: + case CM_TRANSFER_FUNCTION_ST240: + case CM_TRANSFER_FUNCTION_LOG_100: + case CM_TRANSFER_FUNCTION_LOG_316: + case CM_TRANSFER_FUNCTION_XVYCC: + case CM_TRANSFER_FUNCTION_EXT_SRGB: + case CM_TRANSFER_FUNCTION_ST428: + case CM_TRANSFER_FUNCTION_SRGB: + default: return SDR_MIN_LUMINANCE; + } + }; + + float getTFMaxLuminance() const { + switch (transferFunction) { + case CM_TRANSFER_FUNCTION_ST2084_PQ: return HDR_MAX_LUMINANCE; + case CM_TRANSFER_FUNCTION_HLG: return HLG_MAX_LUMINANCE; + case CM_TRANSFER_FUNCTION_GAMMA22: + case CM_TRANSFER_FUNCTION_GAMMA28: + case CM_TRANSFER_FUNCTION_BT1886: + case CM_TRANSFER_FUNCTION_ST240: + case CM_TRANSFER_FUNCTION_LOG_100: + case CM_TRANSFER_FUNCTION_LOG_316: + case CM_TRANSFER_FUNCTION_XVYCC: + case CM_TRANSFER_FUNCTION_EXT_SRGB: + case CM_TRANSFER_FUNCTION_ST428: + case CM_TRANSFER_FUNCTION_SRGB: + default: return SDR_MAX_LUMINANCE; + } + }; + + uint32_t findId() const; + uint32_t getId() const; + uint32_t updateId(); }; } \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a6ddb5198..a6cc176a5 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -908,13 +910,15 @@ static void getCMShaderUniforms(CShader& shader) { shader.skipCM = glGetUniformLocation(shader.program, "skipCM"); shader.sourceTF = glGetUniformLocation(shader.program, "sourceTF"); shader.targetTF = glGetUniformLocation(shader.program, "targetTF"); - shader.sourcePrimaries = glGetUniformLocation(shader.program, "sourcePrimaries"); + shader.srcTFRange = glGetUniformLocation(shader.program, "srcTFRange"); + shader.dstTFRange = glGetUniformLocation(shader.program, "dstTFRange"); shader.targetPrimaries = glGetUniformLocation(shader.program, "targetPrimaries"); shader.maxLuminance = glGetUniformLocation(shader.program, "maxLuminance"); shader.dstMaxLuminance = glGetUniformLocation(shader.program, "dstMaxLuminance"); shader.dstRefLuminance = glGetUniformLocation(shader.program, "dstRefLuminance"); shader.sdrSaturation = glGetUniformLocation(shader.program, "sdrSaturation"); shader.sdrBrightness = glGetUniformLocation(shader.program, "sdrBrightnessMultiplier"); + shader.convertMatrix = glGetUniformLocation(shader.program, "convertMatrix"); } // shader has #include "rounding.glsl" @@ -1437,27 +1441,26 @@ void CHyprOpenGLImpl::renderTextureWithDamage(SP tex, const CBox& box, scissor(nullptr); } +static std::map, std::array> primariesConversionCache; + void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription, bool modifySDR) { glUniform1i(shader.sourceTF, imageDescription.transferFunction); glUniform1i(shader.targetTF, targetImageDescription.transferFunction); - const auto sourcePrimaries = - imageDescription.primariesNameSet || imageDescription.primaries == SPCPRimaries{} ? getPrimaries(imageDescription.primariesNamed) : imageDescription.primaries; + const auto targetPrimaries = targetImageDescription.primariesNameSet || targetImageDescription.primaries == SPCPRimaries{} ? getPrimaries(targetImageDescription.primariesNamed) : targetImageDescription.primaries; - const GLfloat glSourcePrimaries[8] = { - sourcePrimaries.red.x, sourcePrimaries.red.y, sourcePrimaries.green.x, sourcePrimaries.green.y, - sourcePrimaries.blue.x, sourcePrimaries.blue.y, sourcePrimaries.white.x, sourcePrimaries.white.y, - }; const GLfloat glTargetPrimaries[8] = { targetPrimaries.red.x, targetPrimaries.red.y, targetPrimaries.green.x, targetPrimaries.green.y, targetPrimaries.blue.x, targetPrimaries.blue.y, targetPrimaries.white.x, targetPrimaries.white.y, }; - glUniformMatrix4x2fv(shader.sourcePrimaries, 1, false, glSourcePrimaries); glUniformMatrix4x2fv(shader.targetPrimaries, 1, false, glTargetPrimaries); + glUniform2f(shader.srcTFRange, imageDescription.getTFMinLuminance(), imageDescription.getTFMaxLuminance()); + glUniform2f(shader.dstTFRange, targetImageDescription.getTFMinLuminance(), targetImageDescription.getTFMaxLuminance()); + const float maxLuminance = imageDescription.luminances.max > 0 ? imageDescription.luminances.max : imageDescription.luminances.reference; glUniform1f(shader.maxLuminance, maxLuminance * targetImageDescription.luminances.reference / imageDescription.luminances.reference); glUniform1f(shader.dstMaxLuminance, targetImageDescription.luminances.max > 0 ? targetImageDescription.luminances.max : 10000); @@ -1469,7 +1472,19 @@ void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const NColorManageme glUniform1f(shader.sdrBrightness, modifySDR && m_RenderData.pMonitor->sdrBrightness > 0 && targetImageDescription.transferFunction == NColorManagement::CM_TRANSFER_FUNCTION_ST2084_PQ ? m_RenderData.pMonitor->sdrBrightness : + 1.0f); + const auto cacheKey = std::make_pair(imageDescription.getId(), targetImageDescription.getId()); + if (!primariesConversionCache.contains(cacheKey)) { + const auto mat = imageDescription.getPrimaries().convertMatrix(targetImageDescription.getPrimaries()).mat(); + const std::array glConvertMatrix = { + mat[0][0], mat[1][0], mat[2][0], // + mat[0][1], mat[1][1], mat[2][1], // + mat[0][2], mat[1][2], mat[2][2], // + }; + primariesConversionCache.insert(std::make_pair(cacheKey, glConvertMatrix)); + } + glUniformMatrix3fv(shader.convertMatrix, 1, false, &primariesConversionCache[cacheKey][0]); } void CHyprOpenGLImpl::passCMUniforms(const CShader& shader, const SImageDescription& imageDescription) { diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 1d21894c4..cd9b6f225 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -15,13 +15,15 @@ class CShader { GLint skipCM = -1; GLint sourceTF = -1; GLint targetTF = -1; - GLint sourcePrimaries = -1; + GLint srcTFRange = -1; + GLint dstTFRange = -1; GLint targetPrimaries = -1; GLint maxLuminance = -1; GLint dstMaxLuminance = -1; GLint dstRefLuminance = -1; GLint sdrSaturation = -1; // sdr -> hdr saturation GLint sdrBrightness = -1; // sdr -> hdr brightness multiplier + GLint convertMatrix = -1; GLint tex = -1; GLint alpha = -1; GLint posAttrib = -1; diff --git a/src/render/shaders/glsl/CM.frag b/src/render/shaders/glsl/CM.frag index 369e9cf0f..031fe7f32 100644 --- a/src/render/shaders/glsl/CM.frag +++ b/src/render/shaders/glsl/CM.frag @@ -11,7 +11,6 @@ uniform int texType; // eTextureType: 0 - rgba, 1 - rgbx, 2 - ext // uniform int skipCM; uniform int sourceTF; // eTransferFunction uniform int targetTF; // eTransferFunction -uniform mat4x2 sourcePrimaries; uniform mat4x2 targetPrimaries; uniform float alpha; @@ -43,7 +42,7 @@ void main() { discard; // this shader shouldn't be used when skipCM == 1 - pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries); + pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); if (applyTint == 1) pixColor = vec4(pixColor.rgb * tint.rgb, pixColor[3]); diff --git a/src/render/shaders/glsl/CM.glsl b/src/render/shaders/glsl/CM.glsl index 4cf2745c2..8c505ee59 100644 --- a/src/render/shaders/glsl/CM.glsl +++ b/src/render/shaders/glsl/CM.glsl @@ -1,8 +1,12 @@ +uniform vec2 srcTFRange; +uniform vec2 dstTFRange; + uniform float maxLuminance; uniform float dstMaxLuminance; uniform float dstRefLuminance; uniform float sdrSaturation; uniform float sdrBrightnessMultiplier; +uniform mat3 convertMatrix; //enum eTransferFunction #define CM_TRANSFER_FUNCTION_BT1886 1 @@ -117,30 +121,8 @@ vec4 toLinear(vec4 color, int tf) { return color; } -vec4 toNit(vec4 color, int tf) { - if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR) - color.rgb = color.rgb * SDR_MAX_LUMINANCE; - else { - - switch (tf) { - case CM_TRANSFER_FUNCTION_ST2084_PQ: - color.rgb = color.rgb * (HDR_MAX_LUMINANCE - HDR_MIN_LUMINANCE) + HDR_MIN_LUMINANCE; break; - case CM_TRANSFER_FUNCTION_HLG: - color.rgb = color.rgb * (HLG_MAX_LUMINANCE - HDR_MIN_LUMINANCE) + HDR_MIN_LUMINANCE; break; - case CM_TRANSFER_FUNCTION_GAMMA22: - case CM_TRANSFER_FUNCTION_GAMMA28: - case CM_TRANSFER_FUNCTION_BT1886: - case CM_TRANSFER_FUNCTION_ST240: - case CM_TRANSFER_FUNCTION_LOG_100: - case CM_TRANSFER_FUNCTION_LOG_316: - case CM_TRANSFER_FUNCTION_XVYCC: - case CM_TRANSFER_FUNCTION_EXT_SRGB: - case CM_TRANSFER_FUNCTION_ST428: - case CM_TRANSFER_FUNCTION_SRGB: - default: - color.rgb = color.rgb * (SDR_MAX_LUMINANCE - SDR_MIN_LUMINANCE) + SDR_MIN_LUMINANCE; break; - } - } +vec4 toNit(vec4 color, vec2 range) { + color.rgb = color.rgb * (range[1] - range[0]) + range[0]; return color; } @@ -195,33 +177,13 @@ vec4 fromLinear(vec4 color, int tf) { return color; } -vec4 fromLinearNit(vec4 color, int tf) { +vec4 fromLinearNit(vec4 color, int tf, vec2 range) { if (tf == CM_TRANSFER_FUNCTION_EXT_LINEAR) color.rgb = color.rgb / SDR_MAX_LUMINANCE; else { color.rgb /= max(color.a, 0.001); - - switch (tf) { - case CM_TRANSFER_FUNCTION_ST2084_PQ: - color.rgb = (color.rgb - HDR_MIN_LUMINANCE) / (HDR_MAX_LUMINANCE - HDR_MIN_LUMINANCE); break; - case CM_TRANSFER_FUNCTION_HLG: - color.rgb = (color.rgb - HDR_MIN_LUMINANCE) / (HLG_MAX_LUMINANCE - HDR_MIN_LUMINANCE); break; - case CM_TRANSFER_FUNCTION_GAMMA22: - case CM_TRANSFER_FUNCTION_GAMMA28: - case CM_TRANSFER_FUNCTION_BT1886: - case CM_TRANSFER_FUNCTION_ST240: - case CM_TRANSFER_FUNCTION_LOG_100: - case CM_TRANSFER_FUNCTION_LOG_316: - case CM_TRANSFER_FUNCTION_XVYCC: - case CM_TRANSFER_FUNCTION_EXT_SRGB: - case CM_TRANSFER_FUNCTION_ST428: - case CM_TRANSFER_FUNCTION_SRGB: - default: - color.rgb = (color.rgb - SDR_MIN_LUMINANCE) / (SDR_MAX_LUMINANCE - SDR_MIN_LUMINANCE); break; - } - + color.rgb = (color.rgb - range[0]) / (range[1] - range[0]); color.rgb = fromLinearRGB(color.rgb, tf); - color.rgb *= color.a; } return color; @@ -250,13 +212,6 @@ mat3 primaries2xyz(mat4x2 primaries) { ); } -// const vec2 D65 = vec2(0.3127, 0.3290); -const mat3 Bradford = mat3( - 0.8951, 0.2664, -0.1614, - -0.7502, 1.7135, 0.0367, - 0.0389, -0.0685, 1.0296 -); -const mat3 BradfordInv = inverse(Bradford); mat3 adaptWhite(vec2 src, vec2 dst) { if (src == dst) @@ -266,6 +221,13 @@ mat3 adaptWhite(vec2 src, vec2 dst) { 0.0, 0.0, 1.0 ); + // const vec2 D65 = vec2(0.3127, 0.3290); + const mat3 Bradford = mat3( + 0.8951, 0.2664, -0.1614, + -0.7502, 1.7135, 0.0367, + 0.0389, -0.0685, 1.0296 + ); + mat3 BradfordInv = inverse(Bradford); vec3 srcXYZ = xy2xyz(src); vec3 dstXYZ = xy2xyz(dst); vec3 factors = (Bradford * dstXYZ) / (Bradford * srcXYZ); @@ -287,21 +249,37 @@ const mat3 BT2020toLMS = mat3( -0.1922, 1.1004, 0.0755, 0.0070, 0.0749, 0.8434 ); -const mat3 LMStoBT2020 = inverse(BT2020toLMS); +//const mat3 LMStoBT2020 = inverse(BT2020toLMS); +const mat3 LMStoBT2020 = mat3( + 2.0701800566956135096, -1.3264568761030210255, 0.20661600684785517081, + 0.36498825003265747974, 0.68046736285223514102, -0.045421753075853231409, + -0.049595542238932107896, -0.049421161186757487412, 1.1879959417328034394 +); -const mat3 ICtCpPQ = transpose(mat3( - 2048.0, 2048.0, 0.0, - 6610.0, -13613.0, 7003.0, - 17933.0, -17390.0, -543.0 -) / 4096.0); -const mat3 ICtCpPQInv = inverse(ICtCpPQ); +// const mat3 ICtCpPQ = transpose(mat3( +// 2048.0, 2048.0, 0.0, +// 6610.0, -13613.0, 7003.0, +// 17933.0, -17390.0, -543.0 +// ) / 4096.0); +const mat3 ICtCpPQ = mat3( + 0.5, 1.61376953125, 4.378173828125, + 0.5, -3.323486328125, -4.24560546875, + 0.0, 1.709716796875, -0.132568359375 +); +//const mat3 ICtCpPQInv = inverse(ICtCpPQ); +const mat3 ICtCpPQInv = mat3( + 1.0, 1.0, 1.0, + 0.0086090370379327566, -0.0086090370379327566, 0.560031335710679118, + 0.11102962500302595656, -0.11102962500302595656, -0.32062717498731885185 +); -const mat3 ICtCpHLG = transpose(mat3( - 2048.0, 2048.0, 0.0, - 3625.0, -7465.0, 3840.0, - 9500.0, -9212.0, -288.0 -) / 4096.0); -const mat3 ICtCpHLGInv = inverse(ICtCpHLG); +// unused for now +// const mat3 ICtCpHLG = transpose(mat3( +// 2048.0, 2048.0, 0.0, +// 3625.0, -7465.0, 3840.0, +// 9500.0, -9212.0, -288.0 +// ) / 4096.0); +// const mat3 ICtCpHLGInv = inverse(ICtCpHLG); vec4 tonemap(vec4 color, mat3 dstXYZ) { if (maxLuminance < dstMaxLuminance * 1.01) @@ -339,23 +317,17 @@ vec4 tonemap(vec4 color, mat3 dstXYZ) { return vec4(fromLMS * toLinear(vec4(ICtCpPQInv * ICtCp, 1.0), CM_TRANSFER_FUNCTION_ST2084_PQ).rgb * HDR_MAX_LUMINANCE, color[3]); } -vec4 doColorManagement(vec4 pixColor, int srcTF, mat4x2 srcPrimaries, int dstTF, mat4x2 dstPrimaries) { +vec4 doColorManagement(vec4 pixColor, int srcTF, int dstTF, mat4x2 dstPrimaries) { pixColor.rgb /= max(pixColor.a, 0.001); pixColor.rgb = toLinearRGB(pixColor.rgb, srcTF); - mat3 srcxyz = primaries2xyz(srcPrimaries); - mat3 dstxyz; - if (srcPrimaries == dstPrimaries) - dstxyz = srcxyz; - else { - dstxyz = primaries2xyz(dstPrimaries); - pixColor = convertPrimaries(pixColor, srcxyz, srcPrimaries[3], dstxyz, dstPrimaries[3]); - } - pixColor = toNit(pixColor, srcTF); + pixColor.rgb = convertMatrix * pixColor.rgb; + pixColor = toNit(pixColor, srcTFRange); pixColor.rgb *= pixColor.a; + mat3 dstxyz = primaries2xyz(dstPrimaries); pixColor = tonemap(pixColor, dstxyz); - pixColor = fromLinearNit(pixColor, dstTF); + pixColor = fromLinearNit(pixColor, dstTF, dstTFRange); if (srcTF == CM_TRANSFER_FUNCTION_SRGB && dstTF == CM_TRANSFER_FUNCTION_ST2084_PQ) { - pixColor = saturate(pixColor, srcxyz, sdrSaturation); + pixColor = saturate(pixColor, dstxyz, sdrSaturation); pixColor.rgb /= pixColor.a; pixColor.rgb *= sdrBrightnessMultiplier; pixColor.rgb *= pixColor.a; diff --git a/src/render/shaders/glsl/blurprepare.frag b/src/render/shaders/glsl/blurprepare.frag index 0be2d53ac..548289c30 100644 --- a/src/render/shaders/glsl/blurprepare.frag +++ b/src/render/shaders/glsl/blurprepare.frag @@ -11,8 +11,6 @@ uniform float brightness; uniform int skipCM; uniform int sourceTF; // eTransferFunction uniform int targetTF; // eTransferFunction -uniform mat4x2 sourcePrimaries; -uniform mat4x2 targetPrimaries; #include "CM.glsl" @@ -29,17 +27,9 @@ void main() { if (sourceTF == CM_TRANSFER_FUNCTION_ST2084_PQ) { pixColor.rgb /= sdrBrightnessMultiplier; } - pixColor.rgb = toLinearRGB(pixColor.rgb, sourceTF); - mat3 srcxyz = primaries2xyz(sourcePrimaries); - mat3 dstxyz; - if (sourcePrimaries == targetPrimaries) - dstxyz = srcxyz; - else { - dstxyz = primaries2xyz(targetPrimaries); - pixColor = convertPrimaries(pixColor, srcxyz, sourcePrimaries[3], dstxyz, targetPrimaries[3]); - } - pixColor = toNit(pixColor, sourceTF); - pixColor = fromLinearNit(pixColor, targetTF); + pixColor.rgb = convertMatrix * toLinearRGB(pixColor.rgb, sourceTF); + pixColor = toNit(pixColor, srcTFRange); + pixColor = fromLinearNit(pixColor, targetTF, dstTFRange); } // contrast diff --git a/src/render/shaders/glsl/border.frag b/src/render/shaders/glsl/border.frag index 68541e145..38ae24c0e 100644 --- a/src/render/shaders/glsl/border.frag +++ b/src/render/shaders/glsl/border.frag @@ -7,7 +7,6 @@ in vec2 v_texcoord; uniform int skipCM; uniform int sourceTF; // eTransferFunction uniform int targetTF; // eTransferFunction -uniform mat4x2 sourcePrimaries; uniform mat4x2 targetPrimaries; uniform vec2 fullSizeUntransformed; @@ -175,7 +174,7 @@ void main() { pixColor.rgb *= pixColor[3]; if (skipCM == 0) - pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries); + pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); pixColor *= alpha * additionalAlpha; diff --git a/src/render/shaders/glsl/shadow.frag b/src/render/shaders/glsl/shadow.frag index 7a930f965..b6fdf6ee0 100644 --- a/src/render/shaders/glsl/shadow.frag +++ b/src/render/shaders/glsl/shadow.frag @@ -8,7 +8,6 @@ in vec2 v_texcoord; uniform int skipCM; uniform int sourceTF; // eTransferFunction uniform int targetTF; // eTransferFunction -uniform mat4x2 sourcePrimaries; uniform mat4x2 targetPrimaries; uniform vec2 topLeft; @@ -94,7 +93,7 @@ void main() { pixColor.rgb *= pixColor[3]; if (skipCM == 0) - pixColor = doColorManagement(pixColor, sourceTF, sourcePrimaries, targetTF, targetPrimaries); + pixColor = doColorManagement(pixColor, sourceTF, targetTF, targetPrimaries); fragColor = pixColor; } \ No newline at end of file