Use new traversal function when order doesn't matter
The new traversal function just handles traversing children and ignores relative layers. It also doesn't care about the z order. We continue to use the traverseInZOrder functions
for cases when z order matters.
This optimization reduces total CPU time spent in SurfaceFlinger.
Total ~2% savings
The savings where measured sampling over a 20 second period while TouchLatency
bouncy ball app was running.
Baseline
https://pprof.corp.google.com/?id=2ec0b6ac8e24e1571a3173c763ecd7e1&focus=LayerVector%3A%3AtraverseInZOrder
Optimized
https://pprof.corp.google.com/?id=23596aeb3e9db163956dc621dd19d7a4&focus=LayerVector%3A%3Atraverse
Test: manual. checked that normal use on the phone did not have graphical corruptions.
Test: atest SurfaceFlinger_test libcompositionengine_test libsurfaceflinger_unittest
Test: go/wm-smoke
Port from ag/10112179
Change-Id: I60cc6b58efc0e95c5ccc204830a3d76d2e7633c7
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6d18922..9136593 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2039,7 +2039,7 @@
compositorTiming = getBE().mCompositorTiming;
}
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mDrawingState.traverse([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(displayDevice, glCompositionDoneFenceTime,
presentFenceTime, compositorTiming);
if (frameLatched) {
@@ -2463,7 +2463,7 @@
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Notify all layers of available frames
- mCurrentState.traverseInZOrder([expectedPresentTime](Layer* layer) {
+ mCurrentState.traverse([expectedPresentTime](Layer* layer) {
layer->notifyAvailableFrames(expectedPresentTime);
});
@@ -2473,7 +2473,7 @@
*/
if ((transactionFlags & eTraversalNeeded) || mTraversalNeededMainThread) {
- mCurrentState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverse([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) return;
@@ -2520,7 +2520,7 @@
sp<const DisplayDevice> hintDisplay;
uint32_t currentlayerStack = 0;
bool first = true;
- mCurrentState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverse([&](Layer* layer) {
// NOTE: we rely on the fact that layers are sorted by
// layerStack first (so we don't have to traverse the list
// of displays for every layer).
@@ -2744,7 +2744,7 @@
// clear the "changed" flags in current state
mCurrentState.colorMatrixChanged = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mDrawingState.traverse([&](Layer* layer) {
layer->commitChildList();
// If the layer can be reached when traversing mDrawingState, then the layer is no
@@ -2755,7 +2755,7 @@
});
commitOffscreenLayers();
- mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateMirrorInfo(); });
+ mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
}
void SurfaceFlinger::withTracingLock(std::function<void()> lockedOperation) {
@@ -2780,7 +2780,7 @@
void SurfaceFlinger::commitOffscreenLayers() {
for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [](Layer* layer) {
+ offscreenLayer->traverse(LayerVector::StateSet::Drawing, [](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) return;
@@ -2821,7 +2821,7 @@
// 3.) Layer 1 is latched.
// Display is now waiting on Layer 1's frame, which is behind layer 0's
// second frame. But layer 0's second frame could be waiting on display.
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mDrawingState.traverse([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
if (layer->shouldPresentNow(expectedPresentTime)) {
@@ -2839,7 +2839,7 @@
// be shown on screen. Therefore, we need to latch and release buffers of offscreen
// layers to ensure dequeueBuffer doesn't block indefinitely.
for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing,
+ offscreenLayer->traverse(LayerVector::StateSet::Drawing,
[&](Layer* l) { l->latchAndReleaseBuffer(); });
}
@@ -2874,7 +2874,7 @@
mBootStage = BootStage::BOOTANIMATION;
}
- mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateCloneBufferInfo(); });
+ mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
// Only continue with the refresh if there is actually new work to do
return !mLayersWithQueuedFrames.empty() && newDataLatched;
@@ -3696,7 +3696,7 @@
bool matchFound = true;
while (matchFound) {
matchFound = false;
- mCurrentState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverse([&](Layer* layer) {
if (layer->getName() == uniqueName) {
matchFound = true;
uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter);
@@ -4067,7 +4067,7 @@
const bool clearAll = args.size() < 2;
const auto name = clearAll ? String8() : String8(args[1]);
- mCurrentState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverse([&](Layer* layer) {
if (clearAll || layer->getName() == name.string()) {
layer->clearFrameStats();
}
@@ -4083,7 +4083,7 @@
// This should only be called from the main thread. Otherwise it would need
// the lock and should use mCurrentState rather than mDrawingState.
void SurfaceFlinger::logFrameStats() {
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mDrawingState.traverse([&](Layer* layer) {
layer->logFrameStats();
});
@@ -4318,7 +4318,7 @@
result.append("Offscreen Layers:\n");
postMessageSync(new LambdaMessage([&]() {
for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ offscreenLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) {
layer->dumpCallingUidPid(result);
});
}
@@ -5544,6 +5544,10 @@
// ---------------------------------------------------------------------------
+void SurfaceFlinger::State::traverse(const LayerVector::Visitor& visitor) const {
+ layersSortedByZ.traverse(visitor);
+}
+
void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
layersSortedByZ.traverseInZOrder(stateSet, visitor);
}