diff options
-rw-r--r-- | services/surfaceflinger/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/src/Output.cpp | 82 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/ScreenCaptureOutput.cpp | 107 | ||||
-rw-r--r-- | services/surfaceflinger/ScreenCaptureOutput.h | 69 | ||||
-rw-r--r-- | services/surfaceflinger/ScreenCaptureRenderSurface.h | 81 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 201 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/CompositionTest.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h | 13 |
12 files changed, 419 insertions, 150 deletions
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 999c03f96b..14fdd126dd 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -189,6 +189,7 @@ filegroup { "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 23d5570096..e06da33025 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -134,9 +134,11 @@ protected: 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 c2b1f0679c..d1daca6090 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1226,40 +1226,8 @@ std::optional<base::unique_fd> Output::composeSurfaces( 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 @@ std::optional<base::unique_fd> Output::composeSurfaces( 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 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( Enabled); compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{.clip = clip, - .needsFiltering = layer->needsFiltering() || + .needsFiltering = layerNeedsFiltering(layer) || outputState.needsFiltering, .isSecure = outputState.isSecure, .supportsProtectedContent = supportsProtectedContent, @@ -1446,6 +1454,10 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( 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 83a46ae3df..2a18521b5b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3499,6 +3499,12 @@ const compositionengine::LayerFECompositionState* Layer::getCompositionState() c 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 a3c4e5966c..9585fa9b30 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -323,6 +323,7 @@ public: 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 0000000000..8f93ba40ee --- /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 0000000000..61b5ddb1bb --- /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 0000000000..20973003d5 --- /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 999af304ef..56fa96be3e 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 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, 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> SurfaceFlinger::captureScreenCommon( 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::captureScreenCommon( } 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 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( } 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 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( } 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(); - - 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) { + const auto transform = renderArea->getTransform(); + const auto display = renderArea->getDisplayDevice(); + + 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; - - 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, + layers.emplace_back(layer, layer->copyCompositionEngineLayerFE()); - }; - std::optional<compositionengine::LayerFE::LayerSettings> settings; - { - LayerSnapshotGuard layerSnapshotGuard(layer); - settings = layerFE->prepareClientComposition(targetSettings); - } + sp<LayerFE>& layerFE = layers.back().second; - if (!settings) { - return; - } + layerFE->mSnapshot->geomLayerTransform = + renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform; - 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(); + if (layer->needsFilteringForScreenshots(display.get(), transform)) { + filterForScreenshot.insert(layerFE.get()); } - 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; }); + ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK}; + if (!layers.empty()) { + const sp<LayerFE>& layerFE = layers.back().second; + layerStack = layerFE->getCompositionState()->outputFilter.layerStack; + } - // 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; + auto copyLayerFEs = [&layers]() { + std::vector<sp<compositionengine::LayerFE>> layerFEs; + layerFEs.reserve(layers.size()); + for (const auto& [_, layerFE] : layers) { + layerFEs.push_back(layerFE); + } + return layerFEs; + }; - constexpr bool kUseFramebufferCache = false; - const auto future = getRenderEngine() - .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, - buffer, kUseFramebufferCache, std::move(bufferFence)) - .share(); + 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); - for (auto* layer : renderedLayers) { - layer->onLayerDisplayed(future); + 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 future; + return presentFuture; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3d93d90b30..ee2810da36 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -780,7 +780,7 @@ private: 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 7148c117c5..06b9caa7cb 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -244,8 +244,8 @@ void CompositionTest::captureScreenComposition() { 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 46eca69c6a..df53f1560a 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 @@ public: 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)); } |