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

Commit fb7ba6ba authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Return to manual slot use instead of slot generation"

parents 1adf533d 13f0d1a7
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -361,8 +361,12 @@ void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display)

    uint32_t hwcSlot = 0;
    sp<GraphicBuffer> hwcBuffer;

    // INVALID_BUFFER_SLOT is used to identify BufferStateLayers.  Default to 0
    // for BufferQueueLayers
    int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot;
    (*outputLayer->editState().hwc)
            .hwcBufferCache.getHwcBuffer(mActiveBuffer, &hwcSlot, &hwcBuffer);
            .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer);

    auto acquireFence = mConsumer->getCurrentFence();
    auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
+3 −3
Original line number Diff line number Diff line
@@ -585,10 +585,10 @@ void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display)

    const State& s(getDrawingState());

    // obtain slot
    uint32_t hwcSlot = 0;
    uint32_t hwcSlot;
    sp<GraphicBuffer> buffer;
    hwcInfo.hwcBufferCache.getHwcBuffer(s.buffer, &hwcSlot, &buffer);
    hwcInfo.hwcBufferCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, s.buffer, &hwcSlot,
                                        &buffer);

    auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence);
    if (error != HWC2::Error::None) {
+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ public:
    //
    // outBuffer is set to buffer when buffer is not in the HWC cache;
    // otherwise, outBuffer is set to nullptr.
    void getHwcBuffer(const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
    void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                      sp<GraphicBuffer>* outBuffer);

protected:
+11 −3
Original line number Diff line number Diff line
@@ -48,12 +48,20 @@ uint32_t HwcBufferCache::getLeastRecentlyUsedSlot() {
    return std::distance(std::begin(mBuffers), iter);
}

void HwcBufferCache::getHwcBuffer(const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
void HwcBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                                  sp<GraphicBuffer>* outBuffer) {
    bool cached = getSlot(buffer, outSlot);
    // if this slot corresponds to a BufferStateLayer, generate the slot
    if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
        getSlot(buffer, outSlot);
    } else if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
        *outSlot = 0;
    } else {
        *outSlot = slot;
    }

    auto& [currentCounter, currentBuffer] = mBuffers[*outSlot];
    if (cached) {
    wp<GraphicBuffer> weakCopy(buffer);
    if (currentBuffer == weakCopy) {
        // already cached in HWC, skip sending the buffer
        *outBuffer = nullptr;
        currentCounter = getCounter();
+60 −36
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ namespace {

class TestableHwcBufferCache : public impl::HwcBufferCache {
public:
    void getHwcBuffer(const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
    void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                      sp<GraphicBuffer>* outBuffer) {
        HwcBufferCache::getHwcBuffer(buffer, outSlot, outBuffer);
        HwcBufferCache::getHwcBuffer(slot, buffer, outSlot, outBuffer);
    }
    bool getSlot(const sp<GraphicBuffer>& buffer, uint32_t* outSlot) {
        return HwcBufferCache::getSlot(buffer, outSlot);
@@ -38,64 +38,88 @@ class HwcBufferCacheTest : public testing::Test {
public:
    ~HwcBufferCacheTest() override = default;

    TestableHwcBufferCache mCache;
    sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
    sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
};

TEST_F(HwcBufferCacheTest, testSlot) {
    void testSlot(const int inSlot, const uint32_t expectedSlot) {
        uint32_t outSlot;
        sp<GraphicBuffer> outBuffer;

        // The first time, the output  is the same as the input
    mCache.getHwcBuffer(mBuffer1, &outSlot, &outBuffer);
    EXPECT_EQ(0, outSlot);
        mCache.getHwcBuffer(inSlot, mBuffer1, &outSlot, &outBuffer);
        EXPECT_EQ(expectedSlot, outSlot);
        EXPECT_EQ(mBuffer1, outBuffer);

        // The second time with the same buffer, the outBuffer is nullptr.
    mCache.getHwcBuffer(mBuffer1, &outSlot, &outBuffer);
    EXPECT_EQ(0, outSlot);
        mCache.getHwcBuffer(inSlot, mBuffer1, &outSlot, &outBuffer);
        EXPECT_EQ(expectedSlot, outSlot);
        EXPECT_EQ(nullptr, outBuffer.get());

        // With a new buffer, the outBuffer is the input.
    mCache.getHwcBuffer(mBuffer2, &outSlot, &outBuffer);
    EXPECT_EQ(1, outSlot);
        mCache.getHwcBuffer(inSlot, mBuffer2, &outSlot, &outBuffer);
        EXPECT_EQ(expectedSlot, outSlot);
        EXPECT_EQ(mBuffer2, outBuffer);

        // Again, the second request with the same buffer sets outBuffer to nullptr.
    mCache.getHwcBuffer(mBuffer2, &outSlot, &outBuffer);
    EXPECT_EQ(1, outSlot);
        mCache.getHwcBuffer(inSlot, mBuffer2, &outSlot, &outBuffer);
        EXPECT_EQ(expectedSlot, outSlot);
        EXPECT_EQ(nullptr, outBuffer.get());

        // Setting a slot to use nullptr lookslike works, but note that
        // the output values make it look like no new buffer is being set....
    mCache.getHwcBuffer(sp<GraphicBuffer>(), &outSlot, &outBuffer);
    EXPECT_EQ(2, outSlot);
        mCache.getHwcBuffer(inSlot, sp<GraphicBuffer>(), &outSlot, &outBuffer);
        EXPECT_EQ(expectedSlot, outSlot);
        EXPECT_EQ(nullptr, outBuffer.get());
    }

TEST_F(HwcBufferCacheTest, testGetLeastRecentlyUsedSlot) {
    int slot;
    uint32_t outSlot;
    sp<GraphicBuffer> outBuffer;
    impl::HwcBufferCache mCache;
    sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
    sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
};

TEST_F(HwcBufferCacheTest, cacheWorksForSlotZero) {
    testSlot(0, 0);
}

TEST_F(HwcBufferCacheTest, cacheWorksForMaxSlot) {
    testSlot(BufferQueue::NUM_BUFFER_SLOTS - 1, BufferQueue::NUM_BUFFER_SLOTS - 1);
}

    // fill up cache
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        sp<GraphicBuffer> buf{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
        mCache.getHwcBuffer(buf, &outSlot, &outBuffer);
        EXPECT_EQ(buf, outBuffer);
        EXPECT_EQ(i, outSlot);
TEST_F(HwcBufferCacheTest, cacheMapsNegativeSlotToZero) {
    testSlot(-123, 0);
}

    slot = mCache.getLeastRecentlyUsedSlot();
    EXPECT_EQ(0, slot);
TEST_F(HwcBufferCacheTest, cacheGeneratesSlotForInvalidBufferSlot) {
    uint32_t outSlot;
    sp<GraphicBuffer> outBuffer;

    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
    EXPECT_EQ(0, outSlot);
    EXPECT_EQ(mBuffer1, outBuffer);

    mCache.getHwcBuffer(mBuffer1, &outSlot, &outBuffer);
    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer1, &outSlot, &outBuffer);
    EXPECT_EQ(0, outSlot);
    EXPECT_EQ(nullptr, outBuffer.get());

    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
    EXPECT_EQ(1, outSlot);
    EXPECT_EQ(mBuffer2, outBuffer);

    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
    EXPECT_EQ(1, outSlot);
    EXPECT_EQ(nullptr, outBuffer.get());

    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, sp<GraphicBuffer>(), &outSlot,
                        &outBuffer);
    EXPECT_EQ(2, outSlot);
    EXPECT_EQ(nullptr, outBuffer.get());

    // note that sending mBuffer1 with explicit slot 1 will overwrite mBuffer2
    // and also cause mBuffer1 to be stored in two places
    mCache.getHwcBuffer(1, mBuffer1, &outSlot, &outBuffer);
    EXPECT_EQ(1, outSlot);
    EXPECT_EQ(mBuffer1, outBuffer);

    slot = mCache.getLeastRecentlyUsedSlot();
    EXPECT_EQ(1, slot);
    mCache.getHwcBuffer(BufferQueue::INVALID_BUFFER_SLOT, mBuffer2, &outSlot, &outBuffer);
    EXPECT_EQ(3, outSlot);
    EXPECT_EQ(mBuffer2, outBuffer);
}

} // namespace
Loading