Change slot generation for BufferState
BufferState layers now do slot generation with buffer death considered
appropriately. When a buffer dies, the slot will be pushed onto a stack
of available slots to be reused at the next opportunity. This should
mimic BufferQueue slot behavior and prevent Composer Resources from
growing too large.
Test: build, boot, manual
Bug: 129351223
Change-Id: Icef9592593cacb0b5c6b12f6679fc2c4dabdcd19
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
index 97bdc8f..8eec035 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
@@ -48,20 +48,11 @@
void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
sp<GraphicBuffer>* outBuffer);
-protected:
- bool getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot);
- uint32_t getLeastRecentlyUsedSlot();
- uint64_t getCounter();
-
private:
// an array where the index corresponds to a slot and the value corresponds to a (counter,
// buffer) pair. "counter" is a unique value that indicates the last time this slot was updated
// or used and allows us to keep track of the least-recently used buffer.
- std::pair<uint64_t, wp<GraphicBuffer>> mBuffers[BufferQueue::NUM_BUFFER_SLOTS];
-
- // The cache increments this counter value when a slot is updated or used.
- // Used to track the least recently-used buffer
- uint64_t mCounter = 1;
+ wp<GraphicBuffer> mBuffers[BufferQueue::NUM_BUFFER_SLOTS];
};
} // namespace compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
index a941e09..f72862b 100644
--- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
@@ -21,60 +21,30 @@
namespace android::compositionengine::impl {
HwcBufferCache::HwcBufferCache() {
- std::fill(std::begin(mBuffers), std::end(mBuffers),
- std::pair<uint64_t, wp<GraphicBuffer>>(0, nullptr));
-}
-bool HwcBufferCache::getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot) {
- // search for cached buffer first
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- // Weak pointers in the cache may have had their object destroyed.
- // Comparisons between weak pointers will accurately reflect this case,
- // but comparisons between weak and strong may not. Thus, we create a weak
- // pointer from strong pointer buffer
- wp<GraphicBuffer> weakCopy(buffer);
- if (mBuffers[i].second == weakCopy) {
- *outSlot = i;
- return true;
- }
- }
-
- // use the least-recently used slot
- *outSlot = getLeastRecentlyUsedSlot();
- return false;
-}
-
-uint32_t HwcBufferCache::getLeastRecentlyUsedSlot() {
- auto iter = std::min_element(std::begin(mBuffers), std::end(mBuffers));
- return std::distance(std::begin(mBuffers), iter);
+ std::fill(std::begin(mBuffers), std::end(mBuffers), wp<GraphicBuffer>(nullptr));
}
void HwcBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
sp<GraphicBuffer>* outBuffer) {
- // if this slot corresponds to a BufferStateLayer, generate the slot
- if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
- getSlot(buffer, outSlot);
- } else if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
+ // default is 0
+ if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0 ||
+ slot >= BufferQueue::NUM_BUFFER_SLOTS) {
*outSlot = 0;
} else {
*outSlot = slot;
}
- auto& [currentCounter, currentBuffer] = mBuffers[*outSlot];
+ auto& currentBuffer = mBuffers[*outSlot];
wp<GraphicBuffer> weakCopy(buffer);
if (currentBuffer == weakCopy) {
// already cached in HWC, skip sending the buffer
*outBuffer = nullptr;
- currentCounter = getCounter();
} else {
*outBuffer = buffer;
// update cache
currentBuffer = buffer;
- currentCounter = getCounter();
}
}
-uint64_t HwcBufferCache::getCounter() {
- return mCounter++;
-}
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
index b261493..00eafb1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
@@ -28,10 +28,6 @@
sp<GraphicBuffer>* outBuffer) {
HwcBufferCache::getHwcBuffer(slot, buffer, outSlot, outBuffer);
}
- bool getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot) {
- return HwcBufferCache::getSlot(buffer, outSlot);
- }
- uint32_t getLeastRecentlyUsedSlot() { return HwcBufferCache::getLeastRecentlyUsedSlot(); }
};
class HwcBufferCacheTest : public testing::Test {
@@ -86,41 +82,5 @@
testSlot(-123, 0);
}
-TEST_F(HwcBufferCacheTest, cacheGeneratesSlotForInvalidBufferSlot) {
- uint32_t outSlot;
- sp<GraphicBuffer> outBuffer;
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
- EXPECT_EQ(0, outSlot);
- EXPECT_EQ(mBuffer1, outBuffer);
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
- EXPECT_EQ(0, outSlot);
- EXPECT_EQ(nullptr, outBuffer.get());
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
- EXPECT_EQ(1, outSlot);
- EXPECT_EQ(mBuffer2, outBuffer);
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
- EXPECT_EQ(1, outSlot);
- EXPECT_EQ(nullptr, outBuffer.get());
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, sp<GraphicBuffer>(), &outSlot,
- &outBuffer);
- EXPECT_EQ(2, outSlot);
- EXPECT_EQ(nullptr, outBuffer.get());
-
- // note that sending mBuffer1 with explicit slot 1 will overwrite mBuffer2
- // and also cause mBuffer1 to be stored in two places
- mCache.getHwcBuffer(1, mBuffer1, &outSlot, &outBuffer);
- EXPECT_EQ(1, outSlot);
- EXPECT_EQ(mBuffer1, outBuffer);
-
- mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
- EXPECT_EQ(3, outSlot);
- EXPECT_EQ(mBuffer2, outBuffer);
-}
-
} // namespace
} // namespace android::compositionengine