195 lines
8.0 KiB
C++
195 lines
8.0 KiB
C++
/*
|
|
* Copyright 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <compositionengine/impl/HwcBufferCache.h>
|
|
#include <gtest/gtest.h>
|
|
#include <gui/BufferQueue.h>
|
|
#include <ui/GraphicBuffer.h>
|
|
|
|
namespace android::compositionengine {
|
|
namespace {
|
|
|
|
using impl::HwcBufferCache;
|
|
using impl::HwcSlotAndBuffer;
|
|
|
|
class HwcBufferCacheTest : public testing::Test {
|
|
public:
|
|
~HwcBufferCacheTest() override = default;
|
|
|
|
sp<GraphicBuffer> mBuffer1 =
|
|
sp<GraphicBuffer>::make(1u, 1u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, 0u);
|
|
sp<GraphicBuffer> mBuffer2 =
|
|
sp<GraphicBuffer>::make(1u, 1u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, 0u);
|
|
};
|
|
|
|
TEST_F(HwcBufferCacheTest, getHwcSlotAndBuffer_returnsUniqueSlotNumberForEachBuffer) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer slotAndBufferFor1 = cache.getHwcSlotAndBuffer(mBuffer1);
|
|
EXPECT_NE(slotAndBufferFor1.slot, UINT32_MAX);
|
|
EXPECT_EQ(slotAndBufferFor1.buffer, mBuffer1);
|
|
|
|
HwcSlotAndBuffer slotAndBufferFor2 = cache.getHwcSlotAndBuffer(mBuffer2);
|
|
EXPECT_NE(slotAndBufferFor2.slot, slotAndBufferFor1.slot);
|
|
EXPECT_NE(slotAndBufferFor2.slot, UINT32_MAX);
|
|
EXPECT_EQ(slotAndBufferFor2.buffer, mBuffer2);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, getHwcSlotAndBuffer_whenCached_returnsSameSlotNumberAndNullBuffer) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer originalSlotAndBuffer = cache.getHwcSlotAndBuffer(mBuffer1);
|
|
EXPECT_NE(originalSlotAndBuffer.slot, UINT32_MAX);
|
|
EXPECT_EQ(originalSlotAndBuffer.buffer, mBuffer1);
|
|
|
|
HwcSlotAndBuffer finalSlotAndBuffer = cache.getHwcSlotAndBuffer(mBuffer1);
|
|
EXPECT_EQ(finalSlotAndBuffer.slot, originalSlotAndBuffer.slot);
|
|
EXPECT_EQ(finalSlotAndBuffer.buffer, nullptr);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, getHwcSlotAndBuffer_whenSlotsFull_evictsOldestCachedBuffer) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
sp<GraphicBuffer> graphicBuffers[100];
|
|
HwcSlotAndBuffer slotsAndBuffers[100];
|
|
int finalCachedBufferIndex = 0;
|
|
for (int i = 0; i < 100; ++i) {
|
|
graphicBuffers[i] = sp<GraphicBuffer>::make(1u, 1u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, 0u);
|
|
slotsAndBuffers[i] = cache.getHwcSlotAndBuffer(graphicBuffers[i]);
|
|
// we fill up the cache when the slot number for the first buffer is reused
|
|
if (i > 0 && slotsAndBuffers[i].slot == slotsAndBuffers[0].slot) {
|
|
finalCachedBufferIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
ASSERT_GT(finalCachedBufferIndex, 1);
|
|
// the final cached buffer has the same slot value as the oldest buffer
|
|
EXPECT_EQ(slotsAndBuffers[finalCachedBufferIndex].slot, slotsAndBuffers[0].slot);
|
|
// the oldest buffer is no longer in the cache because it was evicted
|
|
EXPECT_EQ(cache.uncache(graphicBuffers[0]->getId()), UINT32_MAX);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, uncache_whenCached_returnsSlotNumber) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer slotAndBufferFor1 = cache.getHwcSlotAndBuffer(mBuffer1);
|
|
ASSERT_NE(slotAndBufferFor1.slot, UINT32_MAX);
|
|
|
|
HwcSlotAndBuffer slotAndBufferFor2 = cache.getHwcSlotAndBuffer(mBuffer2);
|
|
ASSERT_NE(slotAndBufferFor2.slot, UINT32_MAX);
|
|
|
|
// the 1st buffer should be found in the cache with a slot number
|
|
EXPECT_EQ(cache.uncache(mBuffer1->getId()), slotAndBufferFor1.slot);
|
|
// since the 1st buffer has been previously uncached, we should no longer receive a slot number
|
|
EXPECT_EQ(cache.uncache(mBuffer1->getId()), UINT32_MAX);
|
|
// the 2nd buffer should be still found in the cache with a slot number
|
|
EXPECT_EQ(cache.uncache(mBuffer2->getId()), slotAndBufferFor2.slot);
|
|
// since the 2nd buffer has been previously uncached, we should no longer receive a slot number
|
|
EXPECT_EQ(cache.uncache(mBuffer2->getId()), UINT32_MAX);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, uncache_whenUncached_returnsInvalidSlotNumber) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer slotAndBufferFor1 = cache.getHwcSlotAndBuffer(mBuffer1);
|
|
ASSERT_NE(slotAndBufferFor1.slot, UINT32_MAX);
|
|
|
|
EXPECT_EQ(cache.uncache(mBuffer2->getId()), UINT32_MAX);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, getOverrideHwcSlotAndBuffer_whenCached_returnsSameSlotAndNullBuffer) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer originalSlotAndBuffer = cache.getOverrideHwcSlotAndBuffer(mBuffer1);
|
|
EXPECT_NE(originalSlotAndBuffer.slot, UINT32_MAX);
|
|
EXPECT_EQ(originalSlotAndBuffer.buffer, mBuffer1);
|
|
|
|
HwcSlotAndBuffer finalSlotAndBuffer = cache.getOverrideHwcSlotAndBuffer(mBuffer1);
|
|
EXPECT_EQ(finalSlotAndBuffer.slot, originalSlotAndBuffer.slot);
|
|
EXPECT_EQ(finalSlotAndBuffer.buffer, nullptr);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, getOverrideHwcSlotAndBuffer_whenSlotsFull_returnsIndependentSlot) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
sp<GraphicBuffer> graphicBuffers[100];
|
|
HwcSlotAndBuffer slotsAndBuffers[100];
|
|
int finalCachedBufferIndex = -1;
|
|
for (int i = 0; i < 100; ++i) {
|
|
graphicBuffers[i] = sp<GraphicBuffer>::make(1u, 1u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, 0u);
|
|
slotsAndBuffers[i] = cache.getHwcSlotAndBuffer(graphicBuffers[i]);
|
|
// we fill up the cache when the slot number for the first buffer is reused
|
|
if (i > 0 && slotsAndBuffers[i].slot == slotsAndBuffers[0].slot) {
|
|
finalCachedBufferIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
// expect to have cached at least a few buffers before evicting
|
|
ASSERT_GT(finalCachedBufferIndex, 1);
|
|
|
|
sp<GraphicBuffer> overrideBuffer =
|
|
sp<GraphicBuffer>::make(1u, 1u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, 0u);
|
|
HwcSlotAndBuffer overrideSlotAndBuffer = cache.getOverrideHwcSlotAndBuffer(overrideBuffer);
|
|
// expect us to have a slot number
|
|
EXPECT_NE(overrideSlotAndBuffer.slot, UINT32_MAX);
|
|
// expect this to be the first time we cached the buffer
|
|
EXPECT_NE(overrideSlotAndBuffer.buffer, nullptr);
|
|
|
|
// expect the slot number to not equal any other slot number, even after the slots have been
|
|
// exhausted, indicating that the override buffer slot is independent from the slots for
|
|
// non-override buffers
|
|
for (int i = 0; i < finalCachedBufferIndex; ++i) {
|
|
EXPECT_NE(overrideSlotAndBuffer.slot, slotsAndBuffers[i].slot);
|
|
}
|
|
// the override buffer is independently uncached from the oldest cached buffer
|
|
// expect to find the override buffer still in the override buffer slot
|
|
EXPECT_EQ(cache.uncache(overrideBuffer->getId()), overrideSlotAndBuffer.slot);
|
|
// expect that the first buffer was not evicted from the cache when the override buffer was
|
|
// cached
|
|
EXPECT_EQ(cache.uncache(graphicBuffers[1]->getId()), slotsAndBuffers[1].slot);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, uncache_whenOverrideCached_returnsSlotNumber) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer hwcSlotAndBuffer = cache.getOverrideHwcSlotAndBuffer(mBuffer1);
|
|
ASSERT_NE(hwcSlotAndBuffer.slot, UINT32_MAX);
|
|
|
|
EXPECT_EQ(cache.uncache(mBuffer1->getId()), hwcSlotAndBuffer.slot);
|
|
EXPECT_EQ(cache.uncache(mBuffer1->getId()), UINT32_MAX);
|
|
}
|
|
|
|
TEST_F(HwcBufferCacheTest, uncache_whenOverrideUncached_returnsInvalidSlotNumber) {
|
|
HwcBufferCache cache;
|
|
sp<GraphicBuffer> outBuffer;
|
|
|
|
HwcSlotAndBuffer hwcSlotAndBuffer = cache.getOverrideHwcSlotAndBuffer(mBuffer1);
|
|
ASSERT_NE(hwcSlotAndBuffer.slot, UINT32_MAX);
|
|
|
|
EXPECT_EQ(cache.uncache(mBuffer2->getId()), UINT32_MAX);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace android::compositionengine
|