Loading libs/gui/BLASTBufferQueue.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ void BLASTBufferQueue::processNextBufferLocked() { t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()}); t->setCrop(mSurfaceControl, computeCrop(mLastSubmittedBufferItem)); t->setTransform(mSurfaceControl, mLastSubmittedBufferItem.mTransform); if (applyTransaction) { t->apply(); Loading libs/gui/tests/BLASTBufferQueue_test.cpp +227 −9 Original line number Diff line number Diff line Loading @@ -144,7 +144,25 @@ protected: } } void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region) { void fillQuadrants(sp<GraphicBuffer>& buf) { const auto bufWidth = buf->getWidth(); const auto bufHeight = buf->getHeight(); uint32_t* bufData; buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN), reinterpret_cast<void**>(&bufData)); fillBuffer(bufData, Rect(0, 0, bufWidth / 2, bufHeight / 2), buf->getStride(), 0, 0, 0); fillBuffer(bufData, Rect(bufWidth / 2, 0, bufWidth, bufHeight / 2), buf->getStride(), 255, 0, 0); fillBuffer(bufData, Rect(bufWidth / 2, bufHeight / 2, bufWidth, bufHeight), buf->getStride(), 0, 255, 0); fillBuffer(bufData, Rect(0, bufHeight / 2, bufWidth / 2, bufHeight), buf->getStride(), 0, 0, 255); buf->unlock(); } void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0, bool outsideRegion = false) { const auto epsilon = 3; const auto width = mScreenCaptureBuf->getWidth(); const auto height = mScreenCaptureBuf->getHeight(); const auto stride = mScreenCaptureBuf->getStride(); Loading @@ -156,15 +174,22 @@ protected: 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); if (row >= region.top && row < region.bottom && col >= region.left && col < region.right) { EXPECT_EQ(r, *(pixel)); EXPECT_EQ(g, *(pixel + 1)); EXPECT_EQ(b, *(pixel + 2)); bool inRegion; if (!outsideRegion) { inRegion = row >= region.top + border && row < region.bottom - border && col >= region.left + border && col < region.right - border; } else { EXPECT_EQ(0, *(pixel)); EXPECT_EQ(0, *(pixel + 1)); EXPECT_EQ(0, *(pixel + 2)); inRegion = row >= region.top - border && row < region.bottom + border && col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { EXPECT_GE(epsilon, abs(r - *(pixel))); EXPECT_GE(epsilon, abs(g - *(pixel + 1))); EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { EXPECT_GE(epsilon, abs(r - *(pixel))); EXPECT_GE(epsilon, abs(g - *(pixel + 1))); EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } } } Loading Loading @@ -398,6 +423,199 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, /*border*/ 0, /*outsideRegion*/ true)); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { public: void test(uint32_t tr) { BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); auto bufWidth = mDisplayWidth; auto bufHeight = mDisplayHeight; int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufWidth, bufHeight, 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)); fillQuadrants(buf); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, Rect(bufWidth, bufHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, tr, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); switch (tr) { case ui::Transform::ROT_0: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::FLIP_H: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::FLIP_V: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_90: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_180: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_270: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); } } }; TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_0) { test(ui::Transform::ROT_0); } TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_H) { test(ui::Transform::FLIP_H); } TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_V) { test(ui::Transform::FLIP_V); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_90) { test(ui::Transform::ROT_90); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_180) { test(ui::Transform::ROT_180); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) { test(ui::Transform::ROT_270); } } // namespace android Loading
libs/gui/BLASTBufferQueue.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ void BLASTBufferQueue::processNextBufferLocked() { t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()}); t->setCrop(mSurfaceControl, computeCrop(mLastSubmittedBufferItem)); t->setTransform(mSurfaceControl, mLastSubmittedBufferItem.mTransform); if (applyTransaction) { t->apply(); Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +227 −9 Original line number Diff line number Diff line Loading @@ -144,7 +144,25 @@ protected: } } void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region) { void fillQuadrants(sp<GraphicBuffer>& buf) { const auto bufWidth = buf->getWidth(); const auto bufHeight = buf->getHeight(); uint32_t* bufData; buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN), reinterpret_cast<void**>(&bufData)); fillBuffer(bufData, Rect(0, 0, bufWidth / 2, bufHeight / 2), buf->getStride(), 0, 0, 0); fillBuffer(bufData, Rect(bufWidth / 2, 0, bufWidth, bufHeight / 2), buf->getStride(), 255, 0, 0); fillBuffer(bufData, Rect(bufWidth / 2, bufHeight / 2, bufWidth, bufHeight), buf->getStride(), 0, 255, 0); fillBuffer(bufData, Rect(0, bufHeight / 2, bufWidth / 2, bufHeight), buf->getStride(), 0, 0, 255); buf->unlock(); } void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0, bool outsideRegion = false) { const auto epsilon = 3; const auto width = mScreenCaptureBuf->getWidth(); const auto height = mScreenCaptureBuf->getHeight(); const auto stride = mScreenCaptureBuf->getStride(); Loading @@ -156,15 +174,22 @@ protected: 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); if (row >= region.top && row < region.bottom && col >= region.left && col < region.right) { EXPECT_EQ(r, *(pixel)); EXPECT_EQ(g, *(pixel + 1)); EXPECT_EQ(b, *(pixel + 2)); bool inRegion; if (!outsideRegion) { inRegion = row >= region.top + border && row < region.bottom - border && col >= region.left + border && col < region.right - border; } else { EXPECT_EQ(0, *(pixel)); EXPECT_EQ(0, *(pixel + 1)); EXPECT_EQ(0, *(pixel + 2)); inRegion = row >= region.top - border && row < region.bottom + border && col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { EXPECT_GE(epsilon, abs(r - *(pixel))); EXPECT_GE(epsilon, abs(g - *(pixel + 1))); EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { EXPECT_GE(epsilon, abs(r - *(pixel))); EXPECT_GE(epsilon, abs(g - *(pixel + 1))); EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } } } Loading Loading @@ -398,6 +423,199 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, /*border*/ 0, /*outsideRegion*/ true)); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { public: void test(uint32_t tr) { BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); auto bufWidth = mDisplayWidth; auto bufHeight = mDisplayHeight; int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufWidth, bufHeight, 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)); fillQuadrants(buf); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, Rect(bufWidth, bufHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, tr, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); switch (tr) { case ui::Transform::ROT_0: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::FLIP_H: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::FLIP_V: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_90: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_180: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); break; case ui::Transform::ROT_270: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {(int32_t)mDisplayWidth / 2, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {(int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}, 1)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, (int32_t)mDisplayHeight / 2, (int32_t)mDisplayWidth / 2, (int32_t)mDisplayHeight}, 1)); } } }; TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_0) { test(ui::Transform::ROT_0); } TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_H) { test(ui::Transform::FLIP_H); } TEST_F(BLASTBufferQueueTransformTest, setTransform_FLIP_V) { test(ui::Transform::FLIP_V); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_90) { test(ui::Transform::ROT_90); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_180) { test(ui::Transform::ROT_180); } TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) { test(ui::Transform::ROT_270); } } // namespace android