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.cpp58
1 files changed, 39 insertions, 19 deletions
diff --git a/libs/shaders/shaders.cpp b/libs/shaders/shaders.cpp
index a3c403e551..19518eaecc 100644
--- a/libs/shaders/shaders.cpp
+++ b/libs/shaders/shaders.cpp
@@ -191,31 +191,35 @@ void generateLuminanceScalesForOOTF(ui::Dataspace inputDataspace, ui::Dataspace
)");
break;
default:
+ // Input is SDR so map to its white point luminance
switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
+ // Max HLG output is nominally 1000 nits, but BT. 2100-2 allows
+ // for gamma correcting the HLG OOTF for displays with a different
+ // dynamic range. Scale to 1000 nits to apply an inverse OOTF against
+ // a reference display correctly.
+ // TODO: Use knowledge of the dimming ratio here to prevent
+ // unintended gamma shaft.
case HAL_DATASPACE_TRANSFER_HLG:
- // SDR -> HDR tonemap
shader.append(R"(
float3 ScaleLuminance(float3 xyz) {
- return xyz * in_libtonemap_inputMaxLuminance;
+ return xyz * 1000.0;
}
)");
break;
default:
- // Input and output are both SDR, so no tone-mapping is expected so
- // no-op the luminance normalization.
shader.append(R"(
- float3 ScaleLuminance(float3 xyz) {
- return xyz * in_libtonemap_displayMaxLuminance;
- }
- )");
+ float3 ScaleLuminance(float3 xyz) {
+ return xyz * in_libtonemap_displayMaxLuminance;
+ }
+ )");
break;
}
}
}
// Normalizes from absolute light back to relative light (maps from [0, maxNits] back to [0, 1])
-static void generateLuminanceNormalizationForOOTF(ui::Dataspace outputDataspace,
+static void generateLuminanceNormalizationForOOTF(ui::Dataspace inputDataspace,
+ ui::Dataspace outputDataspace,
std::string& shader) {
switch (outputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
@@ -226,11 +230,28 @@ static void generateLuminanceNormalizationForOOTF(ui::Dataspace outputDataspace,
)");
break;
case HAL_DATASPACE_TRANSFER_HLG:
- shader.append(R"(
- float3 NormalizeLuminance(float3 xyz) {
- return xyz / 1000.0;
- }
- )");
+ switch (inputDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_HLG:
+ shader.append(R"(
+ float3 NormalizeLuminance(float3 xyz) {
+ return xyz / 1000.0;
+ }
+ )");
+ break;
+ default:
+ // Transcoding to HLG requires applying the inverse OOTF
+ // with the expectation that the OOTF is then applied during
+ // tonemapping downstream.
+ shader.append(R"(
+ float3 NormalizeLuminance(float3 xyz) {
+ // BT. 2100-2 operates on normalized luminances,
+ // so renormalize to the input
+ float ootfGain = pow(xyz.y / 1000.0, -0.2 / 1.2) / 1000.0;
+ return xyz * ootfGain;
+ }
+ )");
+ break;
+ }
break;
default:
shader.append(R"(
@@ -250,7 +271,7 @@ void generateOOTF(ui::Dataspace inputDataspace, ui::Dataspace outputDataspace,
.c_str());
generateLuminanceScalesForOOTF(inputDataspace, outputDataspace, shader);
- generateLuminanceNormalizationForOOTF(outputDataspace, shader);
+ generateLuminanceNormalizationForOOTF(inputDataspace, outputDataspace, shader);
shader.append(R"(
float3 OOTF(float3 linearRGB, float3 xyz) {
@@ -501,9 +522,8 @@ std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
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