SF: refactor renderScreenImpl to use CompositionEngine

Bug: 238643986
Test: presubmits
Test: go/wm-smoke

Change-Id: I6dbbcd5ce5070ec1d801dca55b5bb89fafe839cb
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;
 }
 
 // ---------------------------------------------------------------------------