Merge "Add buffer rejection logic to BlastBufferQueue"
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index ba72f9b..cce434a 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -166,8 +166,8 @@
const std::vector<SurfaceControlStats>& stats) {
std::unique_lock _lock{mMutex};
ATRACE_CALL();
-
BQA_LOGV("transactionCallback");
+ mInitialCallbackReceived = true;
if (!stats.empty()) {
mTransformHint = stats[0].transformHint;
@@ -185,7 +185,7 @@
if (!stats.empty()) {
mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence;
} else {
- ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");
+ BQA_LOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");
mPendingReleaseItem.releaseFence = nullptr;
}
mBufferItemConsumer->releaseBuffer(mPendingReleaseItem.item,
@@ -198,7 +198,7 @@
}
if (mSubmitted.empty()) {
- ALOGE("ERROR: callback with no corresponding submitted buffer item");
+ BQA_LOGE("ERROR: callback with no corresponding submitted buffer item");
}
mPendingReleaseItem.item = std::move(mSubmitted.front());
mSubmitted.pop();
@@ -213,12 +213,18 @@
ATRACE_CALL();
BQA_LOGV("processNextBufferLocked useNextTransaction=%s", toString(useNextTransaction));
- if (mNumFrameAvailable == 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS + 1) {
+ // Wait to acquire a buffer if there are no frames available or we have acquired the maximum
+ // number of buffers.
+ // As a special case, we wait for the first callback before acquiring the second buffer so we
+ // can ensure the first buffer is presented if multiple buffers are queued in succession.
+ if (mNumFrameAvailable == 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS + 1 ||
+ (!mInitialCallbackReceived && mNumAcquired == 1)) {
+ BQA_LOGV("processNextBufferLocked waiting for frame available or callback");
return;
}
if (mSurfaceControl == nullptr) {
- ALOGE("ERROR : surface control is null");
+ BQA_LOGE("ERROR : surface control is null");
return;
}
@@ -245,6 +251,13 @@
return;
}
+ if (rejectBuffer(bufferItem)) {
+ BQA_LOGE("rejecting buffer: configured width=%d, height=%d, buffer{w=%d, h=%d}", mWidth,
+ mHeight, buffer->getWidth(), buffer->getHeight());
+ mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
+ return;
+ }
+
mNumAcquired++;
mSubmitted.push(bufferItem);
@@ -311,4 +324,13 @@
mNextTransaction = t;
}
+bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) const {
+ if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
+ // Only reject buffers if scaling mode is freeze.
+ return false;
+ }
+
+ // reject buffers if the buffer size doesn't match.
+ return item.mGraphicBuffer->getWidth() != mWidth || item.mGraphicBuffer->getHeight() != mHeight;
+}
} // namespace android
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 35c656a..5b1a018 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -94,6 +94,8 @@
void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex);
Rect computeCrop(const BufferItem& item);
+ // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
+ bool rejectBuffer(const BufferItem& item) const;
std::string mName;
sp<SurfaceControl> mSurfaceControl;
@@ -107,6 +109,7 @@
int32_t mNumFrameAvailable GUARDED_BY(mMutex);
int32_t mNumAcquired GUARDED_BY(mMutex);
+ bool mInitialCallbackReceived GUARDED_BY(mMutex) = false;
struct PendingReleaseItem {
BufferItem item;
sp<Fence> releaseFence;