Loading libs/gui/BLASTBufferQueue.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ BLASTBufferQueue::~BLASTBufferQueue() { void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format) { std::unique_lock _lock{mMutex}; BQA_LOGV("update width=%d height=%d format=%d", width, height, format); if (mFormat != format) { mFormat = format; mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format)); Loading Loading @@ -397,10 +398,11 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Rect crop = computeCrop(bufferItem); mLastAcquiredFrameNumber = bufferItem.mFrameNumber; mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, bufferItem.mScalingMode); bufferItem.mScalingMode, crop); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */, Loading @@ -415,7 +417,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSurfaceControlsWithPendingCallback.push(mSurfaceControl); setMatrix(t, mLastBufferInfo); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setCrop(mSurfaceControl, crop); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); if (!bufferItem.mIsAutoTimestamp) { Loading Loading @@ -543,13 +545,15 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) { uint32_t bufWidth = bufferInfo.width; uint32_t bufHeight = bufferInfo.height; uint32_t bufWidth = bufferInfo.crop.getWidth(); uint32_t bufHeight = bufferInfo.crop.getHeight(); float dsdx = mSize.width / static_cast<float>(bufWidth); float dsdy = mSize.height / static_cast<float>(bufHeight); float sx = mSize.width / static_cast<float>(bufWidth); float sy = mSize.height / static_cast<float>(bufHeight); t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); t->setMatrix(mSurfaceControl, sx, 0, 0, sy); // Update position based on crop. t->setPosition(mSurfaceControl, bufferInfo.crop.left * sx * -1, bufferInfo.crop.top * sy * -1); } void BLASTBufferQueue::setTransactionCompleteCallback( Loading libs/gui/include/gui/BLASTBufferQueue.h +7 −1 Original line number Diff line number Diff line Loading @@ -151,14 +151,20 @@ private: // we get the next buffer. This will support scenarios where the layer can change sizes // and the buffer will scale to fit the new size. uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; Rect crop; void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, uint32_t scalingMode) { uint32_t scalingMode, const Rect& crop) { this->hasBuffer = hasBuffer; this->width = width; this->height = height; this->transform = transform; this->scalingMode = scalingMode; if (!crop.isEmpty()) { this->crop = crop; } else { this->crop = Rect(width, height); } } }; Loading libs/gui/tests/BLASTBufferQueue_test.cpp +138 −8 Original line number Diff line number Diff line Loading @@ -522,16 +522,146 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { adapter.waitForCallbacks(); // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, {10, 10, (int32_t)bufferSideLength - 10, (int32_t)bufferSideLength - 10})); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, /*border*/ 0, /*outsideRegion*/ true)); } Rect bounds; bounds.left = finalCropSideLength / 2; bounds.top = 0; bounds.right = bounds.left + finalCropSideLength; bounds.bottom = finalCropSideLength; TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToBufferSize) { // add black background auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect); ASSERT_NE(nullptr, bg.get()); Transaction t; t.setLayerStack(bg, 0) .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setColor(bg, half3{0, 0, 0}) .setLayer(bg, 0) .apply(); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); Rect windowSize(1000, 1000); Rect bufferSize(windowSize); Rect bufferCrop(200, 200, 700, 700); BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight()); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(), bufferSize.getHeight(), 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)); // fill buffer with grey fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127); // fill crop area with different colors so we can verify the cropped region has been scaled // correctly. fillBuffer(bufData, Rect(200, 200, 450, 450), buf->getStride(), /* rgb */ 255, 0, 0); fillBuffer(bufData, Rect(200, 451, 450, 700), buf->getStride(), /* rgb */ 0, 255, 0); fillBuffer(bufData, Rect(451, 200, 700, 450), buf->getStride(), /* rgb */ 0, 0, 255); fillBuffer(bufData, Rect(451, 451, 700, 700), buf->getStride(), /* rgb */ 255, 0, 0); buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, HAL_DATASPACE_UNKNOWN, bufferCrop /* Rect::INVALID_RECT */, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); // Verify cropped region is scaled correctly. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990})); // Verify outside region is black. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)windowSize.getWidth(), (int32_t)windowSize.getHeight()}, /*border*/ 0, /*outsideRegion*/ true)); } TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToWindowSize) { // add black background auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect); ASSERT_NE(nullptr, bg.get()); Transaction t; t.setLayerStack(bg, 0) .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setColor(bg, half3{0, 0, 0}) .setLayer(bg, 0) .apply(); Rect windowSize(1000, 1000); Rect bufferSize(500, 500); Rect bufferCrop(100, 100, 350, 350); BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight()); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(), bufferSize.getHeight(), 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)); // fill buffer with grey fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127); // fill crop area with different colors so we can verify the cropped region has been scaled // correctly. fillBuffer(bufData, Rect(100, 100, 225, 225), buf->getStride(), /* rgb */ 255, 0, 0); fillBuffer(bufData, Rect(100, 226, 225, 350), buf->getStride(), /* rgb */ 0, 255, 0); fillBuffer(bufData, Rect(226, 100, 350, 225), buf->getStride(), /* rgb */ 0, 0, 255); fillBuffer(bufData, Rect(226, 226, 350, 350), buf->getStride(), /* rgb */ 255, 0, 0); buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, HAL_DATASPACE_UNKNOWN, bufferCrop /* Rect::INVALID_RECT */, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); // Verify cropped region is scaled correctly. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990})); // Verify outside region is black. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)windowSize.getWidth(), (int32_t)windowSize.getHeight()}, /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { Loading services/surfaceflinger/BufferStateLayer.cpp +4 −20 Original line number Diff line number Diff line Loading @@ -790,7 +790,7 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mFence = s.acquireFence; mBufferInfo.mTransform = s.bufferTransform; mBufferInfo.mDataspace = translateDataspace(s.dataspace); mBufferInfo.mCrop = computeCrop(s); mBufferInfo.mCrop = computeBufferCrop(s); mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; Loading @@ -803,27 +803,11 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; } Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { Rect BufferStateLayer::computeBufferCrop(const State& s) { if (s.buffer) { return s.buffer->getBuffer()->getBounds(); } else if (s.buffer) { Rect crop = s.crop; crop.left = std::max(crop.left, 0); crop.top = std::max(crop.top, 0); uint32_t bufferWidth = s.buffer->getBuffer()->getWidth(); uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); if (bufferHeight <= std::numeric_limits<int32_t>::max() && bufferWidth <= std::numeric_limits<int32_t>::max()) { crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth)); crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight)); } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer return s.buffer->getBuffer()->getBounds(); } return crop; } return s.crop; return Rect::INVALID_RECT; } sp<Layer> BufferStateLayer::createClone() { Loading services/surfaceflinger/BufferStateLayer.h +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ private: sp<Layer> createClone() override; // Crop that applies to the buffer Rect computeCrop(const State& s); Rect computeBufferCrop(const State& s); bool willPresentCurrentTransaction() const; Loading Loading
libs/gui/BLASTBufferQueue.cpp +11 −7 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ BLASTBufferQueue::~BLASTBufferQueue() { void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format) { std::unique_lock _lock{mMutex}; BQA_LOGV("update width=%d height=%d format=%d", width, height, format); if (mFormat != format) { mFormat = format; mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format)); Loading Loading @@ -397,10 +398,11 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); Rect crop = computeCrop(bufferItem); mLastAcquiredFrameNumber = bufferItem.mFrameNumber; mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, bufferItem.mScalingMode); bufferItem.mScalingMode, crop); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */, Loading @@ -415,7 +417,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSurfaceControlsWithPendingCallback.push(mSurfaceControl); setMatrix(t, mLastBufferInfo); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setCrop(mSurfaceControl, crop); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); if (!bufferItem.mIsAutoTimestamp) { Loading Loading @@ -543,13 +545,15 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) { uint32_t bufWidth = bufferInfo.width; uint32_t bufHeight = bufferInfo.height; uint32_t bufWidth = bufferInfo.crop.getWidth(); uint32_t bufHeight = bufferInfo.crop.getHeight(); float dsdx = mSize.width / static_cast<float>(bufWidth); float dsdy = mSize.height / static_cast<float>(bufHeight); float sx = mSize.width / static_cast<float>(bufWidth); float sy = mSize.height / static_cast<float>(bufHeight); t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); t->setMatrix(mSurfaceControl, sx, 0, 0, sy); // Update position based on crop. t->setPosition(mSurfaceControl, bufferInfo.crop.left * sx * -1, bufferInfo.crop.top * sy * -1); } void BLASTBufferQueue::setTransactionCompleteCallback( Loading
libs/gui/include/gui/BLASTBufferQueue.h +7 −1 Original line number Diff line number Diff line Loading @@ -151,14 +151,20 @@ private: // we get the next buffer. This will support scenarios where the layer can change sizes // and the buffer will scale to fit the new size. uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; Rect crop; void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, uint32_t scalingMode) { uint32_t scalingMode, const Rect& crop) { this->hasBuffer = hasBuffer; this->width = width; this->height = height; this->transform = transform; this->scalingMode = scalingMode; if (!crop.isEmpty()) { this->crop = crop; } else { this->crop = Rect(width, height); } } }; Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +138 −8 Original line number Diff line number Diff line Loading @@ -522,16 +522,146 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { adapter.waitForCallbacks(); // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, {10, 10, (int32_t)bufferSideLength - 10, (int32_t)bufferSideLength - 10})); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, /*border*/ 0, /*outsideRegion*/ true)); } Rect bounds; bounds.left = finalCropSideLength / 2; bounds.top = 0; bounds.right = bounds.left + finalCropSideLength; bounds.bottom = finalCropSideLength; TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToBufferSize) { // add black background auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect); ASSERT_NE(nullptr, bg.get()); Transaction t; t.setLayerStack(bg, 0) .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setColor(bg, half3{0, 0, 0}) .setLayer(bg, 0) .apply(); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); Rect windowSize(1000, 1000); Rect bufferSize(windowSize); Rect bufferCrop(200, 200, 700, 700); BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight()); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(), bufferSize.getHeight(), 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)); // fill buffer with grey fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127); // fill crop area with different colors so we can verify the cropped region has been scaled // correctly. fillBuffer(bufData, Rect(200, 200, 450, 450), buf->getStride(), /* rgb */ 255, 0, 0); fillBuffer(bufData, Rect(200, 451, 450, 700), buf->getStride(), /* rgb */ 0, 255, 0); fillBuffer(bufData, Rect(451, 200, 700, 450), buf->getStride(), /* rgb */ 0, 0, 255); fillBuffer(bufData, Rect(451, 451, 700, 700), buf->getStride(), /* rgb */ 255, 0, 0); buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, HAL_DATASPACE_UNKNOWN, bufferCrop /* Rect::INVALID_RECT */, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); // Verify cropped region is scaled correctly. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990})); // Verify outside region is black. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)windowSize.getWidth(), (int32_t)windowSize.getHeight()}, /*border*/ 0, /*outsideRegion*/ true)); } TEST_F(BLASTBufferQueueTest, ScaleCroppedBufferToWindowSize) { // add black background auto bg = mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect); ASSERT_NE(nullptr, bg.get()); Transaction t; t.setLayerStack(bg, 0) .setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setColor(bg, half3{0, 0, 0}) .setLayer(bg, 0) .apply(); Rect windowSize(1000, 1000); Rect bufferSize(500, 500); Rect bufferCrop(100, 100, 350, 350); BLASTBufferQueueHelper adapter(mSurfaceControl, windowSize.getWidth(), windowSize.getHeight()); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); int slot; sp<Fence> fence; sp<GraphicBuffer> buf; auto ret = igbProducer->dequeueBuffer(&slot, &fence, bufferSize.getWidth(), bufferSize.getHeight(), 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)); // fill buffer with grey fillBuffer(bufData, bufferSize, buf->getStride(), 127, 127, 127); // fill crop area with different colors so we can verify the cropped region has been scaled // correctly. fillBuffer(bufData, Rect(100, 100, 225, 225), buf->getStride(), /* rgb */ 255, 0, 0); fillBuffer(bufData, Rect(100, 226, 225, 350), buf->getStride(), /* rgb */ 0, 255, 0); fillBuffer(bufData, Rect(226, 100, 350, 225), buf->getStride(), /* rgb */ 0, 0, 255); fillBuffer(bufData, Rect(226, 226, 350, 350), buf->getStride(), /* rgb */ 255, 0, 0); buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, HAL_DATASPACE_UNKNOWN, bufferCrop /* Rect::INVALID_RECT */, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); // Verify cropped region is scaled correctly. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {10, 10, 490, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 255, 0, {10, 510, 490, 990})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 255, {510, 10, 990, 490})); ASSERT_NO_FATAL_FAILURE(checkScreenCapture(255, 0, 0, {510, 510, 990, 990})); // Verify outside region is black. ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, {0, 0, (int32_t)windowSize.getWidth(), (int32_t)windowSize.getHeight()}, /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { Loading
services/surfaceflinger/BufferStateLayer.cpp +4 −20 Original line number Diff line number Diff line Loading @@ -790,7 +790,7 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mFence = s.acquireFence; mBufferInfo.mTransform = s.bufferTransform; mBufferInfo.mDataspace = translateDataspace(s.dataspace); mBufferInfo.mCrop = computeCrop(s); mBufferInfo.mCrop = computeBufferCrop(s); mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; Loading @@ -803,27 +803,11 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; } Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { Rect BufferStateLayer::computeBufferCrop(const State& s) { if (s.buffer) { return s.buffer->getBuffer()->getBounds(); } else if (s.buffer) { Rect crop = s.crop; crop.left = std::max(crop.left, 0); crop.top = std::max(crop.top, 0); uint32_t bufferWidth = s.buffer->getBuffer()->getWidth(); uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); if (bufferHeight <= std::numeric_limits<int32_t>::max() && bufferWidth <= std::numeric_limits<int32_t>::max()) { crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth)); crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight)); } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer return s.buffer->getBuffer()->getBounds(); } return crop; } return s.crop; return Rect::INVALID_RECT; } sp<Layer> BufferStateLayer::createClone() { Loading
services/surfaceflinger/BufferStateLayer.h +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ private: sp<Layer> createClone() override; // Crop that applies to the buffer Rect computeCrop(const State& s); Rect computeBufferCrop(const State& s); bool willPresentCurrentTransaction() const; Loading