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

Commit 802ac4f6 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

[sf] avoid traversals for cursor updates and buffer udpates

In U, we have a unified way to traverse the layer
hierarchy from both new FrontEnd and legacy logic
to generate the snapshots to provide to CE.
We update CE twice, once to draw the cursor and once
for the remaining layers. In T we relied on the previous
frame's composition state to update cursor state. This
extra traversal increases the cpu usage for buffer updates.

Fix this by keeping track of the previous composition state
and expand on this to avoid all traversals when there are
only buffer updates.

Bug: 278634536
Test: simple perf and check the instruction count between T and U

Change-Id: I26989bf42aa00650ee97c3c60e7f34171c385c5c
parent 50fe0d96
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -8144,7 +8144,7 @@ std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToComposit
                });
    }
    if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
        mDrawingState.traverseInZOrder([&refreshArgs, cursorOnly, &layers](Layer* layer) {
        auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) {
            if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
                if (cursorOnly &&
                    layer->getLayerSnapshot()->compositionType !=
@@ -8155,7 +8155,22 @@ std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToComposit
                refreshArgs.layers.push_back(layerFE);
                layers.emplace_back(layer, layerFE.get());
            }
        });
        };

        if (cursorOnly || !mVisibleRegionsDirty) {
            // for hot path avoid traversals by walking though the previous composition list
            for (sp<Layer> layer : mPreviouslyComposedLayers) {
                moveSnapshots(layer.get());
            }
        } else {
            mPreviouslyComposedLayers.clear();
            mDrawingState.traverseInZOrder(
                    [&moveSnapshots](Layer* layer) { moveSnapshots(layer); });
            mPreviouslyComposedLayers.reserve(layers.size());
            for (auto [layer, _] : layers) {
                mPreviouslyComposedLayers.push_back(sp<Layer>::fromExisting(layer));
            }
        }
    }

    return layers;
+5 −0
Original line number Diff line number Diff line
@@ -1199,6 +1199,11 @@ private:
    std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithBuffersRemoved;
    // Tracks layers that need to update a display's dirty region.
    std::vector<sp<Layer>> mLayersPendingRefresh;
    // Sorted list of layers that were composed during previous frame. This is used to
    // avoid an expensive traversal of the layer hierarchy when there are no
    // visible region changes. Because this is a list of strong pointers, this will
    // extend the life of the layer but this list is only updated in the main thread.
    std::vector<sp<Layer>> mPreviouslyComposedLayers;

    BootStage mBootStage = BootStage::BOOTLOADER;

+5 −0
Original line number Diff line number Diff line
@@ -680,6 +680,9 @@ struct SidebandLayerProperties : public BaseLayerProperties<SidebandLayerPropert
                NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
                                     false);
        test->mFlinger.setLayerSidebandStream(layer, stream);
        auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
        layerDrawingState.crop =
                Rect(0, 0, SidebandLayerProperties::HEIGHT, SidebandLayerProperties::WIDTH);
    }

    static void setupHwcSetSourceCropBufferCallExpectations(CompositionTest* test) {
@@ -814,6 +817,7 @@ struct BaseLayerVariant {
        Mock::VerifyAndClear(test->mComposer);

        test->mFlinger.mutableDrawingState().layersSortedByZ.add(layer);
        test->mFlinger.mutableVisibleRegionsDirty() = true;
    }

    static void cleanupInjectedLayers(CompositionTest* test) {
@@ -822,6 +826,7 @@ struct BaseLayerVariant {

        test->mDisplay->getCompositionDisplay()->clearOutputLayers();
        test->mFlinger.mutableDrawingState().layersSortedByZ.clear();
        test->mFlinger.mutablePreviouslyComposedLayers().clear();

        // Layer should be unregistered with scheduler.
        test->mFlinger.commit();
+2 −0
Original line number Diff line number Diff line
@@ -588,6 +588,7 @@ public:
    auto& mutablePhysicalDisplays() { return mFlinger->mPhysicalDisplays; }
    auto& mutableDrawingState() { return mFlinger->mDrawingState; }
    auto& mutableGeometryDirty() { return mFlinger->mGeometryDirty; }
    auto& mutableVisibleRegionsDirty() { return mFlinger->mVisibleRegionsDirty; }
    auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
    auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
    auto& mutableTexturePool() { return mFlinger->mTexturePool; }
@@ -599,6 +600,7 @@ public:
    auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
    auto& mutablePrimaryHwcDisplayId() { return getHwComposer().mPrimaryHwcDisplayId; }
    auto& mutableActiveDisplayId() { return mFlinger->mActiveDisplayId; }
    auto& mutablePreviouslyComposedLayers() { return mFlinger->mPreviouslyComposedLayers; }

    auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }