@@ -7196,14 +7196,13 @@ status_t SurfaceFlinger::setSchedAttr(bool enabled) {
71967196
71977197namespace {
71987198
7199- ui::Dataspace pickBestDataspace (ui::Dataspace requestedDataspace,
7200- const compositionengine::impl::OutputCompositionState& state,
7199+ ui::Dataspace pickBestDataspace (ui::Dataspace requestedDataspace, ui::ColorMode colorMode,
72017200 bool capturingHdrLayers, bool hintForSeamlessTransition) {
72027201 if (requestedDataspace != ui::Dataspace::UNKNOWN) {
72037202 return requestedDataspace;
72047203 }
72057204
7206- const auto dataspaceForColorMode = ui::pickDataspaceFor (state. colorMode );
7205+ const auto dataspaceForColorMode = ui::pickDataspaceFor (colorMode);
72077206
72087207 // TODO: Enable once HDR screenshots are ready.
72097208 if constexpr (/* DISABLES CODE */ (false )) {
@@ -7515,11 +7514,11 @@ bool SurfaceFlinger::layersHasProtectedLayer(
75157514 return protectedLayerFound;
75167515}
75177516
7518- // Getting layer snapshots and display should take place on main thread.
7519- // Accessing display requires mStateLock, and contention for this lock
7520- // is reduced when grabbed from the main thread, thus also reducing
7521- // risk of deadlocks.
7522- std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getSnapshotsFromMainThread (
7517+ // Getting layer snapshots and accessing display state should take place on
7518+ // main thread. Accessing display requires mStateLock, and contention for
7519+ // this lock is reduced when grabbed from the main thread, thus also reducing
7520+ // risk of deadlocks. Returns false if no display is found.
7521+ bool SurfaceFlinger::getSnapshotsFromMainThread (
75237522 ScreenshotArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn,
75247523 std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
75257524 return mScheduler
@@ -7559,8 +7558,8 @@ void SurfaceFlinger::captureScreenCommon(ScreenshotArgs& args,
75597558 }
75607559
75617560 std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
7562- auto displayState = getSnapshotsFromMainThread (args, getLayerSnapshotsFn, layers);
7563- if (!displayState ) {
7561+ bool hasDisplayState = getSnapshotsFromMainThread (args, getLayerSnapshotsFn, layers);
7562+ if (!hasDisplayState ) {
75647563 ALOGD (" Display state not found" );
75657564 invokeScreenCaptureError (NO_MEMORY, captureListener);
75667565 }
@@ -7637,12 +7636,13 @@ void SurfaceFlinger::captureScreenCommon(ScreenshotArgs& args,
76377636
76387637 auto futureFence =
76397638 captureScreenshot (args, texture, false /* regionSampling */ , grayscale, isProtected,
7640- captureListener, displayState, layers, hdrTexture, gainmapTexture);
7639+ captureListener, layers, hdrTexture, gainmapTexture);
76417640 futureFence.get ();
76427641}
76437642
7644- std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getDisplayStateOnMainThread (
7645- ScreenshotArgs& args) {
7643+ // Returns true if display is found and args was populated with display state
7644+ // data. Otherwise, returns false.
7645+ bool SurfaceFlinger::getDisplayStateOnMainThread (ScreenshotArgs& args) {
76467646 sp<const DisplayDevice> display = nullptr ;
76477647 {
76487648 Mutex::Autolock lock (mStateLock );
@@ -7677,67 +7677,66 @@ std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getDisplay
76777677 }
76787678
76797679 if (display != nullptr ) {
7680- return std::optional{display->getCompositionDisplay ()->getState ()};
7680+ const auto & state = display->getCompositionDisplay ()->getState ();
7681+ args.displayBrightnessNits = state.displayBrightnessNits ;
7682+ args.sdrWhitePointNits = state.sdrWhitePointNits ;
7683+ args.renderIntent = state.renderIntent ;
7684+ args.colorMode = state.colorMode ;
7685+ return true ;
76817686 }
76827687 }
7683- return std:: nullopt ;
7688+ return false ;
76847689}
76857690
76867691ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot (
7687- const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
7692+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
76887693 bool regionSampling, bool grayscale, bool isProtected,
76897694 const sp<IScreenCaptureListener>& captureListener,
7690- const std::optional<OutputCompositionState>& displayState,
76917695 const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
76927696 const std::shared_ptr<renderengine::ExternalTexture>& hdrBuffer,
76937697 const std::shared_ptr<renderengine::ExternalTexture>& gainmapBuffer) {
76947698 SFTRACE_CALL ();
76957699
76967700 ScreenCaptureResults captureResults;
7697-
7698- float displayBrightnessNits = displayState.value ().displayBrightnessNits ;
7699- float sdrWhitePointNits = displayState.value ().sdrWhitePointNits ;
7700-
77017701 ftl::SharedFuture<FenceResult> renderFuture;
77027702
7703+ float hdrSdrRatio = args.displayBrightnessNits / args.sdrWhitePointNits ;
7704+
77037705 if (hdrBuffer && gainmapBuffer) {
77047706 ftl::SharedFuture<FenceResult> hdrRenderFuture =
77057707 renderScreenImpl (args, hdrBuffer, regionSampling, grayscale, isProtected,
7706- captureResults, displayState, layers);
7708+ captureResults, layers);
77077709 captureResults.buffer = buffer->getBuffer ();
77087710 captureResults.optionalGainMap = gainmapBuffer->getBuffer ();
77097711
77107712 renderFuture =
77117713 ftl::Future (std::move (hdrRenderFuture))
7712- .then ([&, displayBrightnessNits, sdrWhitePointNits,
7713- dataspace = captureResults.capturedDataspace , buffer, hdrBuffer,
7714- gainmapBuffer](FenceResult fenceResult) -> FenceResult {
7714+ .then ([&, hdrSdrRatio, dataspace = captureResults.capturedDataspace , buffer,
7715+ hdrBuffer, gainmapBuffer](FenceResult fenceResult) -> FenceResult {
77157716 if (!fenceResult.ok ()) {
77167717 return fenceResult;
77177718 }
77187719
77197720 return getRenderEngine ()
77207721 .tonemapAndDrawGainmap (hdrBuffer, fenceResult.value ()->get (),
7721- displayBrightnessNits /
7722- sdrWhitePointNits,
7722+ hdrSdrRatio,
77237723 static_cast <ui::Dataspace>(dataspace),
77247724 buffer, gainmapBuffer)
77257725 .get ();
77267726 })
77277727 .share ();
77287728 } else {
77297729 renderFuture = renderScreenImpl (args, buffer, regionSampling, grayscale, isProtected,
7730- captureResults, displayState, layers);
7730+ captureResults, layers);
77317731 }
77327732
77337733 if (captureListener) {
77347734 // Defer blocking on renderFuture back to the Binder thread.
77357735 return ftl::Future (std::move (renderFuture))
77367736 .then ([captureListener, captureResults = std::move (captureResults),
7737- displayBrightnessNits,
7738- sdrWhitePointNits](FenceResult fenceResult) mutable -> FenceResult {
7737+ hdrSdrRatio](FenceResult fenceResult) mutable -> FenceResult {
77397738 captureResults.fenceResult = std::move (fenceResult);
7740- captureResults.hdrSdrRatio = displayBrightnessNits / sdrWhitePointNits ;
7739+ captureResults.hdrSdrRatio = hdrSdrRatio ;
77417740 captureListener->onScreenCaptureCompleted (captureResults);
77427741 return base::unexpected (NO_ERROR);
77437742 })
@@ -7747,9 +7746,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
77477746}
77487747
77497748ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl (
7750- const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
7749+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
77517750 bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
7752- const std::optional<OutputCompositionState>& displayState,
77537751 const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
77547752 SFTRACE_CALL ();
77557753
@@ -7763,49 +7761,37 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
77637761 layerFE->mSnapshot ->geomLayerTransform .inverse ();
77647762 }
77657763
7766- auto capturedBuffer = buffer;
7767-
7768- auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
7769- auto sdrWhitePointNits = DisplayDevice::sDefaultMaxLumiance ;
7770- auto displayBrightnessNits = DisplayDevice::sDefaultMaxLumiance ;
7771-
7772- captureResults.capturedDataspace = args.dataspace ;
7773-
77747764 const bool enableLocalTonemapping =
77757765 FlagManager::getInstance ().local_tonemap_screenshots () && !args.seamlessTransition ;
77767766
7777- if (displayState) {
7778- const auto & state = displayState.value ();
7779- captureResults.capturedDataspace =
7780- pickBestDataspace (args.dataspace , state, captureResults.capturedHdrLayers ,
7781- args.seamlessTransition );
7782- sdrWhitePointNits = state.sdrWhitePointNits ;
7783-
7784- if (!captureResults.capturedHdrLayers ) {
7785- displayBrightnessNits = sdrWhitePointNits;
7786- } else {
7787- displayBrightnessNits = state.displayBrightnessNits ;
7788- if (!enableLocalTonemapping) {
7789- // Only clamp the display brightness if this is not a seamless transition.
7790- // Otherwise for seamless transitions it's important to match the current
7791- // display state as the buffer will be shown under these same conditions, and we
7792- // want to avoid any flickers
7793- if (sdrWhitePointNits > 1 .0f && !args.seamlessTransition ) {
7794- // Restrict the amount of HDR "headroom" in the screenshot to avoid
7795- // over-dimming the SDR portion. 2.0 chosen by experimentation
7796- constexpr float kMaxScreenshotHeadroom = 2 .0f ;
7797- displayBrightnessNits = std::min (sdrWhitePointNits * kMaxScreenshotHeadroom ,
7798- displayBrightnessNits);
7799- }
7800- }
7801- }
7767+ captureResults.capturedDataspace =
7768+ pickBestDataspace (args.dataspace , args.colorMode , captureResults.capturedHdrLayers ,
7769+ args.seamlessTransition );
7770+
7771+ // Only clamp the display brightness if this is not a seamless transition.
7772+ // Otherwise for seamless transitions it's important to match the current
7773+ // display state as the buffer will be shown under these same conditions, and we
7774+ // want to avoid any flickers.
7775+ if (captureResults.capturedHdrLayers && !enableLocalTonemapping &&
7776+ args.sdrWhitePointNits > 1 .0f && !args.seamlessTransition ) {
7777+ // Restrict the amount of HDR "headroom" in the screenshot to avoid
7778+ // over-dimming the SDR portion. 2.0 chosen by experimentation
7779+ constexpr float kMaxScreenshotHeadroom = 2 .0f ;
7780+ // TODO: Aim to update displayBrightnessNits earlier in screenshot
7781+ // path so ScreenshotArgs can be passed as const
7782+ args.displayBrightnessNits = std::min (args.sdrWhitePointNits * kMaxScreenshotHeadroom ,
7783+ args.displayBrightnessNits );
7784+ } else {
7785+ args.displayBrightnessNits = args.sdrWhitePointNits ;
7786+ }
78027787
7803- // Screenshots leaving the device should be colorimetric
7804- if (args. dataspace == ui::Dataspace::UNKNOWN && args. seamlessTransition ) {
7805- renderIntent = state. renderIntent ;
7806- }
7788+ auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
7789+ // Screenshots leaving the device should be colorimetric
7790+ if (args. dataspace == ui::Dataspace::UNKNOWN && args. seamlessTransition ) {
7791+ renderIntent = args. renderIntent ;
78077792 }
78087793
7794+ auto capturedBuffer = buffer;
78097795 captureResults.buffer = capturedBuffer->getBuffer ();
78107796
78117797 ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK};
@@ -7815,8 +7801,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
78157801 }
78167802
78177803 auto present = [this , buffer = capturedBuffer, dataspace = captureResults.capturedDataspace ,
7818- sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected, layers,
7819- layerStack, regionSampling, args, renderIntent,
7804+ grayscale, isProtected, layers, layerStack, regionSampling, args, renderIntent,
78207805 enableLocalTonemapping]() -> FenceResult {
78217806 std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
78227807 mFactory .createCompositionEngine ();
@@ -7842,9 +7827,10 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
78427827 if (enableLocalTonemapping) {
78437828 // Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr
78447829 // sdr ratio via display brightness / sdrWhite nits.
7845- targetBrightness = sdrWhitePointNits / displayBrightnessNits;
7830+ targetBrightness = args. sdrWhitePointNits / args. displayBrightnessNits ;
78467831 } else if (dataspace == ui::Dataspace::BT2020_HLG) {
7847- const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203 ;
7832+ const float maxBrightnessNits =
7833+ args.displayBrightnessNits / args.sdrWhitePointNits * 203 ;
78487834 // With a low dimming ratio, don't fit the entire curve. Otherwise mixed content
78497835 // will appear way too bright.
78507836 if (maxBrightnessNits < 1000 .f ) {
@@ -7870,8 +7856,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
78707856 .buffer = std::move (buffer),
78717857 .displayId = args.displayId ,
78727858 .reqBufferSize = args.reqSize ,
7873- .sdrWhitePointNits = sdrWhitePointNits,
7874- .displayBrightnessNits = displayBrightnessNits,
7859+ .sdrWhitePointNits = args. sdrWhitePointNits ,
7860+ .displayBrightnessNits = args. displayBrightnessNits ,
78757861 .targetBrightness = targetBrightness,
78767862 .layerAlpha = layerAlpha,
78777863 .regionSampling = regionSampling,
0 commit comments