Uncache the active buffer slot last
This allows the memory for the active buffer to be freed as soon as
possible by purging it from HWC cache as soon as the next buffer is sent
to the layer.
Bug: 258196272
Test: atest OutputLayerUncacheBufferTest
Change-Id: I96c24390de5757ac99b369119e9ba031afb0b042
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 766d7ea..60a2c83 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -617,13 +617,24 @@
return;
}
+ // Uncache the active buffer last so that it's the first buffer to be purged from the cache
+ // next time a buffer is sent to this layer.
+ bool uncacheActiveBuffer = false;
+
std::vector<uint32_t> slotsToClear;
for (uint64_t bufferId : bufferIdsToUncache) {
- uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
- if (slot != UINT32_MAX) {
- slotsToClear.push_back(slot);
+ if (bufferId == state.hwc->activeBufferId) {
+ uncacheActiveBuffer = true;
+ } else {
+ uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
+ if (slot != UINT32_MAX) {
+ slotsToClear.push_back(slot);
+ }
}
}
+ if (uncacheActiveBuffer) {
+ slotsToClear.push_back(state.hwc->hwcBufferCache.uncache(state.hwc->activeBufferId));
+ }
hal::Error error =
state.hwc->hwcLayer->setBufferSlotsToClear(slotsToClear, state.hwc->activeBufferSlot);
@@ -655,17 +666,20 @@
hwcSlotAndBuffer = state.hwc->hwcBufferCache.getOverrideHwcSlotAndBuffer(
state.overrideInfo.buffer->getBuffer());
hwcFence = state.overrideInfo.acquireFence;
+ // Keep track of the active buffer ID so when it's discarded we uncache it last so its
+ // slot will be used first, allowing the memory to be freed as soon as possible.
+ state.hwc->activeBufferId = state.overrideInfo.buffer->getBuffer()->getId();
} else {
hwcSlotAndBuffer =
state.hwc->hwcBufferCache.getHwcSlotAndBuffer(outputIndependentState.buffer);
hwcFence = outputIndependentState.acquireFence;
+ // Keep track of the active buffer ID so when it's discarded we uncache it last so its
+ // slot will be used first, allowing the memory to be freed as soon as possible.
+ state.hwc->activeBufferId = outputIndependentState.buffer->getId();
}
-
// Keep track of the active buffer slot, so we can restore it after clearing other buffer
// slots.
- if (hwcSlotAndBuffer.buffer) {
- state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
- }
+ state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
}
if (auto error = hwcLayer->setBuffer(hwcSlotAndBuffer.slot, hwcSlotAndBuffer.buffer, hwcFence);