diff options
| author | 2018-03-21 19:14:35 -0700 | |
|---|---|---|
| committer | 2018-03-23 21:35:20 +0000 | |
| commit | 7c4d1286ca62db617f8f50b82ea692baf03bda1f (patch) | |
| tree | c43b16b2d56ea5e4960b7c9a58381ae9465b293d | |
| parent | 14c461a47806524f7bb51273df7d45fb8648b4b7 (diff) | |
[SurfaceFlinger] Fix HDR tone mapping.
Previously we tone mapped for all color channels, however, the correct way is
to convert to XYZ color space, and only tone map the Y channel.
BUG: 76220266
Test: Test with modified Youtube apk
Change-Id: Ia00ab32b9d5d9f1d1128d57305ceabbdb68fffcd
| -rw-r--r-- | services/surfaceflinger/RenderEngine/ProgramCache.cpp | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index 7a43ea92bd..6a34981174 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -305,15 +305,24 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { if (needs.hasToneMapping()) { fs << R"__SHADER__( - float ToneMapChannel(const float color) { + float CalculateY(const vec3 color) { + // BT2020 standard uses the unadjusted KR = 0.2627, + // KB = 0.0593 luminance interpretation for RGB conversion. + return color.r * 0.262700 + color.g * 0.677998 + + color.b * 0.059302; + } + vec3 ToneMap(const vec3 color) { const float maxLumi = 10000.0; const float maxMasteringLumi = 1000.0; const float maxContentLumi = 1000.0; const float maxInLumi = min(maxMasteringLumi, maxContentLumi); const float maxOutLumi = 500.0; + // Calculate Y value in XYZ color space. + float colorY = CalculateY(color); + // convert to nits first - float nits = color * maxLumi; + float nits = colorY * maxLumi; // clamp to max input luminance nits = clamp(nits, 0.0, maxInLumi); @@ -360,12 +369,8 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } // convert back to [0.0, 1.0] - return nits / maxOutLumi; - } - - vec3 ToneMap(const vec3 color) { - return vec3(ToneMapChannel(color.r), ToneMapChannel(color.g), - ToneMapChannel(color.b)); + float targetY = nits / maxOutLumi; + return color * (targetY / max(1e-6, colorY)); } )__SHADER__"; } else { |