BlastBufferQueue: Fix scaling when buffer scaling mode changes am: 932f6aee50 am: fec689d8c3
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/15952944
Change-Id: I664321549f871fe5d38eec82de13f82f1678b562
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 379b090..406272c 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -456,10 +456,10 @@
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
+ const bool sizeHasChanged = mRequestedSize != mSize;
+ mSize = mRequestedSize;
+ const bool updateDestinationFrame = sizeHasChanged || !mLastBufferInfo.hasBuffer;
Rect crop = computeCrop(bufferItem);
- const bool updateDestinationFrame =
- bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE ||
- !mLastBufferInfo.hasBuffer;
mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
bufferItem.mScalingMode, crop);
@@ -572,7 +572,6 @@
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
- mSize = mRequestedSize;
// Only reject buffers if scaling mode is freeze.
return false;
}
@@ -586,7 +585,6 @@
}
ui::Size bufferSize(bufWidth, bufHeight);
if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
- mSize = mRequestedSize;
return false;
}
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 26d902d..b474086 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -672,6 +672,83 @@
/*border*/ 0, /*outsideRegion*/ true));
}
+// b/196339769 verify we can can update the requested size while the in FREEZE scaling mode and
+// scale the buffer properly when the mode changes to SCALE_TO_WINDOW
+TEST_F(BLASTBufferQueueTest, ScalingModeChanges) {
+ uint8_t r = 255;
+ uint8_t g = 0;
+ uint8_t b = 0;
+
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight / 4);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 4,
+ 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, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ 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,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 4}));
+
+ // update the size to half the display and dequeue a buffer quarter of the display.
+ adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight / 2);
+
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 8,
+ 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));
+ g = 255;
+ fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
+ 0, Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ adapter.waitForCallbacks();
+ }
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+ // verify we still scale the buffer to the new size (half the screen height)
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(r, g, b,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
+}
+
class TestProducerListener : public BnProducerListener {
public:
sp<IGraphicBufferProducer> mIgbp;