diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 48226785d5..9444d89f80 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -666,11 +666,13 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { 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(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()); } @@ -883,6 +885,106 @@ TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) { execute(); } +/** + * Test IComposerClient::Command::SET_LAYER_BUFFER with the behavior used for clearing buffer slots. + */ +TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER_multipleTimes) { + // A placeholder buffer used to clear buffer slots + auto clearSlotBuffer = allocate(1u, 1u); + + // + // Set the layer buffer to the first buffer + // + 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()); + + // + // Set the layer buffer to the second buffer + // + auto handle2 = allocate(); + ASSERT_NE(nullptr, handle2.get()); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerDisplayFrame(displayFrame); + mWriter->setLayerBuffer(1, handle2.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()); + + // + // Set the layer buffer to the third buffer + // + auto handle3 = allocate(); + ASSERT_NE(nullptr, handle3.get()); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); + mWriter->setLayerDisplayFrame(displayFrame); + mWriter->setLayerBuffer(2, handle3.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 multiple buffer slots and then restore the active buffer at the end + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + mWriter->setLayerBuffer(0, clearSlotBuffer.get(), -1); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + mWriter->setLayerBuffer(1, clearSlotBuffer.get(), -1); + mWriter->selectDisplay(mPrimaryDisplay); + mWriter->selectLayer(layer); + mWriter->setLayerBuffer(2, nullptr, -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. */ diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp index 746330b148..2b1b7532d9 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp @@ -1225,17 +1225,21 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { }); } - sp allocate(::android::PixelFormat pixelFormat) { + sp allocate(uint32_t width, uint32_t height, + ::android::PixelFormat pixelFormat) { return sp::make( - static_cast(getPrimaryDisplay().getDisplayWidth()), - static_cast(getPrimaryDisplay().getDisplayHeight()), pixelFormat, - /*layerCount*/ 1U, - (static_cast(common::BufferUsage::CPU_WRITE_OFTEN) | - static_cast(common::BufferUsage::CPU_READ_OFTEN) | - static_cast(common::BufferUsage::COMPOSER_OVERLAY)), + width, height, pixelFormat, /*layerCount*/ 1U, + static_cast(common::BufferUsage::CPU_WRITE_OFTEN) | + static_cast(common::BufferUsage::CPU_READ_OFTEN) | + static_cast(common::BufferUsage::COMPOSER_OVERLAY), "VtsHalGraphicsComposer3_TargetTest"); } + sp allocate(::android::PixelFormat pixelFormat) { + return allocate(static_cast(getPrimaryDisplay().getDisplayWidth()), + static_cast(getPrimaryDisplay().getDisplayHeight()), pixelFormat); + } + void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) { if (timeline != nullptr) { // Refresh time should be before newVsyncAppliedTimeNanos @@ -1749,6 +1753,104 @@ TEST_P(GraphicsComposerAidlCommandTest, SetLayerBuffer) { 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 @@ int main(int argc, char** argv) { } return RUN_ALL_TESTS(); -} \ No newline at end of file +}