Skip to content

Commit 398819e

Browse files
Melody HsuAndroid (Google) Code Review
authored andcommitted
Merge "Extract DisplayState elements into ScreenshotArgs" into main
2 parents ff04516 + 36cb1ed commit 398819e

4 files changed

Lines changed: 92 additions & 95 deletions

File tree

services/surfaceflinger/RegionSamplingThread.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,10 @@ void RegionSamplingThread::captureSample() {
356356
screenshotArgs.seamlessTransition = false;
357357

358358
std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
359-
auto displayState =
360-
mFlinger.getSnapshotsFromMainThread(screenshotArgs, getLayerSnapshotsFn, layers);
361-
FenceResult fenceResult =
362-
mFlinger.captureScreenshot(screenshotArgs, buffer, kRegionSampling, kGrayscale,
363-
kIsProtected, nullptr, displayState, layers)
364-
.get();
359+
mFlinger.getSnapshotsFromMainThread(screenshotArgs, getLayerSnapshotsFn, layers);
360+
FenceResult fenceResult = mFlinger.captureScreenshot(screenshotArgs, buffer, kRegionSampling,
361+
kGrayscale, kIsProtected, nullptr, layers)
362+
.get();
365363
if (fenceResult.ok()) {
366364
fenceResult.value()->waitForever(LOG_TAG);
367365
}

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 62 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -7196,14 +7196,13 @@ status_t SurfaceFlinger::setSchedAttr(bool enabled) {
71967196

71977197
namespace {
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

76867691
ftl::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

77497748
ftl::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,

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -896,32 +896,41 @@ class SurfaceFlinger : public BnSurfaceComposer,
896896
// If true, the render result may be used for system animations
897897
// that must preserve the exact colors of the display
898898
bool seamlessTransition{false};
899+
900+
// Current display brightness of the output composition state
901+
float displayBrightnessNits{-1.f};
902+
903+
// SDR white point of the output composition state
904+
float sdrWhitePointNits{-1.f};
905+
906+
// Current active color mode of the output composition state
907+
ui::ColorMode colorMode{ui::ColorMode::NATIVE};
908+
909+
// Current active render intent of the output composition state
910+
ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC};
899911
};
900912

901-
std::optional<OutputCompositionState> getSnapshotsFromMainThread(
902-
ScreenshotArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn,
903-
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
913+
bool getSnapshotsFromMainThread(ScreenshotArgs& args,
914+
GetLayerSnapshotsFunction getLayerSnapshotsFn,
915+
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
904916

905917
void captureScreenCommon(ScreenshotArgs& args, GetLayerSnapshotsFunction, ui::Size bufferSize,
906918
ui::PixelFormat, bool allowProtected, bool grayscale,
907919
const sp<IScreenCaptureListener>&);
908920

909-
std::optional<OutputCompositionState> getDisplayStateOnMainThread(ScreenshotArgs& args)
910-
REQUIRES(kMainThreadContext);
921+
bool getDisplayStateOnMainThread(ScreenshotArgs& args) REQUIRES(kMainThreadContext);
911922

912923
ftl::SharedFuture<FenceResult> captureScreenshot(
913-
const ScreenshotArgs& args,
914-
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
915-
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener,
916-
const std::optional<OutputCompositionState>& displayState,
924+
ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
925+
bool regionSampling, bool grayscale, bool isProtected,
926+
const sp<IScreenCaptureListener>& captureListener,
917927
const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
918928
const std::shared_ptr<renderengine::ExternalTexture>& hdrBuffer = nullptr,
919929
const std::shared_ptr<renderengine::ExternalTexture>& gainmapBuffer = nullptr);
920930

921931
ftl::SharedFuture<FenceResult> renderScreenImpl(
922-
const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>&,
932+
ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>&,
923933
bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&,
924-
const std::optional<OutputCompositionState>& displayState,
925934
const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
926935

927936
void readPersistentProperties();

services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class TestableSurfaceFlinger {
469469
ftl::FakeGuard guard(kMainThreadContext);
470470

471471
ScreenCaptureResults captureResults;
472-
auto displayState = std::optional{display->getCompositionDisplay()->getState()};
472+
const auto& state = display->getCompositionDisplay()->getState();
473473
auto layers = getLayerSnapshotsFn();
474474

475475
SurfaceFlinger::ScreenshotArgs screenshotArgs;
@@ -480,10 +480,14 @@ class TestableSurfaceFlinger {
480480
screenshotArgs.dataspace = dataspace;
481481
screenshotArgs.isSecure = isSecure;
482482
screenshotArgs.seamlessTransition = seamlessTransition;
483+
screenshotArgs.displayBrightnessNits = state.displayBrightnessNits;
484+
screenshotArgs.sdrWhitePointNits = state.sdrWhitePointNits;
485+
screenshotArgs.renderIntent = state.renderIntent;
486+
screenshotArgs.colorMode = state.colorMode;
483487

484488
return mFlinger->renderScreenImpl(screenshotArgs, buffer, regionSampling,
485489
false /* grayscale */, false /* isProtected */,
486-
captureResults, displayState, layers);
490+
captureResults, layers);
487491
}
488492

489493
auto getLayerSnapshotsForScreenshotsFn(ui::LayerStack layerStack, uint32_t uid) {

0 commit comments

Comments
 (0)