Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca3eef29 authored by Brian Lindahl's avatar Brian Lindahl
Browse files

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
parent 3ead3226
Loading
Loading
Loading
Loading
+56 −2
Original line number Diff line number Diff line
@@ -657,6 +657,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
                                                             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 @@ 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<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()); }
@@ -883,6 +886,57 @@ 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_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.
 */
+11 −4
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ class ComposerClientWriter final {
    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 @@ class ComposerClientWriter final {
    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 @@ class ComposerClientWriter final {

    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 @@ class ComposerClientWriter final {
    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));
+38 −7
Original line number Diff line number Diff line
@@ -1132,17 +1132,21 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
        }
    }

    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) |
                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)),
                        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 @@ TEST_P(GraphicsComposerAidlCommandTest, SetLayerBuffer) {
    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);