348 lines
19 KiB
Diff
348 lines
19 KiB
Diff
From b12faaf3064de58caf0f6bfaf7fcac5a47f5024d Mon Sep 17 00:00:00 2001
|
|
From: Peter Cai <peter@typeblog.net>
|
|
Date: Sun, 16 Mar 2025 12:54:56 -0400
|
|
Subject: [PATCH 4/7] Revert "Remove flag single_hop_screenshots"
|
|
|
|
This reverts commit 16c4c32c55231dc241c386a0423710baa452b7de.
|
|
|
|
Change-Id: Ib1618cd4e1f83ba1f211a04429538b32e8de79da
|
|
---
|
|
.../surfaceflinger/RegionSamplingThread.cpp | 22 ++-
|
|
services/surfaceflinger/SurfaceFlinger.cpp | 184 ++++++++++++++----
|
|
services/surfaceflinger/SurfaceFlinger.h | 10 +-
|
|
.../surfaceflinger/common/FlagManager.cpp | 2 +
|
|
.../common/include/common/FlagManager.h | 1 +
|
|
.../tests/unittests/TestableSurfaceFlinger.h | 3 +-
|
|
6 files changed, 171 insertions(+), 51 deletions(-)
|
|
|
|
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
|
|
index 21d3396ebe..08f831c8e5 100644
|
|
--- a/services/surfaceflinger/RegionSamplingThread.cpp
|
|
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
|
|
@@ -353,13 +353,21 @@ void RegionSamplingThread::captureSample() {
|
|
sampledBounds.getSize(), ui::Dataspace::V0_SRGB, displayWeak,
|
|
RenderArea::Options::CAPTURE_SECURE_LAYERS);
|
|
|
|
- std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
|
|
- auto displayState =
|
|
- mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
|
|
- FenceResult fenceResult =
|
|
- mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling, kGrayscale,
|
|
- kIsProtected, kAttachGainmap, nullptr, displayState, layers)
|
|
- .get();
|
|
+ FenceResult fenceResult;
|
|
+ if (FlagManager::getInstance().single_hop_screenshot()) {
|
|
+ std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
|
|
+ auto displayState =
|
|
+ mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
|
|
+ fenceResult = mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling,
|
|
+ kGrayscale, kIsProtected, kAttachGainmap, nullptr,
|
|
+ displayState, layers)
|
|
+ .get();
|
|
+ } else {
|
|
+ fenceResult = mFlinger.captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn,
|
|
+ buffer, kRegionSampling, kGrayscale,
|
|
+ kIsProtected, kAttachGainmap, nullptr)
|
|
+ .get();
|
|
+ }
|
|
if (fenceResult.ok()) {
|
|
fenceResult.value()->waitForever(LOG_TAG);
|
|
}
|
|
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
|
|
index 896d13d31d..852a8b81e1 100644
|
|
--- a/services/surfaceflinger/SurfaceFlinger.cpp
|
|
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
|
|
@@ -7389,41 +7389,79 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil
|
|
return;
|
|
}
|
|
|
|
- std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
|
|
- auto displayState = getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
|
|
-
|
|
- const bool supportsProtected = getRenderEngine().supportsProtectedContent();
|
|
- bool hasProtectedLayer = false;
|
|
- if (allowProtected && supportsProtected) {
|
|
- hasProtectedLayer = layersHasProtectedLayer(layers);
|
|
- }
|
|
- const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
|
|
- const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
|
|
- GRALLOC_USAGE_HW_TEXTURE |
|
|
- (isProtected ? GRALLOC_USAGE_PROTECTED
|
|
- : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
|
- sp<GraphicBuffer> buffer =
|
|
- getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
|
|
- static_cast<android_pixel_format>(reqPixelFormat),
|
|
- 1 /* layerCount */, usage, "screenshot");
|
|
-
|
|
- const status_t bufferStatus = buffer->initCheck();
|
|
- if (bufferStatus != OK) {
|
|
- // Animations may end up being really janky, but don't crash here.
|
|
- // Otherwise an irreponsible process may cause an SF crash by allocating
|
|
- // too much.
|
|
- ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
|
|
- invokeScreenCaptureError(bufferStatus, captureListener);
|
|
- return;
|
|
+ if (FlagManager::getInstance().single_hop_screenshot()) {
|
|
+ std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
|
|
+ auto displayState =
|
|
+ getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
|
|
+
|
|
+ const bool supportsProtected = getRenderEngine().supportsProtectedContent();
|
|
+ bool hasProtectedLayer = false;
|
|
+ if (allowProtected && supportsProtected) {
|
|
+ hasProtectedLayer = layersHasProtectedLayer(layers);
|
|
+ }
|
|
+ const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
|
|
+ const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
|
|
+ GRALLOC_USAGE_HW_TEXTURE |
|
|
+ (isProtected ? GRALLOC_USAGE_PROTECTED
|
|
+ : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
|
+ sp<GraphicBuffer> buffer =
|
|
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
|
|
+ static_cast<android_pixel_format>(reqPixelFormat),
|
|
+ 1 /* layerCount */, usage, "screenshot");
|
|
+
|
|
+ const status_t bufferStatus = buffer->initCheck();
|
|
+ if (bufferStatus != OK) {
|
|
+ // Animations may end up being really janky, but don't crash here.
|
|
+ // Otherwise an irreponsible process may cause an SF crash by allocating
|
|
+ // too much.
|
|
+ ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
|
|
+ invokeScreenCaptureError(bufferStatus, captureListener);
|
|
+ return;
|
|
+ }
|
|
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
|
|
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
|
|
+ renderengine::impl::ExternalTexture::Usage::
|
|
+ WRITEABLE);
|
|
+ auto futureFence = captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */,
|
|
+ grayscale, isProtected, attachGainmap, captureListener,
|
|
+ displayState, layers);
|
|
+ futureFence.get();
|
|
+
|
|
+ } else {
|
|
+ const bool supportsProtected = getRenderEngine().supportsProtectedContent();
|
|
+ bool hasProtectedLayer = false;
|
|
+ if (allowProtected && supportsProtected) {
|
|
+ auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get();
|
|
+ hasProtectedLayer = layersHasProtectedLayer(layers);
|
|
+ }
|
|
+ const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
|
|
+ const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
|
|
+ GRALLOC_USAGE_HW_TEXTURE |
|
|
+ (isProtected ? GRALLOC_USAGE_PROTECTED
|
|
+ : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
|
+ sp<GraphicBuffer> buffer =
|
|
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
|
|
+ static_cast<android_pixel_format>(reqPixelFormat),
|
|
+ 1 /* layerCount */, usage, "screenshot");
|
|
+
|
|
+ const status_t bufferStatus = buffer->initCheck();
|
|
+ if (bufferStatus != OK) {
|
|
+ // Animations may end up being really janky, but don't crash here.
|
|
+ // Otherwise an irreponsible process may cause an SF crash by allocating
|
|
+ // too much.
|
|
+ ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
|
|
+ invokeScreenCaptureError(bufferStatus, captureListener);
|
|
+ return;
|
|
+ }
|
|
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
|
|
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
|
|
+ renderengine::impl::ExternalTexture::Usage::
|
|
+ WRITEABLE);
|
|
+ auto futureFence = captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, texture,
|
|
+ false /* regionSampling */, grayscale,
|
|
+ isProtected, attachGainmap, captureListener);
|
|
+ futureFence.get();
|
|
}
|
|
- const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
|
|
- renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
|
|
- renderengine::impl::ExternalTexture::Usage::
|
|
- WRITEABLE);
|
|
- auto futureFence =
|
|
- captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */, grayscale,
|
|
- isProtected, attachGainmap, captureListener, displayState, layers);
|
|
- futureFence.get();
|
|
}
|
|
|
|
std::optional<SurfaceFlinger::OutputCompositionState>
|
|
@@ -7489,7 +7527,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
|
|
|
|
ftl::SharedFuture<FenceResult> renderFuture =
|
|
renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
|
|
- captureResults, displayState, layers);
|
|
+ attachGainmap, captureResults, displayState, layers);
|
|
|
|
if (captureResults.capturedHdrLayers && attachGainmap &&
|
|
FlagManager::getInstance().true_hdr_screenshots()) {
|
|
@@ -7524,7 +7562,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
|
|
ScreenCaptureResults unusedResults;
|
|
ftl::SharedFuture<FenceResult> hdrRenderFuture =
|
|
renderScreenImpl(renderArea.get(), hdrTexture, regionSampling, grayscale,
|
|
- isProtected, unusedResults, displayState, layers);
|
|
+ isProtected, attachGainmap, unusedResults, displayState,
|
|
+ layers);
|
|
|
|
renderFuture =
|
|
ftl::Future(std::move(renderFuture))
|
|
@@ -7570,10 +7609,67 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
|
|
return renderFuture;
|
|
}
|
|
|
|
+ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshotLegacy(
|
|
+ RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
|
|
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
|
|
+ bool grayscale, bool isProtected, bool attachGainmap,
|
|
+ const sp<IScreenCaptureListener>& captureListener) {
|
|
+ SFTRACE_CALL();
|
|
+
|
|
+ auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
|
|
+ kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
|
|
+ auto layers = getLayerSnapshotsFn();
|
|
+ auto displayState = getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
|
|
+
|
|
+ ScreenCaptureResults captureResults;
|
|
+ std::unique_ptr<const RenderArea> renderArea =
|
|
+ std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
|
|
+ renderAreaBuilder);
|
|
+
|
|
+ if (!renderArea) {
|
|
+ ALOGW("Skipping screen capture because of invalid render area.");
|
|
+ if (captureListener) {
|
|
+ captureResults.fenceResult = base::unexpected(NO_MEMORY);
|
|
+ captureListener->onScreenCaptureCompleted(captureResults);
|
|
+ }
|
|
+ return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
|
|
+ }
|
|
+
|
|
+ ftl::SharedFuture<FenceResult> renderFuture =
|
|
+ renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
|
|
+ attachGainmap, captureResults, displayState, layers);
|
|
+
|
|
+ if (captureListener) {
|
|
+ // Defer blocking on renderFuture back to the Binder thread.
|
|
+ return ftl::Future(std::move(renderFuture))
|
|
+ .then([captureListener, captureResults = std::move(captureResults)](
|
|
+ FenceResult fenceResult) mutable -> FenceResult {
|
|
+ captureResults.fenceResult = std::move(fenceResult);
|
|
+ captureListener->onScreenCaptureCompleted(captureResults);
|
|
+ return base::unexpected(NO_ERROR);
|
|
+ })
|
|
+ .share();
|
|
+ }
|
|
+ return renderFuture;
|
|
+ };
|
|
+
|
|
+ // TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number
|
|
+ // of calls on the main thread.
|
|
+ auto future =
|
|
+ mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));
|
|
+
|
|
+ // Flatten nested futures.
|
|
+ auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
|
|
+ return future;
|
|
+ });
|
|
+
|
|
+ return chain.share();
|
|
+}
|
|
+
|
|
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
|
|
const RenderArea* renderArea, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
|
|
- bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
|
|
- std::optional<OutputCompositionState>& displayState,
|
|
+ bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
|
|
+ ScreenCaptureResults& captureResults, std::optional<OutputCompositionState>& displayState,
|
|
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
|
|
SFTRACE_CALL();
|
|
|
|
@@ -7719,9 +7815,15 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
|
|
//
|
|
// TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call
|
|
// to CompositionEngine::present.
|
|
- ftl::SharedFuture<FenceResult> presentFuture = mRenderEngine->isThreaded()
|
|
- ? ftl::yield(present()).share()
|
|
- : mScheduler->schedule(std::move(present)).share();
|
|
+ ftl::SharedFuture<FenceResult> presentFuture;
|
|
+ if (FlagManager::getInstance().single_hop_screenshot()) {
|
|
+ presentFuture = mRenderEngine->isThreaded()
|
|
+ ? ftl::yield(present()).share()
|
|
+ : mScheduler->schedule(std::move(present)).share();
|
|
+ } else {
|
|
+ presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share()
|
|
+ : ftl::yield(present()).share();
|
|
+ }
|
|
|
|
return presentFuture;
|
|
}
|
|
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
|
|
index 1e2c08747b..835cb572b4 100644
|
|
--- a/services/surfaceflinger/SurfaceFlinger.h
|
|
+++ b/services/surfaceflinger/SurfaceFlinger.h
|
|
@@ -885,10 +885,16 @@ private:
|
|
std::optional<OutputCompositionState>& displayState,
|
|
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
|
|
|
|
+ ftl::SharedFuture<FenceResult> captureScreenshotLegacy(
|
|
+ RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
|
|
+ const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
|
|
+ bool grayscale, bool isProtected, bool attachGainmap,
|
|
+ const sp<IScreenCaptureListener>&);
|
|
+
|
|
ftl::SharedFuture<FenceResult> renderScreenImpl(
|
|
const RenderArea*, const std::shared_ptr<renderengine::ExternalTexture>&,
|
|
- bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&,
|
|
- std::optional<OutputCompositionState>& displayState,
|
|
+ bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
|
|
+ ScreenCaptureResults&, std::optional<OutputCompositionState>& displayState,
|
|
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
|
|
|
|
void readPersistentProperties();
|
|
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
|
|
index 5e78426c77..5c417ba748 100644
|
|
--- a/services/surfaceflinger/common/FlagManager.cpp
|
|
+++ b/services/surfaceflinger/common/FlagManager.cpp
|
|
@@ -166,6 +166,7 @@ void FlagManager::dump(std::string& result) const {
|
|
DUMP_ACONFIG_FLAG(skip_invisible_windows_in_input);
|
|
DUMP_ACONFIG_FLAG(begone_bright_hlg);
|
|
DUMP_ACONFIG_FLAG(window_blur_kawase2);
|
|
+ DUMP_ACONFIG_FLAG(single_hop_screenshot);
|
|
|
|
#undef DUMP_ACONFIG_FLAG
|
|
#undef DUMP_LEGACY_SERVER_FLAG
|
|
@@ -259,6 +260,7 @@ FLAG_MANAGER_ACONFIG_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_scr
|
|
FLAG_MANAGER_ACONFIG_FLAG(override_trusted_overlay, "");
|
|
FLAG_MANAGER_ACONFIG_FLAG(flush_buffer_slots_to_uncache, "");
|
|
FLAG_MANAGER_ACONFIG_FLAG(force_compile_graphite_renderengine, "");
|
|
+FLAG_MANAGER_ACONFIG_FLAG(single_hop_screenshot, "");
|
|
FLAG_MANAGER_ACONFIG_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
|
|
FLAG_MANAGER_ACONFIG_FLAG(display_config_error_hal, "");
|
|
FLAG_MANAGER_ACONFIG_FLAG(connected_display_hdr, "debug.sf.connected_display_hdr");
|
|
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
|
|
index d8887f538f..15284ba0ee 100644
|
|
--- a/services/surfaceflinger/common/include/common/FlagManager.h
|
|
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
|
|
@@ -95,6 +95,7 @@ public:
|
|
bool override_trusted_overlay() const;
|
|
bool flush_buffer_slots_to_uncache() const;
|
|
bool force_compile_graphite_renderengine() const;
|
|
+ bool single_hop_screenshot() const;
|
|
bool trace_frame_rate_override() const;
|
|
bool true_hdr_screenshots() const;
|
|
bool display_config_error_hal() const;
|
|
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
|
|
index 7f0b7a6585..fd8bc0d22d 100644
|
|
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
|
|
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
|
|
@@ -475,7 +475,8 @@ public:
|
|
|
|
return mFlinger->renderScreenImpl(renderArea.get(), buffer, regionSampling,
|
|
false /* grayscale */, false /* isProtected */,
|
|
- captureResults, displayState, layers);
|
|
+ false /* attachGainmap */, captureResults, displayState,
|
|
+ layers);
|
|
}
|
|
|
|
auto getLayerSnapshotsForScreenshotsFn(ui::LayerStack layerStack, uint32_t uid) {
|
|
--
|
|
2.48.1
|
|
|