summaryrefslogtreecommitdiff
path: root/libs/shaders/shaders.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/shaders/shaders.cpp')
-rw-r--r--libs/shaders/shaders.cpp510
1 files changed, 159 insertions, 351 deletions
diff --git a/libs/shaders/shaders.cpp b/libs/shaders/shaders.cpp
index f80e93f6f8..c85517a976 100644
--- a/libs/shaders/shaders.cpp
+++ b/libs/shaders/shaders.cpp
@@ -33,212 +33,111 @@ aidl::android::hardware::graphics::common::Dataspace toAidlDataspace(ui::Dataspa
return static_cast<aidl::android::hardware::graphics::common::Dataspace>(dataspace);
}
-void generateEOTF(ui::Dataspace dataspace, std::string& shader) {
- switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
- shader.append(R"(
-
- float3 EOTF(float3 color) {
- float m1 = (2610.0 / 4096.0) / 4.0;
- float m2 = (2523.0 / 4096.0) * 128.0;
- float c1 = (3424.0 / 4096.0);
- float c2 = (2413.0 / 4096.0) * 32.0;
- float c3 = (2392.0 / 4096.0) * 32.0;
-
- float3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / float3(m2));
- tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
- return pow(tmp, 1.0 / float3(m1));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_HLG:
- shader.append(R"(
- float EOTF_channel(float channel) {
- const float a = 0.17883277;
- const float b = 0.28466892;
- const float c = 0.55991073;
- return channel <= 0.5 ? channel * channel / 3.0 :
- (exp((channel - c) / a) + b) / 12.0;
- }
-
- float3 EOTF(float3 color) {
- return float3(EOTF_channel(color.r), EOTF_channel(color.g),
- EOTF_channel(color.b));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_LINEAR:
- shader.append(R"(
- float3 EOTF(float3 color) {
- return color;
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_SMPTE_170M:
- shader.append(R"(
-
- float EOTF_sRGB(float srgb) {
- return srgb <= 0.08125 ? srgb / 4.50 : pow((srgb + 0.099) / 1.099, 1 / 0.45);
- }
-
- float3 EOTF_sRGB(float3 srgb) {
- return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
- }
-
- float3 EOTF(float3 srgb) {
- return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_2:
- shader.append(R"(
+void generateXYZTransforms(std::string& shader) {
+ shader.append(R"(
+ uniform float3x3 in_rgbToXyz;
+ uniform float3x3 in_xyzToSrcRgb;
+ uniform float4x4 in_colorTransform;
+ float3 ToXYZ(float3 rgb) {
+ return in_rgbToXyz * rgb;
+ }
- float EOTF_sRGB(float srgb) {
- return pow(srgb, 2.2);
- }
+ float3 ToSrcRGB(float3 xyz) {
+ return in_xyzToSrcRgb * xyz;
+ }
- float3 EOTF_sRGB(float3 srgb) {
- return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
- }
+ float3 ApplyColorTransform(float3 rgb) {
+ return (in_colorTransform * float4(rgb, 1.0)).rgb;
+ }
+ )");
+}
- float3 EOTF(float3 srgb) {
- return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_6:
+// Conversion from relative light to absolute light
+// Note that 1.0 == 203 nits.
+void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, std::string& shader) {
+ switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_HLG:
+ // BT. 2408 says that a signal level of 0.75 == 203 nits for HLG, but that's after
+ // applying OOTF. But we haven't applied OOTF yet, so we need to scale by a different
+ // constant instead.
shader.append(R"(
-
- float EOTF_sRGB(float srgb) {
- return pow(srgb, 2.6);
- }
-
- float3 EOTF_sRGB(float3 srgb) {
- return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
- }
-
- float3 EOTF(float3 srgb) {
- return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * 264.96;
}
)");
break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_8:
- shader.append(R"(
-
- float EOTF_sRGB(float srgb) {
- return pow(srgb, 2.8);
- }
-
- float3 EOTF_sRGB(float3 srgb) {
- return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
- }
-
- float3 EOTF(float3 srgb) {
- return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_SRGB:
default:
shader.append(R"(
-
- float EOTF_sRGB(float srgb) {
- return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
- }
-
- float3 EOTF_sRGB(float3 srgb) {
- return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
- }
-
- float3 EOTF(float3 srgb) {
- return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * 203.0;
}
)");
break;
}
}
-void generateXYZTransforms(std::string& shader) {
- shader.append(R"(
- uniform float4x4 in_rgbToXyz;
- uniform float4x4 in_xyzToRgb;
- float3 ToXYZ(float3 rgb) {
- return (in_rgbToXyz * float4(rgb, 1.0)).rgb;
- }
-
- float3 ToRGB(float3 xyz) {
- return clamp((in_xyzToRgb * float4(xyz, 1.0)).rgb, 0.0, 1.0);
- }
- )");
-}
-
-// Conversion from relative light to absolute light (maps from [0, 1] to [0, maxNits])
-void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
- std::string& shader) {
- switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+// Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1])
+static void generateLuminanceNormalizationForOOTF(ui::Dataspace inputDataspace,
+ ui::Dataspace outputDataspace,
+ std::string& shader) {
+ switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * 10000.0;
- }
- )");
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / 203.0;
+ }
+ )");
break;
case HAL_DATASPACE_TRANSFER_HLG:
- shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * 1000.0;
- }
- )");
- break;
- default:
- switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
+ switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_HLG:
- // SDR -> HDR tonemap
shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * in_libtonemap_inputMaxLuminance;
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / 264.96;
}
)");
break;
default:
- // Input and output are both SDR, so no tone-mapping is expected so
- // no-op the luminance normalization.
+ // Transcoding to HLG requires applying the inverse OOTF
+ // with the expectation that the OOTF is then applied during
+ // tonemapping downstream.
+ // BT. 2100-2 operates on normalized luminances, so renormalize to the input to
+ // correctly adjust gamma.
+ // Note that following BT. 2408 for HLG OETF actually maps 0.75 == ~264.96 nits,
+ // rather than 203 nits, because 203 nits == OOTF(invOETF(0.75)), so even though
+ // we originally scaled by 203 nits we need to re-normalize to 264.96 nits when
+ // converting to the correct brightness range.
shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * in_libtonemap_displayMaxLuminance;
- }
- )");
+ float3 NormalizeLuminance(float3 xyz) {
+ float ootfGain = pow(xyz.y / 1000.0, -0.2 / 1.2);
+ return xyz * ootfGain / 264.96;
+ }
+ )");
break;
}
- }
-}
-
-// Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1])
-static void generateLuminanceNormalizationForOOTF(ui::Dataspace outputDataspace,
- std::string& shader) {
- switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
- shader.append(R"(
- float3 NormalizeLuminance(float3 xyz) {
- return xyz / 10000.0;
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_HLG:
- shader.append(R"(
- float3 NormalizeLuminance(float3 xyz) {
- return xyz / 1000.0;
- }
- )");
break;
default:
- shader.append(R"(
- float3 NormalizeLuminance(float3 xyz) {
- return xyz / in_libtonemap_displayMaxLuminance;
- }
- )");
- break;
+ switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_HLG:
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ // libtonemap outputs a range [0, in_libtonemap_displayMaxLuminance], so
+ // normalize back to [0, 1] when the output is SDR.
+ shader.append(R"(
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / in_libtonemap_displayMaxLuminance;
+ }
+ )");
+ break;
+ default:
+ // Otherwise normalize back down to the range [0, 1]
+ // TODO: get this working for extended range outputs
+ shader.append(R"(
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / 203.0;
+ }
+ )");
+ break;
+ }
}
}
@@ -249,159 +148,67 @@ void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
toAidlDataspace(outputDataspace))
.c_str());
- generateLuminanceScalesForOOTF(inputDataspace, outputDataspace, shader);
- generateLuminanceNormalizationForOOTF(outputDataspace, shader);
+ generateLuminanceScalesForOOTF(inputDataspace, shader);
+ generateLuminanceNormalizationForOOTF(inputDataspace, outputDataspace, shader);
+ // Some tonemappers operate on CIE luminance, other tonemappers operate on linear rgb
+ // luminance in the source gamut.
shader.append(R"(
- float3 OOTF(float3 linearRGB, float3 xyz) {
+ float3 OOTF(float3 linearRGB) {
float3 scaledLinearRGB = ScaleLuminance(linearRGB);
- float3 scaledXYZ = ScaleLuminance(xyz);
+ float3 scaledXYZ = ToXYZ(scaledLinearRGB);
- float gain = libtonemap_LookupTonemapGain(scaledLinearRGB, scaledXYZ);
+ float gain = libtonemap_LookupTonemapGain(ToSrcRGB(scaledXYZ), scaledXYZ);
return NormalizeLuminance(scaledXYZ * gain);
}
)");
}
-void generateOETF(ui::Dataspace dataspace, std::string& shader) {
- switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
- shader.append(R"(
-
- float3 OETF(float3 xyz) {
- float m1 = (2610.0 / 4096.0) / 4.0;
- float m2 = (2523.0 / 4096.0) * 128.0;
- float c1 = (3424.0 / 4096.0);
- float c2 = (2413.0 / 4096.0) * 32.0;
- float c3 = (2392.0 / 4096.0) * 32.0;
-
- float3 tmp = pow(xyz, float3(m1));
- tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
- return pow(tmp, float3(m2));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_HLG:
- shader.append(R"(
- float OETF_channel(float channel) {
- const float a = 0.17883277;
- const float b = 0.28466892;
- const float c = 0.55991073;
- return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) :
- a * log(12.0 * channel - b) + c;
- }
-
- float3 OETF(float3 linear) {
- return float3(OETF_channel(linear.r), OETF_channel(linear.g),
- OETF_channel(linear.b));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_LINEAR:
- shader.append(R"(
- float3 OETF(float3 linear) {
- return linear;
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_SMPTE_170M:
- shader.append(R"(
- float OETF_sRGB(float linear) {
- return linear <= 0.018 ?
- linear * 4.50 : (pow(linear, 0.45) * 1.099) - 0.099;
- }
-
- float3 OETF_sRGB(float3 linear) {
- return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
-
- float3 OETF(float3 linear) {
- return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_2:
- shader.append(R"(
- float OETF_sRGB(float linear) {
- return pow(linear, (1.0 / 2.2));
- }
-
- float3 OETF_sRGB(float3 linear) {
- return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
-
- float3 OETF(float3 linear) {
- return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_6:
- shader.append(R"(
- float OETF_sRGB(float linear) {
- return pow(linear, (1.0 / 2.6));
- }
-
- float3 OETF_sRGB(float3 linear) {
- return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
+void generateOETF(std::string& shader) {
+ // Only support gamma 2.2 for now
+ shader.append(R"(
+ float OETF(float3 linear) {
+ return sign(linear) * pow(abs(linear), (1.0 / 2.2));
+ }
+ )");
+}
- float3 OETF(float3 linear) {
- return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
- }
- )");
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_8:
+void generateEffectiveOOTF(bool undoPremultipliedAlpha, LinearEffect::SkSLType type,
+ bool needsCustomOETF, std::string& shader) {
+ switch (type) {
+ case LinearEffect::SkSLType::ColorFilter:
shader.append(R"(
- float OETF_sRGB(float linear) {
- return pow(linear, (1.0 / 2.8));
- }
-
- float3 OETF_sRGB(float3 linear) {
- return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
-
- float3 OETF(float3 linear) {
- return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
- }
+ half4 main(half4 inputColor) {
+ float4 c = float4(inputColor);
)");
break;
- case HAL_DATASPACE_TRANSFER_SRGB:
- default:
+ case LinearEffect::SkSLType::Shader:
shader.append(R"(
- float OETF_sRGB(float linear) {
- return linear <= 0.0031308 ?
- linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
- }
-
- float3 OETF_sRGB(float3 linear) {
- return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
- }
-
- float3 OETF(float3 linear) {
- return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
- }
+ uniform shader child;
+ half4 main(float2 xy) {
+ float4 c = float4(child.eval(xy));
)");
break;
}
-}
-
-void generateEffectiveOOTF(bool undoPremultipliedAlpha, std::string& shader) {
- shader.append(R"(
- uniform shader child;
- half4 main(float2 xy) {
- float4 c = float4(child.eval(xy));
- )");
if (undoPremultipliedAlpha) {
shader.append(R"(
c.rgb = c.rgb / (c.a + 0.0019);
)");
}
+ // We are using linear sRGB as a working space, with 1.0 == 203 nits
shader.append(R"(
- float3 linearRGB = EOTF(c.rgb);
- float3 xyz = ToXYZ(linearRGB);
- c.rgb = OETF(ToRGB(OOTF(linearRGB, xyz)));
+ c.rgb = ApplyColorTransform(OOTF(toLinearSrgb(c.rgb)));
)");
+ if (needsCustomOETF) {
+ shader.append(R"(
+ c.rgb = OETF(c.rgb);
+ )");
+ } else {
+ shader.append(R"(
+ c.rgb = fromLinearSrgb(c.rgb);
+ )");
+ }
if (undoPremultipliedAlpha) {
shader.append(R"(
c.rgb = c.rgb * (c.a + 0.0019);
@@ -413,7 +220,31 @@ void generateEffectiveOOTF(bool undoPremultipliedAlpha, std::string& shader) {
)");
}
-// please keep in sync with toSkColorSpace function in renderengine/skia/ColorSpaces.cpp
+template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true>
+std::vector<uint8_t> buildUniformValue(T value) {
+ std::vector<uint8_t> result;
+ result.resize(sizeof(value));
+ std::memcpy(result.data(), &value, sizeof(value));
+ return result;
+}
+
+} // namespace
+
+std::string buildLinearEffectSkSL(const LinearEffect& linearEffect) {
+ std::string shaderString;
+ generateXYZTransforms(shaderString);
+ generateOOTF(linearEffect.inputDataspace, linearEffect.outputDataspace, shaderString);
+
+ const bool needsCustomOETF = (linearEffect.fakeOutputDataspace & HAL_DATASPACE_TRANSFER_MASK) ==
+ HAL_DATASPACE_TRANSFER_GAMMA2_2;
+ if (needsCustomOETF) {
+ generateOETF(shaderString);
+ }
+ generateEffectiveOOTF(linearEffect.undoPremultipliedAlpha, linearEffect.type, needsCustomOETF,
+ shaderString);
+ return shaderString;
+}
+
ColorSpace toColorSpace(ui::Dataspace dataspace) {
switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
case HAL_DATASPACE_STANDARD_BT709:
@@ -425,14 +256,14 @@ ColorSpace toColorSpace(ui::Dataspace dataspace) {
return ColorSpace::BT2020();
case HAL_DATASPACE_STANDARD_ADOBE_RGB:
return ColorSpace::AdobeRGB();
- // TODO(b/208290320): BT601 format and variants return different primaries
+ // TODO(b/208290320): BT601 format and variants return different primaries
case HAL_DATASPACE_STANDARD_BT601_625:
case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
case HAL_DATASPACE_STANDARD_BT601_525:
case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
- // TODO(b/208290329): BT407M format returns different primaries
+ // TODO(b/208290329): BT407M format returns different primaries
case HAL_DATASPACE_STANDARD_BT470M:
- // TODO(b/208290904): FILM format returns different primaries
+ // TODO(b/208290904): FILM format returns different primaries
case HAL_DATASPACE_STANDARD_FILM:
case HAL_DATASPACE_STANDARD_UNSPECIFIED:
default:
@@ -440,29 +271,6 @@ ColorSpace toColorSpace(ui::Dataspace dataspace) {
}
}
-template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true>
-std::vector<uint8_t> buildUniformValue(T value) {
- std::vector<uint8_t> result;
- result.resize(sizeof(value));
- std::memcpy(result.data(), &value, sizeof(value));
- return result;
-}
-
-} // namespace
-
-std::string buildLinearEffectSkSL(const LinearEffect& linearEffect) {
- std::string shaderString;
- generateEOTF(linearEffect.fakeInputDataspace == ui::Dataspace::UNKNOWN
- ? linearEffect.inputDataspace
- : linearEffect.fakeInputDataspace,
- shaderString);
- generateXYZTransforms(shaderString);
- generateOOTF(linearEffect.inputDataspace, linearEffect.outputDataspace, shaderString);
- generateOETF(linearEffect.outputDataspace, shaderString);
- generateEffectiveOOTF(linearEffect.undoPremultipliedAlpha, shaderString);
- return shaderString;
-}
-
// Generates a list of uniforms to set on the LinearEffect shader above.
std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance,
@@ -470,29 +278,29 @@ std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
aidl::android::hardware::graphics::composer3::RenderIntent renderIntent) {
std::vector<tonemap::ShaderUniform> uniforms;
- const ui::Dataspace inputDataspace = linearEffect.fakeInputDataspace == ui::Dataspace::UNKNOWN
- ? linearEffect.inputDataspace
- : linearEffect.fakeInputDataspace;
-
- if (inputDataspace == linearEffect.outputDataspace) {
- uniforms.push_back({.name = "in_rgbToXyz", .value = buildUniformValue<mat4>(mat4())});
- uniforms.push_back(
- {.name = "in_xyzToRgb", .value = buildUniformValue<mat4>(colorTransform)});
- } else {
- ColorSpace inputColorSpace = toColorSpace(inputDataspace);
- ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
- uniforms.push_back({.name = "in_rgbToXyz",
- .value = buildUniformValue<mat4>(mat4(inputColorSpace.getRGBtoXYZ()))});
- uniforms.push_back({.name = "in_xyzToRgb",
- .value = buildUniformValue<mat4>(
- colorTransform * mat4(outputColorSpace.getXYZtoRGB()))});
- }
+ auto inputColorSpace = toColorSpace(linearEffect.inputDataspace);
+ auto outputColorSpace = toColorSpace(linearEffect.outputDataspace);
+
+ uniforms.push_back(
+ {.name = "in_rgbToXyz",
+ .value = buildUniformValue<mat3>(ColorSpace::linearExtendedSRGB().getRGBtoXYZ())});
+ uniforms.push_back({.name = "in_xyzToSrcRgb",
+ .value = buildUniformValue<mat3>(inputColorSpace.getXYZtoRGB())});
+ // Transforms xyz colors to linear source colors, then applies the color transform, then
+ // transforms to linear extended RGB for skia to color manage.
+ uniforms.push_back({.name = "in_colorTransform",
+ .value = buildUniformValue<mat4>(
+ mat4(ColorSpace::linearExtendedSRGB().getXYZtoRGB()) *
+ // TODO: the color transform ideally should be applied
+ // in the source colorspace, but doing that breaks
+ // renderengine tests
+ mat4(outputColorSpace.getRGBtoXYZ()) * colorTransform *
+ mat4(outputColorSpace.getXYZtoRGB()))});
tonemap::Metadata metadata{.displayMaxLuminance = maxDisplayLuminance,
// If the input luminance is unknown, use display luminance (aka,
- // no-op any luminance changes)
- // This will be the case for eg screenshots in addition to
- // uncalibrated displays
+ // no-op any luminance changes).
+ // This is expected to only be meaningful for PQ content
.contentMaxLuminance =
maxLuminance > 0 ? maxLuminance : maxDisplayLuminance,
.currentDisplayLuminance = currentDisplayLuminanceNits > 0