[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
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dfe8c72..9476c45 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -8144,7 +8144,7 @@
});
}
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 @@
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;