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/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 4822678..b66ee19 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -657,6 +657,7 @@
IComposerClient::Attribute::WIDTH);
mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
IComposerClient::Attribute::HEIGHT);
+
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
}
@@ -666,11 +667,13 @@
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
}
- NativeHandleWrapper allocate() {
+ NativeHandleWrapper allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
+
+ NativeHandleWrapper allocate(uint32_t width, uint32_t height) {
uint64_t usage =
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
BufferUsage::COMPOSER_OVERLAY);
- return mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
+ return mGralloc->allocate(width, height, 1, PixelFormat::RGBA_8888, usage);
}
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -884,6 +887,57 @@
}
/**
+ * Test IComposerClient::Command::SET_LAYER_BUFFER with the behavior used for clearing buffer slots.
+ */
+TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER_TO_CLEAR_BUFFER_SLOTS) {
+ // A buffer used to clear buffer slots
+ auto clearSlotBuffer = allocate(1u, 1u);
+
+ auto handle1 = allocate();
+ ASSERT_NE(nullptr, handle1.get());
+ IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+ mWriter->setLayerDisplayFrame(displayFrame);
+ mWriter->setLayerBuffer(0, handle1.get(), -1);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ GTEST_SUCCEED() << "Composition change requested, skipping test";
+ return;
+ }
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ // Ensure we can clear a buffer slot and then set that same slot with a new buffer
+ auto handle2 = allocate();
+ ASSERT_NE(nullptr, handle2.get());
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, clearSlotBuffer.get(), -1);
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerBuffer(0, handle2.get(), -1);
+ mWriter->validateDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+}
+
+/**
* Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
*/
TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 0c8742f..e35d07b 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -91,7 +91,7 @@
void setClientTarget(int64_t display, uint32_t slot, const native_handle_t* target,
int acquireFence, Dataspace dataspace, const std::vector<Rect>& damage) {
ClientTarget clientTargetCommand;
- clientTargetCommand.buffer = getBuffer(slot, target, acquireFence);
+ clientTargetCommand.buffer = getBufferCommand(slot, target, acquireFence);
clientTargetCommand.dataspace = dataspace;
clientTargetCommand.damage.assign(damage.begin(), damage.end());
getDisplayCommand(display).clientTarget.emplace(std::move(clientTargetCommand));
@@ -100,7 +100,7 @@
void setOutputBuffer(int64_t display, uint32_t slot, const native_handle_t* buffer,
int releaseFence) {
getDisplayCommand(display).virtualDisplayOutputBuffer.emplace(
- getBuffer(slot, buffer, releaseFence));
+ getBufferCommand(slot, buffer, releaseFence));
}
void validateDisplay(int64_t display,
@@ -132,7 +132,14 @@
void setLayerBuffer(int64_t display, int64_t layer, uint32_t slot,
const native_handle_t* buffer, int acquireFence) {
- getLayerCommand(display, layer).buffer = getBuffer(slot, buffer, acquireFence);
+ getLayerCommand(display, layer).buffer = getBufferCommand(slot, buffer, acquireFence);
+ }
+
+ void setLayerBufferWithNewCommand(int64_t display, int64_t layer, uint32_t slot,
+ const native_handle_t* buffer, int acquireFence) {
+ flushLayerCommand();
+ getLayerCommand(display, layer).buffer = getBufferCommand(slot, buffer, acquireFence);
+ flushLayerCommand();
}
void setLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector<Rect>& damage) {
@@ -234,7 +241,7 @@
std::vector<DisplayCommand> mCommands;
const int64_t mDisplay;
- Buffer getBuffer(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
+ Buffer getBufferCommand(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
Buffer bufferCommand;
bufferCommand.slot = static_cast<int32_t>(slot);
if (bufferHandle) bufferCommand.handle.emplace(::android::dupToAidl(bufferHandle));
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index fa66812..30ee1eb 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1132,17 +1132,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
@@ -1643,6 +1647,33 @@
execute();
}
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferWithSlotsToClear) {
+ auto clearSlotBuffer = allocate(1u, 1u, ::android::PIXEL_FORMAT_RGB_888);
+ ASSERT_NE(nullptr, clearSlotBuffer);
+ auto clearSlotBufferHandle = clearSlotBuffer->handle;
+
+ const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer1);
+ const auto handle1 = buffer1->handle;
+ const auto& [layerStatus, layer] =
+ mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+ EXPECT_TRUE(layerStatus.isOk());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ // Ensure we can clear a buffer slot and then set that same slot with a new buffer
+ const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer2);
+ const auto handle2 = buffer2->handle;
+ writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /* slot */ 0,
+ clearSlotBufferHandle, /*acquireFence*/ -1);
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle2, /*acquireFence*/ -1);
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
TEST_P(GraphicsComposerAidlCommandTest, SetLayerSurfaceDamage) {
const auto& [layerStatus, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);