summaryrefslogtreecommitdiff
path: root/libs/gui/BLASTBufferQueue.cpp
diff options
context:
space:
mode:
author chaviw <chaviw@google.com> 2021-09-27 09:37:30 -0500
committer chaviw <chaviw@google.com> 2021-10-08 09:10:52 -0500
commit69058fb42b64794bb86a8ed23693eaf3dcc686ea (patch)
tree3d1a7a0e2706f6513ff3c303c1cb90b27b564f0c /libs/gui/BLASTBufferQueue.cpp
parent6cb6100dd6c1f4a2d50a74905df46b84382236cc (diff)
Call release buffer if the buffer is overwritten in the client
Clients can overwrite the buffer in a transaction before it's applied. When this happens, the buffer is then replaced, but the client doesn't get a callback that the buffer was released. This could cause the client to run out of buffers since the dropped ones become lost. This can happen in two situations: 1. Merging two transactions where each has a buffer for the same SurfaceControl 2. Transaction.setBuffer is called multiple times before an apply In both cases, call the release callback so the client can properly handle the dropped buffers. It's also possible that the merging occurs in a different process than the one that set the buffer. Because of that, we need to ensure we call the correct releaseBufferListener that's associated with the one that set the buffer. The transformHint is removed from the releaseCallback since it's already provided in the transaction callback. It was originally added in the release callback to give it to BBQ early so it can know the new transform hint before rendering a new frame. However, the transform hint is now provided by VRI to BBQ so it no longer needs to be sent back via release callback. Test: ReleaseBufferCallbackTest Change-Id: I9df0c713bf841f53e1a3d092f33179573a680dc4 Bug: 200285149
Diffstat (limited to 'libs/gui/BLASTBufferQueue.cpp')
-rw-r--r--libs/gui/BLASTBufferQueue.cpp32
1 files changed, 14 insertions, 18 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 2b17616eda..36de581e38 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -162,6 +162,7 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont
ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
+ mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
@@ -325,31 +326,23 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
// So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
// Otherwise, this is a no-op.
static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const ReleaseCallbackId& id,
- const sp<Fence>& releaseFence, uint32_t transformHint,
- uint32_t currentMaxAcquiredBufferCount) {
+ const sp<Fence>& releaseFence,
+ std::optional<uint32_t> currentMaxAcquiredBufferCount) {
sp<BLASTBufferQueue> blastBufferQueue = context.promote();
if (blastBufferQueue) {
- blastBufferQueue->releaseBufferCallback(id, releaseFence, transformHint,
- currentMaxAcquiredBufferCount);
+ blastBufferQueue->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
} else {
ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
}
}
-void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
- const sp<Fence>& releaseFence, uint32_t transformHint,
- uint32_t currentMaxAcquiredBufferCount) {
+void BLASTBufferQueue::releaseBufferCallback(
+ const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
+ std::optional<uint32_t> currentMaxAcquiredBufferCount) {
ATRACE_CALL();
std::unique_lock _lock{mMutex};
BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
- if (mSurfaceControl != nullptr) {
- mTransformHint = transformHint;
- mSurfaceControl->setTransformHint(transformHint);
- mBufferItemConsumer->setTransformHint(mTransformHint);
- BQA_LOGV("updated mTransformHint=%d", mTransformHint);
- }
-
// Calculate how many buffers we need to hold before we release them back
// to the buffer queue. This will prevent higher latency when we are running
// on a lower refresh rate than the max supported. We only do that for EGL
@@ -359,8 +352,12 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
}();
+ if (currentMaxAcquiredBufferCount) {
+ mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
+ }
+
const auto numPendingBuffersToHold =
- isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0;
+ isEGL ? std::max(0u, mMaxAcquiredBuffers - mCurrentMaxAcquiredBufferCount) : 0;
mPendingRelease.emplace_back(ReleasedBuffer{id, releaseFence});
// Release all buffers that are beyond the ones that we need to hold
@@ -374,7 +371,7 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
return;
}
mNumAcquired--;
- BQA_LOGV("released %s", id.to_string().c_str());
+ BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str());
mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
mSubmitted.erase(it);
processNextBufferLocked(false /* useNextTransaction */);
@@ -466,8 +463,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
auto releaseBufferCallback =
std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
- std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
- std::placeholders::_4);
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId,
releaseBufferCallback);