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

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

Merge "Adding onFrameAvailable test for BLASTBufferQueue"

parents b7943bcd da3446eb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                   : Fence::NO_FENCE);
        mNextCallbackBufferItem = BufferItem();
    }
    mDequeueWaitCV.notify_one();
    mDequeueWaitCV.notify_all();
    decStrong((void*)transactionCallbackThunk);
}

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

#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 <private/gui/ComposerService.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>

#include <gtest/gtest.h>

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

namespace android {

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

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

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

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

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

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

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

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

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

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

    void SetUp() {
        mComposer = ComposerService::getComposerService();
        mClient = new SurfaceComposerClient();
        mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
                                                 DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
        mDisplayToken = mClient->getInternalDisplayToken();
        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<ISurfaceComposer> mComposer;

    sp<IBinder> mDisplayToken;

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

    uint32_t mDisplayWidth;
    uint32_t mDisplayHeight;
};

TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
    // 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(DEFAULT_WIDTH, adapter.getWidth());
    ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
    ASSERT_EQ(mDisplayWidth, adapter.getWidth());
    ASSERT_EQ(mDisplayHeight, adapter.getHeight());
    ASSERT_EQ(nullptr, adapter.getNextTransaction());
}

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

TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    Transaction next;
    adapter.setNextTransaction(&next);
    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