diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 201 |
1 files changed, 95 insertions, 106 deletions
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; } // --------------------------------------------------------------------------- |