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
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index dd03366..8bb72b8 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -30,7 +30,7 @@
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 @@
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 @@
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 069f458..c233ead 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -39,6 +39,7 @@
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 @@
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 @@
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 66385d8..95f3799 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -8302,6 +8302,9 @@
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 @@
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 @@
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 @@
.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 @@
.treat170mAsSrgb = mTreat170mAsSrgb,
.dimInGammaSpaceForEnhancedScreenshots =
dimInGammaSpaceForEnhancedScreenshots,
- .isProtected = isProtected});
+ .isProtected = isProtected,
+ .enableLocalTonemapping = enableLocalTonemapping});
const float colorSaturation = grayscale ? 0 : 1;
compositionengine::CompositionRefreshArgs refreshArgs{