Loading libs/gui/BLASTBufferQueue.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading libs/gui/tests/BLASTBufferQueue_test.cpp +141 −15 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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: Loading @@ -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; }; Loading @@ -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 Loading
libs/gui/BLASTBufferQueue.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +141 −15 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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: Loading @@ -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; }; Loading @@ -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