diff options
author | 2024-05-24 18:21:21 +0000 | |
---|---|---|
committer | 2024-05-24 18:27:32 +0000 | |
commit | a7e752e25f54296c907ddbf5a682990bf9e85f6d (patch) | |
tree | 87c569600f79d3a9721589bf6d65baf8f53bbd49 | |
parent | ef7f5d11c09ff046e4cf5420aaf07c8baa01aded (diff) |
Plumb in local tonemapping flag into renderengine
The detailed local tonemapping implementation will come in a later CL.
Also allow the flag to configure luminance spaces in SF, to prevent
SDR-only regions from dimming.
Bug: 329464641
Test: builds
Change-Id: Ia2bbf12b2cdfb5597137a6028911ff71b3d866d3
-rw-r--r-- | libs/renderengine/include/renderengine/DisplaySettings.h | 16 | ||||
-rw-r--r-- | libs/renderengine/skia/SkiaRenderEngine.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/ScreenCaptureOutput.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/ScreenCaptureOutput.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 38 |
5 files changed, 60 insertions, 17 deletions
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h index deb62534a5..b640983a55 100644 --- a/libs/renderengine/include/renderengine/DisplaySettings.h +++ b/libs/renderengine/include/renderengine/DisplaySettings.h @@ -86,6 +86,22 @@ struct DisplaySettings { // Configures the rendering intent of the output display. This is used for tonemapping. aidl::android::hardware::graphics::composer3::RenderIntent renderIntent = aidl::android::hardware::graphics::composer3::RenderIntent::TONE_MAP_COLORIMETRIC; + + // Tonemapping strategy to use for each layer. This is only used for tonemapping HDR source + // content + enum class TonemapStrategy { + // Use a tonemapper defined by libtonemap. This may be OEM-defined as of Android 13, aka + // undefined. + // This is typically a global tonemapper, designed to match what is on screen. + Libtonemap, + // Use a local tonemapper. Because local tonemapping uses large intermediate allocations, + // this + // method is primarily recommended for infrequent rendering that does not need to exactly + // match + // pixels that are on-screen. + Local, + }; + TonemapStrategy tonemapStrategy = TonemapStrategy::Libtonemap; }; static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) { diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index b973211966..ccbf0924d0 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -519,6 +519,11 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader( } if (parameters.requiresLinearEffect) { + if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) { + // TODO: Apply a local tonemap + // fallthrough for now + } + auto effect = shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace, .outputDataspace = parameters.outputDataSpace, diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp index dd03366bcc..8bb72b8470 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.cpp +++ b/services/surfaceflinger/ScreenCaptureOutput.cpp @@ -30,7 +30,7 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&, const compositionengine::Output::ColorProfile&, bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling, - args.dimInGammaSpaceForEnhancedScreenshots); + args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping); output->editState().isSecure = args.renderArea.isSecure(); output->editState().isProtected = args.isProtected; output->setCompositionEnabled(true); @@ -63,11 +63,13 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp ScreenCaptureOutput::ScreenCaptureOutput( const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile, - bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots) + bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots, + bool enableLocalTonemapping) : mRenderArea(renderArea), mColorProfile(colorProfile), mRegionSampling(regionSampling), - mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots) {} + mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots), + mEnableLocalTonemapping(enableLocalTonemapping) {} void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) { auto& outputState = editState(); @@ -88,6 +90,11 @@ renderengine::DisplaySettings ScreenCaptureOutput::generateClientCompositionDisp aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF; } + if (mEnableLocalTonemapping) { + clientCompositionDisplay.tonemapStrategy = + renderengine::DisplaySettings::TonemapStrategy::Local; + } + return clientCompositionDisplay; } diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h index 069f458bdb..c233ead575 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.h +++ b/services/surfaceflinger/ScreenCaptureOutput.h @@ -39,6 +39,7 @@ struct ScreenCaptureOutputArgs { bool treat170mAsSrgb; bool dimInGammaSpaceForEnhancedScreenshots; bool isProtected = false; + bool enableLocalTonemapping = false; }; // ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer. @@ -49,7 +50,8 @@ class ScreenCaptureOutput : public compositionengine::impl::Output { public: ScreenCaptureOutput(const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile, - bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots); + bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots, + bool enableLocalTonemapping); void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override; @@ -67,6 +69,7 @@ private: const compositionengine::Output::ColorProfile& mColorProfile; const bool mRegionSampling; const bool mDimInGammaSpaceForEnhancedScreenshots; + const bool mEnableLocalTonemapping; }; std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 66385d8db5..95f37997ef 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8302,6 +8302,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( captureResults.capturedDataspace = requestedDataspace; + const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() && + !renderArea->getHintForSeamlessTransition(); + { Mutex::Autolock lock(mStateLock); const DisplayDevice* display = nullptr; @@ -8335,16 +8338,19 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( displayBrightnessNits = sdrWhitePointNits; } else { displayBrightnessNits = state.displayBrightnessNits; - // Only clamp the display brightness if this is not a seamless transition. Otherwise - // for seamless transitions it's important to match the current display state as the - // buffer will be shown under these same conditions, and we want to avoid any - // flickers - if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) { - // Restrict the amount of HDR "headroom" in the screenshot to avoid over-dimming - // the SDR portion. 2.0 chosen by experimentation - constexpr float kMaxScreenshotHeadroom = 2.0f; - displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom, - displayBrightnessNits); + + if (!enableLocalTonemapping) { + // Only clamp the display brightness if this is not a seamless transition. + // Otherwise for seamless transitions it's important to match the current + // display state as the buffer will be shown under these same conditions, and we + // want to avoid any flickers + if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) { + // Restrict the amount of HDR "headroom" in the screenshot to avoid + // over-dimming the SDR portion. 2.0 chosen by experimentation + constexpr float kMaxScreenshotHeadroom = 2.0f; + displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom, + displayBrightnessNits); + } } } @@ -8376,7 +8382,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace, sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected, layerFEs = copyLayerFEs(), layerStack, regionSampling, - renderArea = std::move(renderArea), renderIntent]() -> FenceResult { + renderArea = std::move(renderArea), renderIntent, + enableLocalTonemapping]() -> FenceResult { std::unique_ptr<compositionengine::CompositionEngine> compositionEngine = mFactory.createCompositionEngine(); compositionEngine->setRenderEngine(mRenderEngine.get()); @@ -8385,7 +8392,11 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .renderIntent = renderIntent}; float targetBrightness = 1.0f; - if (dataspace == ui::Dataspace::BT2020_HLG) { + if (enableLocalTonemapping) { + // Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr + // sdr ratio via display brightness / sdrWhite nits. + targetBrightness = sdrWhitePointNits / displayBrightnessNits; + } else if (dataspace == ui::Dataspace::BT2020_HLG) { const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203; // With a low dimming ratio, don't fit the entire curve. Otherwise mixed content // will appear way too bright. @@ -8411,7 +8422,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .treat170mAsSrgb = mTreat170mAsSrgb, .dimInGammaSpaceForEnhancedScreenshots = dimInGammaSpaceForEnhancedScreenshots, - .isProtected = isProtected}); + .isProtected = isProtected, + .enableLocalTonemapping = enableLocalTonemapping}); const float colorSaturation = grayscale ? 0 : 1; compositionengine::CompositionRefreshArgs refreshArgs{ |