SF: refactor renderScreenImpl to use CompositionEngine
Bug: 238643986
Test: presubmits
Test: go/wm-smoke
Change-Id: I6dbbcd5ce5070ec1d801dca55b5bb89fafe839cb
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 999c03f..14fdd12 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -189,6 +189,7 @@
"Scheduler/VsyncConfiguration.cpp",
"Scheduler/VsyncModulator.cpp",
"Scheduler/VsyncSchedule.cpp",
+ "ScreenCaptureOutput.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceFlingerDefaultFactory.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 23d5570..e06da33 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -134,9 +134,11 @@
void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override{};
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
+ virtual renderengine::DisplaySettings generateClientCompositionDisplaySettings() const;
std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
bool supportsProtectedContent, ui::Dataspace outputDataspace,
std::vector<LayerFE*> &outLayerFEs) override;
+ virtual bool layerNeedsFiltering(const OutputLayer*) const;
void appendRegionFlashRequests(const Region&, std::vector<LayerFE::LayerSettings>&) override;
void setExpensiveRenderingExpected(bool enabled) override;
void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) override;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index c2b1f06..d1daca6 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1226,40 +1226,8 @@
ALOGV("hasClientComposition");
- renderengine::DisplaySettings clientCompositionDisplay;
- clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.getContent();
- clientCompositionDisplay.clip = outputState.layerStackSpace.getContent();
- clientCompositionDisplay.orientation =
- ui::Transform::toRotationFlags(outputState.displaySpace.getOrientation());
- clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
- ? outputState.dataspace
- : ui::Dataspace::UNKNOWN;
-
- // If we have a valid current display brightness use that, otherwise fall back to the
- // display's max desired
- clientCompositionDisplay.currentLuminanceNits = outputState.displayBrightnessNits > 0.f
- ? outputState.displayBrightnessNits
- : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
- clientCompositionDisplay.maxLuminance =
- mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
- clientCompositionDisplay.targetLuminanceNits =
- outputState.clientTargetBrightness * outputState.displayBrightnessNits;
- clientCompositionDisplay.dimmingStage = outputState.clientTargetDimmingStage;
- clientCompositionDisplay.renderIntent =
- static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(
- outputState.renderIntent);
-
- // Compute the global color transform matrix.
- clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
- for (auto& info : outputState.borderInfoList) {
- renderengine::BorderRenderInfo borderInfo;
- borderInfo.width = info.width;
- borderInfo.color = info.color;
- borderInfo.combinedRegion = info.combinedRegion;
- clientCompositionDisplay.borderInfoList.emplace_back(std::move(borderInfo));
- }
- clientCompositionDisplay.deviceHandlesColorTransform =
- outputState.usesDeviceComposition || getSkipColorTransform();
+ renderengine::DisplaySettings clientCompositionDisplay =
+ generateClientCompositionDisplaySettings();
// Generate the client composition requests for the layers on this output.
auto& renderEngine = getCompositionEngine().getRenderEngine();
@@ -1350,6 +1318,46 @@
return base::unique_fd(fence->dup());
}
+renderengine::DisplaySettings Output::generateClientCompositionDisplaySettings() const {
+ const auto& outputState = getState();
+
+ renderengine::DisplaySettings clientCompositionDisplay;
+ clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.getContent();
+ clientCompositionDisplay.clip = outputState.layerStackSpace.getContent();
+ clientCompositionDisplay.orientation =
+ ui::Transform::toRotationFlags(outputState.displaySpace.getOrientation());
+ clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
+ ? outputState.dataspace
+ : ui::Dataspace::UNKNOWN;
+
+ // If we have a valid current display brightness use that, otherwise fall back to the
+ // display's max desired
+ clientCompositionDisplay.currentLuminanceNits = outputState.displayBrightnessNits > 0.f
+ ? outputState.displayBrightnessNits
+ : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+ clientCompositionDisplay.maxLuminance =
+ mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+ clientCompositionDisplay.targetLuminanceNits =
+ outputState.clientTargetBrightness * outputState.displayBrightnessNits;
+ clientCompositionDisplay.dimmingStage = outputState.clientTargetDimmingStage;
+ clientCompositionDisplay.renderIntent =
+ static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(
+ outputState.renderIntent);
+
+ // Compute the global color transform matrix.
+ clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
+ for (auto& info : outputState.borderInfoList) {
+ renderengine::BorderRenderInfo borderInfo;
+ borderInfo.width = info.width;
+ borderInfo.color = info.color;
+ borderInfo.combinedRegion = info.combinedRegion;
+ clientCompositionDisplay.borderInfoList.emplace_back(std::move(borderInfo));
+ }
+ clientCompositionDisplay.deviceHandlesColorTransform =
+ outputState.usesDeviceComposition || getSkipColorTransform();
+ return clientCompositionDisplay;
+}
+
std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
bool supportsProtectedContent, ui::Dataspace outputDataspace, std::vector<LayerFE*>& outLayerFEs) {
std::vector<LayerFE::LayerSettings> clientCompositionLayers;
@@ -1415,7 +1423,7 @@
Enabled);
compositionengine::LayerFE::ClientCompositionTargetSettings
targetSettings{.clip = clip,
- .needsFiltering = layer->needsFiltering() ||
+ .needsFiltering = layerNeedsFiltering(layer) ||
outputState.needsFiltering,
.isSecure = outputState.isSecure,
.supportsProtectedContent = supportsProtectedContent,
@@ -1446,6 +1454,10 @@
return clientCompositionLayers;
}
+bool Output::layerNeedsFiltering(const compositionengine::OutputLayer* layer) const {
+ return layer->needsFiltering();
+}
+
void Output::appendRegionFlashRequests(
const Region& flashRegion, std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
if (flashRegion.isEmpty()) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 83a46ae..2a18521 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3499,6 +3499,12 @@
return mSnapshot.get();
}
+sp<LayerFE> Layer::copyCompositionEngineLayerFE() const {
+ auto result = mFlinger->getFactory().createLayerFE(mLayerFE->getDebugName());
+ result->mSnapshot = std::make_unique<LayerSnapshot>(*mSnapshot);
+ return result;
+}
+
void Layer::useSurfaceDamage() {
if (mFlinger->mForceFullDamage) {
surfaceDamageRegion = Region::INVALID_REGION;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a3c4e59..9585fa9 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -323,6 +323,7 @@
ui::Dataspace getRequestedDataSpace() const;
virtual sp<LayerFE> getCompositionEngineLayerFE() const;
+ virtual sp<LayerFE> copyCompositionEngineLayerFE() const;
const LayerSnapshot* getLayerSnapshot() const;
LayerSnapshot* editLayerSnapshot();
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
new file mode 100644
index 0000000..8f93ba4
--- /dev/null
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ScreenCaptureOutput.h"
+#include "ScreenCaptureRenderSurface.h"
+
+#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/DisplayColorProfileCreationArgs.h>
+#include <compositionengine/impl/DisplayColorProfile.h>
+#include <ui/Rotation.h>
+
+namespace android {
+
+std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs&& args) {
+ std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
+ ScreenCaptureOutput, compositionengine::CompositionEngine,
+ ScreenCaptureOutputArgs&&>(args.compositionEngine, std::move(args));
+ output->editState().isSecure = args.renderArea.isSecure();
+ output->setCompositionEnabled(true);
+ output->setLayerFilter({args.layerStack});
+ output->setRenderSurface(std::make_unique<ScreenCaptureRenderSurface>(std::move(args.buffer)));
+ output->setDisplayBrightness(args.sdrWhitePointNits, args.displayBrightnessNits);
+
+ output->setDisplayColorProfile(std::make_unique<compositionengine::impl::DisplayColorProfile>(
+ compositionengine::DisplayColorProfileCreationArgsBuilder()
+ .setHasWideColorGamut(true)
+ .Build()));
+
+ ui::Rotation orientation = ui::Transform::toRotation(args.renderArea.getRotationFlags());
+ Rect orientedDisplaySpaceRect{args.renderArea.getReqWidth(), args.renderArea.getReqHeight()};
+ output->setProjection(orientation, args.renderArea.getLayerStackSpaceRect(),
+ orientedDisplaySpaceRect);
+
+ Rect sourceCrop = args.renderArea.getSourceCrop();
+ output->setDisplaySize({sourceCrop.getWidth(), sourceCrop.getHeight()});
+
+ return output;
+}
+
+ScreenCaptureOutput::ScreenCaptureOutput(ScreenCaptureOutputArgs&& args)
+ : mRenderArea(args.renderArea),
+ mFilterForScreenshot(std::move(args.filterForScreenshot)),
+ mColorProfile(args.colorProfile),
+ mRegionSampling(args.regionSampling) {}
+
+void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) {
+ auto& outputState = editState();
+ outputState.dataspace = mColorProfile.dataspace;
+ outputState.renderIntent = mColorProfile.renderIntent;
+}
+
+renderengine::DisplaySettings ScreenCaptureOutput::generateClientCompositionDisplaySettings()
+ const {
+ auto clientCompositionDisplay =
+ compositionengine::impl::Output::generateClientCompositionDisplaySettings();
+ clientCompositionDisplay.clip = mRenderArea.getSourceCrop();
+ clientCompositionDisplay.targetLuminanceNits = -1;
+ return clientCompositionDisplay;
+}
+
+std::vector<compositionengine::LayerFE::LayerSettings>
+ScreenCaptureOutput::generateClientCompositionRequests(
+ bool supportsProtectedContent, ui::Dataspace outputDataspace,
+ std::vector<compositionengine::LayerFE*>& outLayerFEs) {
+ auto clientCompositionLayers = compositionengine::impl::Output::
+ generateClientCompositionRequests(supportsProtectedContent, outputDataspace,
+ outLayerFEs);
+
+ if (mRegionSampling) {
+ for (auto& layer : clientCompositionLayers) {
+ layer.backgroundBlurRadius = 0;
+ layer.blurRegions.clear();
+ }
+ }
+
+ Rect sourceCrop = mRenderArea.getSourceCrop();
+ compositionengine::LayerFE::LayerSettings fillLayer;
+ fillLayer.source.buffer.buffer = nullptr;
+ fillLayer.source.solidColor = half3(0.0f, 0.0f, 0.0f);
+ fillLayer.geometry.boundaries =
+ FloatRect(static_cast<float>(sourceCrop.left), static_cast<float>(sourceCrop.top),
+ static_cast<float>(sourceCrop.right), static_cast<float>(sourceCrop.bottom));
+ fillLayer.alpha = half(RenderArea::getCaptureFillValue(mRenderArea.getCaptureFill()));
+ clientCompositionLayers.insert(clientCompositionLayers.begin(), fillLayer);
+
+ return clientCompositionLayers;
+}
+
+bool ScreenCaptureOutput::layerNeedsFiltering(const compositionengine::OutputLayer* layer) const {
+ return mRenderArea.needsFiltering() ||
+ mFilterForScreenshot.find(&layer->getLayerFE()) != mFilterForScreenshot.end();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
new file mode 100644
index 0000000..61b5ddb
--- /dev/null
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/RenderSurface.h>
+#include <compositionengine/impl/Output.h>
+#include <ui/Rect.h>
+
+#include "RenderArea.h"
+
+namespace android {
+
+struct ScreenCaptureOutputArgs {
+ const compositionengine::CompositionEngine& compositionEngine;
+ const compositionengine::Output::ColorProfile& colorProfile;
+ const RenderArea& renderArea;
+ ui::LayerStack layerStack;
+ std::shared_ptr<renderengine::ExternalTexture> buffer;
+ float sdrWhitePointNits;
+ float displayBrightnessNits;
+ std::unordered_set<compositionengine::LayerFE*> filterForScreenshot;
+ bool regionSampling;
+};
+
+// ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer.
+//
+// SurfaceFlinger passes instances of ScreenCaptureOutput to CompositionEngine in calls to
+// SurfaceFlinger::captureLayers and SurfaceFlinger::captureDisplay.
+class ScreenCaptureOutput : public compositionengine::impl::Output {
+public:
+ ScreenCaptureOutput(ScreenCaptureOutputArgs&&);
+
+ void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
+
+ std::vector<compositionengine::LayerFE::LayerSettings> generateClientCompositionRequests(
+ bool supportsProtectedContent, ui::Dataspace outputDataspace,
+ std::vector<compositionengine::LayerFE*>& outLayerFEs) override;
+
+ bool layerNeedsFiltering(const compositionengine::OutputLayer*) const override;
+
+protected:
+ bool getSkipColorTransform() const override { return false; }
+ renderengine::DisplaySettings generateClientCompositionDisplaySettings() const override;
+
+private:
+ const RenderArea& mRenderArea;
+ const std::unordered_set<compositionengine::LayerFE*> mFilterForScreenshot;
+ const compositionengine::Output::ColorProfile& mColorProfile;
+ const bool mRegionSampling;
+};
+
+std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs&&);
+
+} // namespace android
diff --git a/services/surfaceflinger/ScreenCaptureRenderSurface.h b/services/surfaceflinger/ScreenCaptureRenderSurface.h
new file mode 100644
index 0000000..2097300
--- /dev/null
+++ b/services/surfaceflinger/ScreenCaptureRenderSurface.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <compositionengine/RenderSurface.h>
+#include <renderengine/impl/ExternalTexture.h>
+#include <ui/Fence.h>
+#include <ui/Size.h>
+
+namespace android {
+
+// ScreenCaptureRenderSurface is a RenderSurface that returns a preallocated buffer used by
+// ScreenCaptureOutput.
+class ScreenCaptureRenderSurface : public compositionengine::RenderSurface {
+public:
+ ScreenCaptureRenderSurface(std::shared_ptr<renderengine::ExternalTexture> buffer)
+ : mBuffer(std::move(buffer)){};
+
+ std::shared_ptr<renderengine::ExternalTexture> dequeueBuffer(
+ base::unique_fd* /* bufferFence */) override {
+ return mBuffer;
+ }
+
+ void queueBuffer(base::unique_fd readyFence) override {
+ mRenderFence = sp<Fence>::make(readyFence.release());
+ }
+
+ const sp<Fence>& getClientTargetAcquireFence() const override { return mRenderFence; }
+
+ bool supportsCompositionStrategyPrediction() const override { return false; }
+
+ bool isValid() const override { return true; }
+
+ void initialize() override {}
+
+ const ui::Size& getSize() const override { return mSize; }
+
+ bool isProtected() const override { return mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED; }
+
+ void setDisplaySize(const ui::Size&) override {}
+
+ void setBufferDataspace(ui::Dataspace) override {}
+
+ void setBufferPixelFormat(ui::PixelFormat) override {}
+
+ void setProtected(bool /* useProtected */) override {}
+
+ status_t beginFrame(bool /* mustRecompose */) override { return OK; }
+
+ void prepareFrame(bool /* usesClientComposition */, bool /* usesDeviceComposition */) override {
+ }
+
+ void onPresentDisplayCompleted() override {}
+
+ void dump(std::string& /* result */) const override {}
+
+private:
+ std::shared_ptr<renderengine::ExternalTexture> mBuffer;
+
+ sp<Fence> mRenderFence = Fence::NO_FENCE;
+
+ ui::Size mSize;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 999af30..56fa96b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -44,10 +44,12 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/Display.h>
#include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/DisplayColorProfileCreationArgs.h>
#include <compositionengine/DisplayCreationArgs.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/RenderSurface.h>
+#include <compositionengine/impl/DisplayColorProfile.h>
#include <compositionengine/impl/OutputCompositionState.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <configstore/Utils.h>
@@ -137,6 +139,7 @@
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VsyncConfiguration.h"
+#include "ScreenCaptureOutput.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlingerProperties.h"
#include "TimeStats/TimeStats.h"
@@ -6256,7 +6259,8 @@
return BAD_VALUE;
}
- Rect layerStackSpaceRect(0, 0, reqSize.width, reqSize.height);
+ Rect layerStackSpaceRect(crop.left, crop.top, crop.left + reqSize.width,
+ crop.top + reqSize.height);
bool childrenOnly = args.childrenOnly;
RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> {
return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace,
@@ -6376,7 +6380,7 @@
ftl::SharedFuture<FenceResult> renderFuture;
renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- renderFuture = renderScreenImpl(*renderArea, traverseLayers, buffer,
+ renderFuture = renderScreenImpl(std::move(renderArea), traverseLayers, buffer,
canCaptureBlackoutContent, regionSampling,
grayscale, captureResults);
});
@@ -6404,19 +6408,19 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ std::unique_ptr<RenderArea> renderArea, TraverseLayersFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
ScreenCaptureResults& captureResults) {
ATRACE_CALL();
+ size_t layerCount = 0;
traverseLayers([&](Layer* layer) {
+ layerCount++;
captureResults.capturedSecureLayers =
captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure());
});
- const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
-
// We allow the system server to take screenshots of secure layers for
// use in situations like the Screen-rotation animation and place
// the impetus on WindowManager to not persist them.
@@ -6426,8 +6430,8 @@
}
captureResults.buffer = buffer->getBuffer();
- auto dataspace = renderArea.getReqDataSpace();
- auto parent = renderArea.getParentLayer();
+ auto dataspace = renderArea->getReqDataSpace();
+ auto parent = renderArea->getParentLayer();
auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
auto sdrWhitePointNits = DisplayDevice::sDefaultMaxLumiance;
auto displayBrightnessNits = DisplayDevice::sDefaultMaxLumiance;
@@ -6449,122 +6453,107 @@
}
captureResults.capturedDataspace = dataspace;
- const auto reqWidth = renderArea.getReqWidth();
- const auto reqHeight = renderArea.getReqHeight();
- const auto sourceCrop = renderArea.getSourceCrop();
- const auto transform = renderArea.getTransform();
- const auto rotation = renderArea.getRotationFlags();
- const auto& layerStackSpaceRect = renderArea.getLayerStackSpaceRect();
+ const auto transform = renderArea->getTransform();
+ const auto display = renderArea->getDisplayDevice();
- renderengine::DisplaySettings clientCompositionDisplay;
- std::vector<compositionengine::LayerFE::LayerSettings> clientCompositionLayers;
-
- // assume that bounds are never offset, and that they are the same as the
- // buffer bounds.
- clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
- clientCompositionDisplay.clip = sourceCrop;
- clientCompositionDisplay.orientation = rotation;
-
- clientCompositionDisplay.outputDataspace = dataspace;
- clientCompositionDisplay.currentLuminanceNits = displayBrightnessNits;
- clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
- clientCompositionDisplay.renderIntent =
- static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(renderIntent);
-
- const float colorSaturation = grayscale ? 0 : 1;
- clientCompositionDisplay.colorTransform = calculateColorMatrix(colorSaturation);
-
- const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
-
- compositionengine::LayerFE::LayerSettings fillLayer;
- fillLayer.source.buffer.buffer = nullptr;
- fillLayer.source.solidColor = half3(0.0, 0.0, 0.0);
- fillLayer.geometry.boundaries =
- FloatRect(sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
- fillLayer.alpha = half(alpha);
- clientCompositionLayers.push_back(fillLayer);
-
- const auto display = renderArea.getDisplayDevice();
- std::vector<Layer*> renderedLayers;
- bool disableBlurs = false;
- traverseLayers([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) {
+ std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
+ layers.reserve(layerCount);
+ std::unordered_set<compositionengine::LayerFE*> filterForScreenshot;
+ traverseLayers([&](Layer* layer) {
auto strongLayer = sp<Layer>::fromExisting(layer);
- auto layerFE = layer->getCompositionEngineLayerFE();
- if (!layerFE) {
- return;
- }
+ captureResults.capturedHdrLayers |= isHdrLayer(layer);
// Layer::prepareClientComposition uses the layer's snapshot to populate the resulting
// LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings are
// generated with the layer's current buffer and geometry.
layer->updateSnapshot(true /* updateGeometry */);
- disableBlurs |= layer->getDrawingState().sidebandStream != nullptr;
+ layers.emplace_back(layer, layer->copyCompositionEngineLayerFE());
- Region clip(renderArea.getBounds());
- compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
- clip,
- layer->needsFilteringForScreenshots(display.get(), transform) ||
- renderArea.needsFiltering(),
- renderArea.isSecure(),
- useProtected,
- layerStackSpaceRect,
- clientCompositionDisplay.outputDataspace,
- true, /* realContentIsVisible */
- false, /* clearContent */
- disableBlurs ? compositionengine::LayerFE::ClientCompositionTargetSettings::
- BlurSetting::Disabled
- : compositionengine::LayerFE::ClientCompositionTargetSettings::
- BlurSetting::Enabled,
- isHdrLayer(layer) ? displayBrightnessNits : sdrWhitePointNits,
+ sp<LayerFE>& layerFE = layers.back().second;
- };
- std::optional<compositionengine::LayerFE::LayerSettings> settings;
- {
- LayerSnapshotGuard layerSnapshotGuard(layer);
- settings = layerFE->prepareClientComposition(targetSettings);
+ layerFE->mSnapshot->geomLayerTransform =
+ renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform;
+
+ if (layer->needsFilteringForScreenshots(display.get(), transform)) {
+ filterForScreenshot.insert(layerFE.get());
}
-
- if (!settings) {
- return;
- }
-
- settings->geometry.positionTransform =
- transform.asMatrix4() * settings->geometry.positionTransform;
- // There's no need to process blurs when we're executing region sampling,
- // we're just trying to understand what we're drawing, and doing so without
- // blurs is already a pretty good approximation.
- if (regionSampling) {
- settings->backgroundBlurRadius = 0;
- settings->blurRegions.clear();
- }
- captureResults.capturedHdrLayers |= isHdrLayer(layer);
-
- clientCompositionLayers.push_back(std::move(*settings));
- renderedLayers.push_back(layer);
});
- std::vector<renderengine::LayerSettings> clientRenderEngineLayers;
- clientRenderEngineLayers.reserve(clientCompositionLayers.size());
- std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
- std::back_inserter(clientRenderEngineLayers),
- [](compositionengine::LayerFE::LayerSettings& settings)
- -> renderengine::LayerSettings { return settings; });
-
- // Use an empty fence for the buffer fence, since we just created the buffer so
- // there is no need for synchronization with the GPU.
- base::unique_fd bufferFence;
-
- constexpr bool kUseFramebufferCache = false;
- const auto future = getRenderEngine()
- .drawLayers(clientCompositionDisplay, clientRenderEngineLayers,
- buffer, kUseFramebufferCache, std::move(bufferFence))
- .share();
-
- for (auto* layer : renderedLayers) {
- layer->onLayerDisplayed(future);
+ ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK};
+ if (!layers.empty()) {
+ const sp<LayerFE>& layerFE = layers.back().second;
+ layerStack = layerFE->getCompositionState()->outputFilter.layerStack;
}
- return future;
+ auto copyLayerFEs = [&layers]() {
+ std::vector<sp<compositionengine::LayerFE>> layerFEs;
+ layerFEs.reserve(layers.size());
+ for (const auto& [_, layerFE] : layers) {
+ layerFEs.push_back(layerFE);
+ }
+ return layerFEs;
+ };
+
+ auto present = [this, buffer = std::move(buffer), dataspace, sdrWhitePointNits,
+ displayBrightnessNits, filterForScreenshot = std::move(filterForScreenshot),
+ grayscale, layerFEs = copyLayerFEs(), layerStack, regionSampling,
+ renderArea = std::move(renderArea), renderIntent]() -> FenceResult {
+ std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
+ mFactory.createCompositionEngine();
+ compositionEngine->setRenderEngine(mRenderEngine.get());
+
+ compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace,
+ .renderIntent = renderIntent};
+
+ std::shared_ptr<ScreenCaptureOutput> output = createScreenCaptureOutput(
+ ScreenCaptureOutputArgs{.compositionEngine = *compositionEngine,
+ .colorProfile = colorProfile,
+ .renderArea = *renderArea,
+ .layerStack = layerStack,
+ .buffer = std::move(buffer),
+ .sdrWhitePointNits = sdrWhitePointNits,
+ .displayBrightnessNits = displayBrightnessNits,
+ .filterForScreenshot = std::move(filterForScreenshot),
+ .regionSampling = regionSampling});
+
+ const float colorSaturation = grayscale ? 0 : 1;
+ compositionengine::CompositionRefreshArgs refreshArgs{
+ .outputs = {output},
+ .layers = std::move(layerFEs),
+ .updatingOutputGeometryThisFrame = true,
+ .updatingGeometryThisFrame = true,
+ .colorTransformMatrix = calculateColorMatrix(colorSaturation),
+ };
+ compositionEngine->present(refreshArgs);
+
+ return output->getRenderSurface()->getClientTargetAcquireFence();
+ };
+
+ // If RenderEngine is threaded, we can safely call CompositionEngine::present off the main
+ // thread as the RenderEngine::drawLayers call will run on RenderEngine's thread. Otherwise,
+ // we need RenderEngine to run on the main thread so we call CompositionEngine::present
+ // immediately.
+ //
+ // TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call
+ // to CompositionEngine::present.
+ const bool renderEngineIsThreaded = [&]() {
+ using Type = renderengine::RenderEngine::RenderEngineType;
+ const auto type = mRenderEngine->getRenderEngineType();
+ return type == Type::THREADED || type == Type::SKIA_GL_THREADED;
+ }();
+ auto presentFuture = renderEngineIsThreaded ? ftl::defer(std::move(present)).share()
+ : ftl::yield(present()).share();
+
+ for (auto& [layer, layerFE] : layers) {
+ layer->onLayerDisplayed(
+ ftl::Future(presentFuture)
+ .then([layerFE = std::move(layerFE)](FenceResult) {
+ return layerFE->stealCompositionResult().releaseFences.back().get();
+ })
+ .share());
+ }
+
+ return presentFuture;
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3d93d90..ee2810d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -780,7 +780,7 @@
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, const sp<IScreenCaptureListener>&);
ftl::SharedFuture<FenceResult> renderScreenImpl(
- const RenderArea&, TraverseLayersFunction,
+ std::unique_ptr<RenderArea>, TraverseLayersFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent,
bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock)
REQUIRES(kMainThreadContext);
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 7148c11..06b9caa 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -244,8 +244,8 @@
HAL_PIXEL_FORMAT_RGBA_8888, 1,
usage);
- auto future = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer,
- forSystem, regionSampling);
+ auto future = mFlinger.renderScreenImpl(std::move(renderArea), traverseLayers,
+ mCaptureScreenBuffer, forSystem, regionSampling);
ASSERT_TRUE(future.valid());
const auto fenceResult = future.get();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 46eca69..df53f15 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -37,6 +37,7 @@
#include "FrontEnd/LayerHandle.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
+#include "RenderArea.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/RefreshRateSelector.h"
#include "StartPropertySetThread.h"
@@ -399,14 +400,14 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto renderScreenImpl(const RenderArea& renderArea,
- SurfaceFlinger::TraverseLayersFunction traverseLayers,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool forSystem, bool regionSampling) {
+ auto renderScreenImpl(std::unique_ptr<RenderArea> renderArea,
+ SurfaceFlinger::TraverseLayersFunction traverseLayers,
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ bool forSystem, bool regionSampling) {
ScreenCaptureResults captureResults;
return FTL_FAKE_GUARD(kMainThreadContext,
- mFlinger->renderScreenImpl(renderArea, traverseLayers, buffer,
- forSystem, regionSampling,
+ mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers,
+ buffer, forSystem, regionSampling,
false /* grayscale */, captureResults));
}