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

Commit da3446eb authored by Valerie Hau's avatar Valerie Hau
Browse files

Adding onFrameAvailable test for BLASTBufferQueue

Bug: 142546708
Test: build, boot, libgui_test
Change-Id: I92a03e777334b7b4729338c7e3a75dad1db8b613
parent e676761d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -64,7 +64,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                   : Fence::NO_FENCE);
                                                   : Fence::NO_FENCE);
        mNextCallbackBufferItem = BufferItem();
        mNextCallbackBufferItem = BufferItem();
    }
    }
    mDequeueWaitCV.notify_one();
    mDequeueWaitCV.notify_all();
    decStrong((void*)transactionCallbackThunk);
    decStrong((void*)transactionCallbackThunk);
}
}


+141 −15
Original line number Original line Diff line number Diff line
@@ -18,8 +18,14 @@


#include <gui/BLASTBufferQueue.h>
#include <gui/BLASTBufferQueue.h>


#include <android/hardware/graphics/common/1.2/types.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>


#include <gtest/gtest.h>
#include <gtest/gtest.h>


@@ -27,10 +33,8 @@ using namespace std::chrono_literals;


namespace android {
namespace android {


const int DEFAULT_WIDTH = 100;
const int DEFAULT_HEIGHT = 100;

using Transaction = SurfaceComposerClient::Transaction;
using Transaction = SurfaceComposerClient::Transaction;
using android::hardware::graphics::common::V1_2::BufferUsage;


class BLASTBufferQueueHelper {
class BLASTBufferQueueHelper {
public:
public:
@@ -47,12 +51,24 @@ public:
    }
    }


    int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
    int getWidth() { return mBlastBufferQueueAdapter->mWidth; }

    int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
    int getHeight() { return mBlastBufferQueueAdapter->mHeight; }

    Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
    Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }

    sp<IGraphicBufferProducer> getIGraphicBufferProducer() {
        return mBlastBufferQueueAdapter->getIGraphicBufferProducer();
    }

    const sp<SurfaceControl> getSurfaceControl() {
    const sp<SurfaceControl> getSurfaceControl() {
        return mBlastBufferQueueAdapter->mSurfaceControl;
        return mBlastBufferQueueAdapter->mSurfaceControl;
    }
    }


    void waitForCallback() {
        std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
        mBlastBufferQueueAdapter->mDequeueWaitCV.wait_for(lock, 1s);
    }

private:
private:
    sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
    sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
};
};
@@ -73,39 +89,149 @@ protected:
    }
    }


    void SetUp() {
    void SetUp() {
        mComposer = ComposerService::getComposerService();
        mClient = new SurfaceComposerClient();
        mClient = new SurfaceComposerClient();
        mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
        mDisplayToken = mClient->getInternalDisplayToken();
                                                 DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
        ASSERT_NE(nullptr, mDisplayToken.get());
        Transaction t;
        t.setDisplayLayerStack(mDisplayToken, 0);
        t.apply();
        t.clear();

        DisplayInfo info;
        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplayToken, &info));
        mDisplayWidth = info.w;
        mDisplayHeight = info.h;

        mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
                                                 mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
                                                 ISurfaceComposerClient::eFXSurfaceBufferState,
                                                 /*parent*/ nullptr);
        t.setLayerStack(mSurfaceControl, 0)
                .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
                .setFrame(mSurfaceControl, Rect(0, 0, mDisplayWidth, mDisplayHeight))
                .show(mSurfaceControl)
                .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
                .apply();
    }

    void fillBuffer(uint32_t* bufData, uint32_t width, uint32_t height, uint32_t stride, uint8_t r,
                    uint8_t g, uint8_t b) {
        for (uint32_t row = 0; row < height; row++) {
            for (uint32_t col = 0; col < width; col++) {
                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
                *pixel = r;
                *(pixel + 1) = g;
                *(pixel + 2) = b;
                *(pixel + 3) = 255;
            }
        }
    }

    void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b) {
        const auto width = mScreenCaptureBuf->getWidth();
        const auto height = mScreenCaptureBuf->getHeight();
        const auto stride = mScreenCaptureBuf->getStride();

        uint32_t* bufData;
        mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
                                reinterpret_cast<void**>(&bufData));

        for (uint32_t row = 0; row < height; row++) {
            for (uint32_t col = 0; col < width; col++) {
                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
                EXPECT_EQ(r, *(pixel));
                EXPECT_EQ(g, *(pixel + 1));
                EXPECT_EQ(b, *(pixel + 2));
            }
        }
        mScreenCaptureBuf->unlock();
        ASSERT_EQ(false, ::testing::Test::HasFailure());
    }
    }


    sp<SurfaceComposerClient> mClient;
    sp<SurfaceComposerClient> mClient;
    sp<ISurfaceComposer> mComposer;

    sp<IBinder> mDisplayToken;

    sp<SurfaceControl> mSurfaceControl;
    sp<SurfaceControl> mSurfaceControl;
    sp<GraphicBuffer> mScreenCaptureBuf;

    uint32_t mDisplayWidth;
    uint32_t mDisplayHeight;
};
};


TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
    // create BLASTBufferQueue adapter associated with this surface
    // create BLASTBufferQueue adapter associated with this surface
    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
    ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
    ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
    ASSERT_EQ(mDisplayWidth, adapter.getWidth());
    ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
    ASSERT_EQ(mDisplayHeight, adapter.getHeight());
    ASSERT_EQ(nullptr, adapter.getNextTransaction());
    ASSERT_EQ(nullptr, adapter.getNextTransaction());
}
}


TEST_F(BLASTBufferQueueTest, Update) {
TEST_F(BLASTBufferQueueTest, Update) {
    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    sp<SurfaceControl> updateSurface =
    sp<SurfaceControl> updateSurface =
            mClient->createSurface(String8("UpdateTest"), DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2,
            mClient->createSurface(String8("UpdateTest"), mDisplayWidth / 2, mDisplayHeight / 2,
                                   PIXEL_FORMAT_RGB_888);
                                   PIXEL_FORMAT_RGBA_8888);
    adapter.update(updateSurface, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
    adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
    ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
    ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
    ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
    ASSERT_EQ(mDisplayWidth / 2, adapter.getWidth());
    ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
    ASSERT_EQ(mDisplayHeight / 2, adapter.getHeight());
}
}


TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    Transaction next;
    Transaction next;
    adapter.setNextTransaction(&next);
    adapter.setNextTransaction(&next);
    ASSERT_EQ(&next, adapter.getNextTransaction());
    ASSERT_EQ(&next, adapter.getNextTransaction());
}
}

TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) {
    uint8_t r = 255;
    uint8_t g = 0;
    uint8_t b = 0;

    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    auto igbProducer = adapter.getIGraphicBufferProducer();
    ASSERT_NE(nullptr, igbProducer.get());
    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    ASSERT_EQ(NO_ERROR,
              igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
                                   &qbOutput));
    ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(3));

    int slot;
    sp<Fence> fence;
    sp<GraphicBuffer> buf;
    auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
                                          PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
                                          nullptr, nullptr);
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
    ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));

    uint32_t* bufData;
    buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
              reinterpret_cast<void**>(&bufData));
    fillBuffer(bufData, buf->getWidth(), buf->getHeight(), buf->getStride(), r, g, b);
    buf->unlock();

    IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN,
                                                   Rect(mDisplayWidth, mDisplayHeight),
                                                   NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
                                                   Fence::NO_FENCE);
    igbProducer->queueBuffer(slot, input, &qbOutput);

    adapter.waitForCallback();

    // capture screen and verify that it is red
    bool capturedSecureLayers;
    ASSERT_EQ(NO_ERROR,
              mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
                                       ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
                                       mDisplayWidth, mDisplayHeight,
                                       /*useIdentityTransform*/ false));
    ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b));
}
} // namespace android
} // namespace android