diff options
-rw-r--r-- | libs/renderengine/include/renderengine/DisplaySettings.h | 3 | ||||
-rw-r--r-- | libs/renderengine/skia/SkiaGLRenderEngine.cpp | 1 | ||||
-rw-r--r-- | libs/renderengine/skia/filters/LinearEffect.cpp | 7 | ||||
-rw-r--r-- | libs/renderengine/skia/filters/LinearEffect.h | 3 | ||||
-rw-r--r-- | libs/shaders/include/shaders/shaders.h | 1 | ||||
-rw-r--r-- | libs/shaders/shaders.cpp | 2 | ||||
-rw-r--r-- | libs/tonemap/include/tonemap/tonemap.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/src/Output.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp | 94 |
9 files changed, 94 insertions, 25 deletions
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h index b4cab39bd9..2c51ccd334 100644 --- a/libs/renderengine/include/renderengine/DisplaySettings.h +++ b/libs/renderengine/include/renderengine/DisplaySettings.h @@ -43,6 +43,9 @@ struct DisplaySettings { // Maximum luminance pulled from the display's HDR capabilities. float maxLuminance = 1.0f; + // Current luminance of the display + float currentLuminanceNits = -1.f; + // Output dataspace that will be populated if wide color gamut is used, or // DataSpace::UNKNOWN otherwise. ui::Dataspace outputDataspace = ui::Dataspace::UNKNOWN; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index cc90946753..063ce67f83 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -656,6 +656,7 @@ sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader( parameters.layerDimmingRatio, 1.f)); return createLinearEffectShader(parameters.shader, effect, runtimeEffect, colorTransform, parameters.display.maxLuminance, + parameters.display.currentLuminanceNits, parameters.layer.source.buffer.maxLuminanceNits); } return parameters.shader; diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp index 36305aeea8..6077c2e7da 100644 --- a/libs/renderengine/skia/filters/LinearEffect.cpp +++ b/libs/renderengine/skia/filters/LinearEffect.cpp @@ -44,14 +44,15 @@ sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader, const shaders::LinearEffect& linearEffect, sk_sp<SkRuntimeEffect> runtimeEffect, const mat4& colorTransform, float maxDisplayLuminance, - float maxLuminance) { + float currentDisplayLuminanceNits, float maxLuminance) { ATRACE_CALL(); SkRuntimeShaderBuilder effectBuilder(runtimeEffect); effectBuilder.child("child") = shader; - const auto uniforms = shaders::buildLinearEffectUniforms(linearEffect, colorTransform, - maxDisplayLuminance, maxLuminance); + const auto uniforms = + shaders::buildLinearEffectUniforms(linearEffect, colorTransform, maxDisplayLuminance, + currentDisplayLuminanceNits, maxLuminance); for (const auto& uniform : uniforms) { effectBuilder.uniform(uniform.name.c_str()).set(uniform.value.data(), uniform.value.size()); diff --git a/libs/renderengine/skia/filters/LinearEffect.h b/libs/renderengine/skia/filters/LinearEffect.h index 8eb6670150..e0a556b11a 100644 --- a/libs/renderengine/skia/filters/LinearEffect.h +++ b/libs/renderengine/skia/filters/LinearEffect.h @@ -37,13 +37,14 @@ sk_sp<SkRuntimeEffect> buildRuntimeEffect(const shaders::LinearEffect& linearEff // matrix transforming from linear XYZ to linear RGB immediately before OETF. // We also provide additional HDR metadata upon creating the shader: // * The max display luminance is the max luminance of the physical display in nits +// * The current luminance of the physical display in nits // * The max luminance is provided as the max luminance for the buffer, either from the SMPTE 2086 // or as the max light level from the CTA 861.3 standard. sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> inputShader, const shaders::LinearEffect& linearEffect, sk_sp<SkRuntimeEffect> runtimeEffect, const mat4& colorTransform, float maxDisplayLuminance, - float maxLuminance); + float currentDisplayLuminanceNits, float maxLuminance); } // namespace skia } // namespace renderengine } // namespace android diff --git a/libs/shaders/include/shaders/shaders.h b/libs/shaders/include/shaders/shaders.h index 712a27a3eb..43828ccd05 100644 --- a/libs/shaders/include/shaders/shaders.h +++ b/libs/shaders/include/shaders/shaders.h @@ -100,6 +100,7 @@ std::string buildLinearEffectSkSL(const LinearEffect& linearEffect); std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance, + float currentDisplayLuminanceNits, float maxLuminance); } // namespace android::shaders diff --git a/libs/shaders/shaders.cpp b/libs/shaders/shaders.cpp index 6019c4ac28..4d88d5d417 100644 --- a/libs/shaders/shaders.cpp +++ b/libs/shaders/shaders.cpp @@ -463,6 +463,7 @@ std::vector<uint8_t> buildUniformValue(T value) { std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance, + float currentDisplayLuminanceNits, float maxLuminance) { std::vector<tonemap::ShaderUniform> uniforms; if (linearEffect.inputDataspace == linearEffect.outputDataspace) { @@ -480,6 +481,7 @@ std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(const LinearEffect } tonemap::Metadata metadata{.displayMaxLuminance = maxDisplayLuminance, + .currentDisplayLuminanceNits = currentDisplayLuminanceNits, // 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 diff --git a/libs/tonemap/include/tonemap/tonemap.h b/libs/tonemap/include/tonemap/tonemap.h index bd7b72d186..6233e6c418 100644 --- a/libs/tonemap/include/tonemap/tonemap.h +++ b/libs/tonemap/include/tonemap/tonemap.h @@ -42,7 +42,11 @@ struct ShaderUniform { // This metadata should not be used for manipulating the source code of the shader program directly, // as otherwise caching by other system of these shaders may break. struct Metadata { + // The maximum luminance of the display in nits float displayMaxLuminance = 0.0; + // The current luminance of the display in nits + float currentDisplayLuminanceNits = 0.0; + // The maximum luminance of the content in nits float contentMaxLuminance = 0.0; }; diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 192ee047ee..162d84ef31 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1059,9 +1059,11 @@ std::optional<base::unique_fd> Output::composeSurfaces( // If we have a valid current display brightness use that, otherwise fall back to the // display's max desired - clientCompositionDisplay.maxLuminance = outputState.displayBrightnessNits > 0.f + clientCompositionDisplay.currentLuminanceNits = outputState.displayBrightnessNits > 0.f ? outputState.displayBrightnessNits : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance(); + clientCompositionDisplay.maxLuminance = + mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance(); clientCompositionDisplay.targetLuminanceNits = outputState.clientTargetWhitePointNits; // Compute the global color transform matrix. diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index f7c75337ff..c2235a26ea 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -3069,6 +3069,8 @@ struct OutputComposeSurfacesTest : public testing::Test { static constexpr float kDefaultMaxLuminance = 0.9f; static constexpr float kDefaultAvgLuminance = 0.7f; static constexpr float kDefaultMinLuminance = 0.1f; + static constexpr float kUnknownLuminance = -1.f; + static constexpr float kDisplayLuminance = 80.f; static constexpr float kClientTargetLuminanceNits = 200.f; static const Rect kDefaultOutputFrame; @@ -3101,6 +3103,7 @@ const Rect OutputComposeSurfacesTest::kDefaultOutputDestinationClip{1013, 1014, const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5f}; const compositionengine::CompositionRefreshArgs OutputComposeSurfacesTest::kDefaultRefreshArgs; const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}}; + const HdrCapabilities OutputComposeSurfacesTest:: kHdrCapabilities{{}, OutputComposeSurfacesTest::kDefaultMaxLuminance, @@ -3403,6 +3406,14 @@ struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComp auto andIfUsesHdr(bool used) { EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasWideColorGamut()) .WillOnce(Return(used)); + return nextState<OutputWithDisplayBrightnessNits>(); + } + }; + + struct OutputWithDisplayBrightnessNits + : public CallOrderStateMachineHelper<TestType, OutputWithDisplayBrightnessNits> { + auto withDisplayBrightnessNits(float nits) { + getInstance()->mOutput.mState.displayBrightnessNits = nits; return nextState<SkipColorTransformState>(); } }; @@ -3434,11 +3445,34 @@ struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComp TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) { verify().ifMixedCompositionIs(true) .andIfUsesHdr(true) + .withDisplayBrightnessNits(kUnknownLuminance) + .andIfSkipColorTransform(false) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDefaultMaxLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = mat4(), + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) + .execute() + .expectAFenceWasReturned(); +} + +TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, + forHdrMixedCompositionWithDisplayBrightness) { + verify().ifMixedCompositionIs(true) + .andIfUsesHdr(true) + .withDisplayBrightnessNits(kDisplayLuminance) .andIfSkipColorTransform(false) - .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport, - kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(), - kDefaultOutputOrientationFlags, - kClientTargetLuminanceNits}) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDisplayLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = mat4(), + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) .execute() .expectAFenceWasReturned(); } @@ -3446,11 +3480,16 @@ TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposi TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) { verify().ifMixedCompositionIs(true) .andIfUsesHdr(false) + .withDisplayBrightnessNits(kUnknownLuminance) .andIfSkipColorTransform(false) - .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport, - kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(), - kDefaultOutputOrientationFlags, - kClientTargetLuminanceNits}) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDefaultMaxLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = mat4(), + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) .execute() .expectAFenceWasReturned(); } @@ -3458,11 +3497,16 @@ TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComp TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) { verify().ifMixedCompositionIs(false) .andIfUsesHdr(true) + .withDisplayBrightnessNits(kUnknownLuminance) .andIfSkipColorTransform(false) - .thenExpectDisplaySettingsUsed( - {kDefaultOutputDestinationClip, kDefaultOutputViewport, kDefaultMaxLuminance, - kDefaultOutputDataspace, kDefaultColorTransformMat, - kDefaultOutputOrientationFlags, kClientTargetLuminanceNits}) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDefaultMaxLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = kDefaultColorTransformMat, + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) .execute() .expectAFenceWasReturned(); } @@ -3470,11 +3514,16 @@ TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientCo TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) { verify().ifMixedCompositionIs(false) .andIfUsesHdr(false) + .withDisplayBrightnessNits(kUnknownLuminance) .andIfSkipColorTransform(false) - .thenExpectDisplaySettingsUsed( - {kDefaultOutputDestinationClip, kDefaultOutputViewport, kDefaultMaxLuminance, - kDefaultOutputDataspace, kDefaultColorTransformMat, - kDefaultOutputOrientationFlags, kClientTargetLuminanceNits}) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDefaultMaxLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = kDefaultColorTransformMat, + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) .execute() .expectAFenceWasReturned(); } @@ -3483,11 +3532,16 @@ TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) { verify().ifMixedCompositionIs(false) .andIfUsesHdr(true) + .withDisplayBrightnessNits(kUnknownLuminance) .andIfSkipColorTransform(true) - .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport, - kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(), - kDefaultOutputOrientationFlags, - kClientTargetLuminanceNits}) + .thenExpectDisplaySettingsUsed({.physicalDisplay = kDefaultOutputDestinationClip, + .clip = kDefaultOutputViewport, + .maxLuminance = kDefaultMaxLuminance, + .currentLuminanceNits = kDefaultMaxLuminance, + .outputDataspace = kDefaultOutputDataspace, + .colorTransform = mat4(), + .orientation = kDefaultOutputOrientationFlags, + .targetLuminanceNits = kClientTargetLuminanceNits}) .execute() .expectAFenceWasReturned(); } |