summaryrefslogtreecommitdiff
path: root/libs/gui/BLASTBufferQueue.cpp
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2022-02-10 14:49:09 -0800
committer Vishnu Nair <vishnun@google.com> 2022-02-19 00:08:04 +0000
commitd2aaab14d2fd52a6c6a0c928a55bf000f6c538ca (patch)
tree8ae9ece2f949f1734de7a468b271912c180fede0 /libs/gui/BLASTBufferQueue.cpp
parent9cb96607229431793f38825387cef5ac561db49c (diff)
SurfaceView: Avoid destination frame updates on multiple threads 2/2
The caller such as SurfaceView can optionally apply destination frame changes if they wish to synchronize buffer scale with other scales in the hierarchy. This is hard to synchronize if the buffer scale changes, since in fixed scaling mode we want the destination frame to be applied when a buffer of the new size is queued. This approach is brittle because SurfaceView does not have control over the buffer production and the app can get into a scenario where there is scaled incorrectly. Fix this by configuring BBQ to always apply destination frame changes or always defer to the caller. If the scaling mode is freeze, then BBQ will set a flag to ignore the destination frame. This allows us to synchronize destination frame changes with scale applied by a parent and avoid unwanted scaling if the scaling mode changes to freeze. Test: atest SurfaceViewTest Test: go/wm-smoke Bug: 217973491 Change-Id: I0d214e3f7e45c38e6222a2947ca354c36a202ff5
Diffstat (limited to 'libs/gui/BLASTBufferQueue.cpp')
-rw-r--r--libs/gui/BLASTBufferQueue.cpp35
1 files changed, 18 insertions, 17 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 7ce72ffa59..b7a7aa0ccb 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -132,12 +132,13 @@ void BLASTBufferItemConsumer::onSidebandStreamChanged() {
}
}
-BLASTBufferQueue::BLASTBufferQueue(const std::string& name)
+BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
: mSurfaceControl(nullptr),
mSize(1, 1),
mRequestedSize(mSize),
mFormat(PIXEL_FORMAT_RGBA_8888),
- mSyncTransaction(nullptr) {
+ mSyncTransaction(nullptr),
+ mUpdateDestinationFrame(updateDestinationFrame) {
createBufferQueue(&mProducer, &mConsumer);
// since the adapter is in the client process, set dequeue timeout
// explicitly so that dequeueBuffer will block
@@ -184,7 +185,7 @@ BLASTBufferQueue::~BLASTBufferQueue() {
}
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
- int32_t format, SurfaceComposerClient::Transaction* outTransaction) {
+ int32_t format) {
LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
std::unique_lock _lock{mMutex};
@@ -193,7 +194,6 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
}
- SurfaceComposerClient::Transaction t;
const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
if (surfaceControlChanged && mSurfaceControl != nullptr) {
BQA_LOGD("Updating SurfaceControl without recreating BBQ");
@@ -203,6 +203,7 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
// Always update the native object even though they might have the same layer handle, so we can
// get the updated transform hint from WM.
mSurfaceControl = surface;
+ SurfaceComposerClient::Transaction t;
if (surfaceControlChanged) {
t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
layer_state_t::eEnableBackpressure);
@@ -221,12 +222,10 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
// If the buffer supports scaling, update the frame immediately since the client may
// want to scale the existing buffer to the new size.
mSize = mRequestedSize;
- SurfaceComposerClient::Transaction* destFrameTransaction =
- (outTransaction) ? outTransaction : &t;
- destFrameTransaction->setDestinationFrame(mSurfaceControl,
- Rect(0, 0, newSize.getWidth(),
- newSize.getHeight()));
- applyTransaction = true;
+ if (mUpdateDestinationFrame) {
+ t.setDestinationFrame(mSurfaceControl, Rect(newSize));
+ applyTransaction = true;
+ }
}
}
if (applyTransaction) {
@@ -498,7 +497,6 @@ void BLASTBufferQueue::acquireNextBufferLocked(
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
- const bool updateDestinationFrame = mRequestedSize != mSize;
mSize = mRequestedSize;
Rect crop = computeCrop(bufferItem);
mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
@@ -517,12 +515,19 @@ void BLASTBufferQueue::acquireNextBufferLocked(
mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
- if (updateDestinationFrame) {
- t->setDestinationFrame(mSurfaceControl, Rect(0, 0, mSize.getWidth(), mSize.getHeight()));
+ if (mUpdateDestinationFrame) {
+ t->setDestinationFrame(mSurfaceControl, Rect(mSize));
+ } else {
+ const bool ignoreDestinationFrame =
+ bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ t->setFlags(mSurfaceControl,
+ ignoreDestinationFrame ? layer_state_t::eIgnoreDestinationFrame : 0,
+ layer_state_t::eIgnoreDestinationFrame);
}
t->setBufferCrop(mSurfaceControl, crop);
t->setTransform(mSurfaceControl, bufferItem.mTransform);
t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
+ t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
if (!bufferItem.mIsAutoTimestamp) {
t->setDesiredPresentTime(bufferItem.mTimestamp);
}
@@ -532,10 +537,6 @@ void BLASTBufferQueue::acquireNextBufferLocked(
mNextFrameTimelineInfoQueue.pop();
}
- if (mAutoRefresh != bufferItem.mAutoRefresh) {
- t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
- mAutoRefresh = bufferItem.mAutoRefresh;
- }
{
std::unique_lock _lock{mTimestampMutex};
auto dequeueTime = mDequeueTimestamps.find(buffer->getId());