Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26d03fdb authored by Lloyd Pique's avatar Lloyd Pique
Browse files

SF: Move OutputLayer creation to computeVisibleRegions

This moves part of rebuildLayerStacks to computeVisibleRegions. In
particular it eliminates a second loop over all front-end layers to
identify the ones that are visible on an output. The first loop
computes the visibility, and can immediately create the output layers.

This is a bit of nontrivial restructuring prior to moving the code to
CompositionEngine, since that will also break things up a bit.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I8a498195f9b5f976e7a69de717818b57494e2f2b
parent 30629982
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ struct LayerCreationArgs {
    LayerMetadata metadata;
};

class Layer : public virtual compositionengine::LayerFE {
class Layer : public compositionengine::LayerFE {
    static std::atomic<int32_t> sSequence;

public:
+62 −45
Original line number Diff line number Diff line
@@ -2085,6 +2085,12 @@ void SurfaceFlinger::rebuildLayerStacks() {
        ATRACE_NAME("rebuildLayerStacks VR Dirty");
        invalidateHwcGeometry();

        std::vector<sp<compositionengine::LayerFE>> layersWithQueuedFrames;
        layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
        for (sp<Layer> layer : mLayersWithQueuedFrames) {
            layersWithQueuedFrames.push_back(layer);
        }

        for (const auto& pair : mDisplays) {
            const auto& displayDevice = pair.second;
            auto display = displayDevice->getCompositionDisplay();
@@ -2092,59 +2098,44 @@ void SurfaceFlinger::rebuildLayerStacks() {
            Region opaqueRegion;
            Region dirtyRegion;
            compositionengine::Output::OutputLayers layersSortedByZ;
            compositionengine::Output::ReleasedLayers releasedLayers;
            const ui::Transform& tr = displayState.transform;
            const Rect bounds = displayState.bounds;
            if (displayState.isEnabled) {
                computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);

                mDrawingState.traverseInZOrder([&](Layer* layer) {
                    auto compositionLayer = layer->getCompositionLayer();
                    if (compositionLayer == nullptr) {
                        return;
            if (!displayState.isEnabled) {
                continue;
            }

                    const auto displayId = displayDevice->getId();
                    sp<compositionengine::LayerFE> layerFE = compositionLayer->getLayerFE();
                    LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr);
            computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion, layersSortedByZ);

                    bool needsOutputLayer = false;
            // computeVisibleRegions walks the layers in reverse-Z order. Reverse
            // to get a back-to-front ordering.
            std::reverse(layersSortedByZ.begin(), layersSortedByZ.end());

                    if (display->belongsInOutput(layer->getLayerStack(),
                                                 layer->getPrimaryDisplayOnly())) {
                        Region drawRegion(tr.transform(
                                layer->visibleNonTransparentRegion));
                        drawRegion.andSelf(bounds);
                        if (!drawRegion.isEmpty()) {
                            needsOutputLayer = true;
                        }
                    }

                    if (needsOutputLayer) {
                        layersSortedByZ.emplace_back(
                                display->getOrCreateOutputLayer(displayId, compositionLayer,
                                                                layerFE));
                        auto& outputLayerState = layersSortedByZ.back()->editState();
                        outputLayerState.visibleRegion =
                                tr.transform(layer->visibleRegion.intersect(displayState.viewport));
                    } else if (displayId) {
            display->setOutputLayersOrderedByZ(std::move(layersSortedByZ));

            compositionengine::Output::ReleasedLayers releasedLayers;
            if (displayDevice->getId() && !layersWithQueuedFrames.empty()) {
                // For layers that are being removed from a HWC display,
                // and that have queued frames, add them to a a list of
                // released layers so we can properly set a fence.
                        bool hasExistingOutputLayer =
                                display->getOutputLayerForLayer(compositionLayer.get()) != nullptr;
                        bool hasQueuedFrames = std::find(mLayersWithQueuedFrames.cbegin(),
                                                         mLayersWithQueuedFrames.cend(),
                                                         layer) != mLayersWithQueuedFrames.cend();

                        if (hasExistingOutputLayer && hasQueuedFrames) {
                            releasedLayers.push_back(layer);
                // Any non-null entries in the current list of layers are layers
                // that are no longer going to be visible
                for (auto& layer : display->getOutputLayersOrderedByZ()) {
                    if (!layer) {
                        continue;
                    }

                    sp<compositionengine::LayerFE> layerFE(&layer->getLayerFE());
                    const bool hasQueuedFrames =
                            std::find(layersWithQueuedFrames.cbegin(),
                                      layersWithQueuedFrames.cend(),
                                      layerFE) != layersWithQueuedFrames.cend();

                    if (hasQueuedFrames) {
                        releasedLayers.emplace_back(layerFE);
                    }
                }
                });
            }

            display->setOutputLayersOrderedByZ(std::move(layersSortedByZ));
            display->setReleasedLayers(std::move(releasedLayers));

            Region undefinedRegion{bounds};
@@ -2744,8 +2735,10 @@ void SurfaceFlinger::commitOffscreenLayers() {
    }
}

void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
                                           Region& outDirtyRegion, Region& outOpaqueRegion) {
void SurfaceFlinger::computeVisibleRegions(
        const sp<const DisplayDevice>& displayDevice, Region& outDirtyRegion,
        Region& outOpaqueRegion,
        std::vector<std::unique_ptr<compositionengine::OutputLayer>>& outLayersSortedByZ) {
    ATRACE_CALL();
    ALOGV("computeVisibleRegions");

@@ -2758,6 +2751,11 @@ void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displa
    outDirtyRegion.clear();

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        auto compositionLayer = layer->getCompositionLayer();
        if (compositionLayer == nullptr) {
            return;
        }

        // start with the whole surface at its current location
        const Layer::State& s(layer->getDrawingState());

@@ -2880,6 +2878,25 @@ void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displa
        layer->setCoveredRegion(coveredRegion);
        layer->setVisibleNonTransparentRegion(
                visibleRegion.subtract(transparentRegion));

        // Setup an output layer for this output if the layer is
        // visible on this output
        const auto& displayState = display->getState();
        Region drawRegion(displayState.transform.transform(layer->visibleNonTransparentRegion));
        drawRegion.andSelf(displayState.bounds);
        if (drawRegion.isEmpty()) {
            return;
        }

        const auto displayId = displayDevice->getId();
        sp<compositionengine::LayerFE> layerFE = compositionLayer->getLayerFE();
        LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr);

        outLayersSortedByZ.emplace_back(
                display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE));
        auto& outputLayerState = outLayersSortedByZ.back()->editState();
        outputLayerState.visibleRegion = displayState.transform.transform(
                layer->visibleRegion.intersect(displayState.viewport));
    });

    outOpaqueRegion = aboveOpaqueLayers;
+4 −2
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ class TimeStats;

namespace compositionengine {
class DisplaySurface;
class OutputLayer;

struct CompositionRefreshArgs;
} // namespace compositionengine
@@ -740,8 +741,9 @@ private:
     * Compositing
     */
    void invalidateHwcGeometry();
    void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
                               Region& opaqueRegion);
    void computeVisibleRegions(
            const sp<const DisplayDevice>& display, Region& dirtyRegion, Region& opaqueRegion,
            std::vector<std::unique_ptr<compositionengine::OutputLayer>>& outputLayers);

    void postComposition();
    void getCompositorTiming(CompositorTiming* compositorTiming);