Add VTS test for clearing buffer slots to Composer HIDL and AIDL
This feature allows SurfaceFlinger to clear buffer slots when buffers
are discarded by SurfaceFlinger clients and will no longer be used,
allowing the graphics memory to be freed immediately.
Bug: 258196272
Test: atest VtsHalGraphicsComposerV2_4TargetTest
Test: atest VtsHalGraphicsComposer3_TargetTest
Change-Id: Ibfbe2078ac419bb8f3880ee3f0512acaad2f5012
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 746330b..2b1b753 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1225,17 +1225,21 @@
});
}
- sp<GraphicBuffer> allocate(::android::PixelFormat pixelFormat) {
+ sp<GraphicBuffer> allocate(uint32_t width, uint32_t height,
+ ::android::PixelFormat pixelFormat) {
return sp<GraphicBuffer>::make(
- static_cast<uint32_t>(getPrimaryDisplay().getDisplayWidth()),
- static_cast<uint32_t>(getPrimaryDisplay().getDisplayHeight()), pixelFormat,
- /*layerCount*/ 1U,
- (static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
- static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
- static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY)),
+ width, height, pixelFormat, /*layerCount*/ 1U,
+ static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+ static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY),
"VtsHalGraphicsComposer3_TargetTest");
}
+ sp<GraphicBuffer> allocate(::android::PixelFormat pixelFormat) {
+ return allocate(static_cast<uint32_t>(getPrimaryDisplay().getDisplayWidth()),
+ static_cast<uint32_t>(getPrimaryDisplay().getDisplayHeight()), pixelFormat);
+ }
+
void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
if (timeline != nullptr) {
// Refresh time should be before newVsyncAppliedTimeNanos
@@ -1749,6 +1753,104 @@
execute();
}
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferSlotsToClear) {
+ // Older HAL versions use a backwards compatible way of clearing buffer slots
+ const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+ ASSERT_TRUE(versionStatus.isOk());
+ if (version <= 1) {
+ GTEST_SUCCEED() << "HAL at version 1 or lower does not have "
+ "LayerCommand::bufferSlotsToClear.";
+ return;
+ }
+
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ EXPECT_TRUE(layerStatus.isOk());
+ auto& writer = getWriter(getPrimaryDisplayId());
+
+ // setup 3 buffers in the buffer cache, with the last buffer being active
+ // then emulate the Android platform code that clears all 3 buffer slots
+
+ const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer1);
+ const auto handle1 = buffer1->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer2);
+ const auto handle2 = buffer2->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer3);
+ const auto handle3 = buffer3->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 2, handle3, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ // Ensure we can clear all 3 buffer slots, even the active buffer - it is assumed the
+ // current active buffer's slot will be cleared, but still remain the active buffer and no
+ // errors will occur.
+ writer.setLayerBufferSlotsToClear(getPrimaryDisplayId(), layer, {0, 1, 2});
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferMultipleTimes) {
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ EXPECT_TRUE(layerStatus.isOk());
+ auto& writer = getWriter(getPrimaryDisplayId());
+
+ // Setup 3 buffers in the buffer cache, with the last buffer being active. Then, emulate the
+ // Android platform code that clears all 3 buffer slots by setting all but the active buffer
+ // slot to a placeholder buffer, and then restoring the active buffer.
+
+ // This is used on HALs that don't support setLayerBufferSlotsToClear (version <= 3.1).
+
+ const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer1);
+ const auto handle1 = buffer1->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer2);
+ const auto handle2 = buffer2->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 1, handle2, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ const auto buffer3 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer3);
+ const auto handle3 = buffer3->handle;
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 2, handle3, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ // Older versions of the HAL clear all but the active buffer slot with a placeholder buffer,
+ // and then restoring the current active buffer at the end
+ auto clearSlotBuffer = allocate(1u, 1u, ::android::PIXEL_FORMAT_RGB_888);
+ ASSERT_NE(nullptr, clearSlotBuffer);
+ auto clearSlotBufferHandle = clearSlotBuffer->handle;
+
+ // clear buffer slots 0 and 1 with new layer commands... and then...
+ writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /* slot */ 0,
+ clearSlotBufferHandle, /*acquireFence*/ -1);
+ writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /* slot */ 1,
+ clearSlotBufferHandle, /*acquireFence*/ -1);
+ // ...reset the layer buffer to the current active buffer slot with a final new command
+ writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /*slot*/ 2, nullptr,
+ /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
TEST_P(GraphicsComposerAidlCommandTest, SetLayerSurfaceDamage) {
const auto& [layerStatus, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
@@ -2583,4 +2685,4 @@
}
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}