Track BBQ dequeue count and mode
Counts, shared buffer mode, and async mode will be used to determine when dequeueBuffer should block.
Bug: 294133380
Flag: com.android.graphics.libgui.flags.buffer_release_channel
Test: BLASTBufferQueueTest
Change-Id: I23cd5606f84ac5e0c29c470d05b28153fc4c9ce8
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 739c3c2..7f0e80e 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -39,7 +39,6 @@
#include <private/gui/ComposerServiceAIDL.h>
#include <android-base/thread_annotations.h>
-#include <chrono>
#include <com_android_graphics_libgui_flags.h>
@@ -179,8 +178,6 @@
// explicitly so that dequeueBuffer will block
mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
- // safe default, most producers are expected to override this
- mProducer->setMaxDequeuedBufferCount(2);
mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_HW_TEXTURE,
@@ -236,6 +233,11 @@
}
}
+void BLASTBufferQueue::onFirstRef() {
+ // safe default, most producers are expected to override this
+ mProducer->setMaxDequeuedBufferCount(2);
+}
+
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
int32_t format) {
LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
@@ -499,7 +501,13 @@
callbackId.to_string().c_str());
return;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ if (!it->second.mIsStale) {
+ mNumAcquired--;
+ }
+#else
mNumAcquired--;
+#endif
BBQ_TRACE("frame=%" PRIu64, callbackId.framenumber);
BQA_LOGV("released %s", callbackId.to_string().c_str());
mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
@@ -761,6 +769,9 @@
}
// add to shadow queue
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mNumDequeued--;
+#endif
mNumFrameAvailable++;
if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
acquireAndReleaseBuffer();
@@ -815,9 +826,18 @@
};
void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
- std::lock_guard _lock{mTimestampMutex};
- mDequeueTimestamps.erase(bufferId);
-};
+ {
+ std::lock_guard _lock{mTimestampMutex};
+ mDequeueTimestamps.erase(bufferId);
+ }
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ {
+ std::lock_guard lock{mMutex};
+ mNumDequeued--;
+ }
+#endif
+}
bool BLASTBufferQueue::syncNextTransaction(
std::function<void(SurfaceComposerClient::Transaction*)> callback,
@@ -1116,30 +1136,143 @@
producerControlledByApp, output);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ status_t disconnect(int api, DisconnectMode mode) override {
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return BufferQueueProducer::disconnect(api, mode);
+ }
+
+ std::lock_guard lock{bbq->mMutex};
+ if (status_t status = BufferQueueProducer::disconnect(api, mode); status != OK) {
+ return status;
+ }
+
+ bbq->mNumDequeued = 0;
+ bbq->mNumAcquired = 0;
+ for (auto& [releaseId, bufferItem] : bbq->mSubmitted) {
+ bufferItem.mIsStale = true;
+ }
+
+ return OK;
+ }
+
+ status_t setAsyncMode(bool asyncMode) override {
+ if (status_t status = BufferQueueProducer::setAsyncMode(asyncMode); status != OK) {
+ return status;
+ }
+
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return OK;
+ }
+
+ {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mAsyncMode = asyncMode;
+ }
+
+ return OK;
+ }
+
+ status_t setSharedBufferMode(bool sharedBufferMode) override {
+ if (status_t status = BufferQueueProducer::setSharedBufferMode(sharedBufferMode);
+ status != OK) {
+ return status;
+ }
+
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return OK;
+ }
+
+ {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mSharedBufferMode = sharedBufferMode;
+ }
+
+ return OK;
+ }
+
+ status_t detachBuffer(int slot) override {
+ if (status_t status = BufferQueueProducer::detachBuffer(slot); status != OK) {
+ return status;
+ }
+
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return OK;
+ }
+
+ {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mNumDequeued--;
+ }
+
+ return OK;
+ }
+
+ status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width, uint32_t height,
+ PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+ FrameEventHistoryDelta* outTimestamps) override {
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return BufferQueueProducer::dequeueBuffer(outSlot, outFence, width, height, format,
+ usage, outBufferAge, outTimestamps);
+ }
+
+ {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mNumDequeued++;
+ }
+
+ status_t status =
+ BufferQueueProducer::dequeueBuffer(outSlot, outFence, width, height, format, usage,
+ outBufferAge, outTimestamps);
+ if (status < 0) {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mNumDequeued--;
+ }
+ return status;
+ }
+#endif
+
// We want to resize the frame history when changing the size of the buffer queue
status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
int maxBufferCount;
- status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
- &maxBufferCount);
- // if we can't determine the max buffer count, then just skip growing the history size
- if (status == OK) {
- size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
- // optimize away resizing the frame history unless it will grow
- if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
- sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
- if (bbq != nullptr) {
- ALOGV("increasing frame history size to %zu", newFrameHistorySize);
- bbq->resizeFrameEventHistory(newFrameHistorySize);
- }
- }
+ if (status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
+ &maxBufferCount);
+ status != OK) {
+ return status;
}
- return status;
+
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return OK;
+ }
+
+ // if we can't determine the max buffer count, then just skip growing the history size
+ size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
+ // optimize away resizing the frame history unless it will grow
+ if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
+ ALOGV("increasing frame history size to %zu", newFrameHistorySize);
+ bbq->resizeFrameEventHistory(newFrameHistorySize);
+ }
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ {
+ std::lock_guard lock{bbq->mMutex};
+ bbq->mMaxDequeuedBuffers = maxDequeuedBufferCount;
+ }
+#endif
+
+ return OK;
}
int query(int what, int* value) override {
if (what == NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER) {
*value = 1;
- return NO_ERROR;
+ return OK;
}
return BufferQueueProducer::query(what, value);
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 0e1a505..266729a 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -28,7 +28,6 @@
#include <utils/RefBase.h>
#include <system/window.h>
-#include <thread>
#include <queue>
#include <com_android_graphics_libgui_flags.h>
@@ -131,6 +130,8 @@
virtual ~BLASTBufferQueue();
+ void onFirstRef() override;
+
private:
friend class BLASTBufferQueueHelper;
friend class BBQBufferQueueProducer;
@@ -170,8 +171,16 @@
// BufferQueue internally allows 1 more than
// the max to be acquired
- int32_t mMaxAcquiredBuffers = 1;
+ int32_t mMaxAcquiredBuffers GUARDED_BY(mMutex) = 1;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ int32_t mMaxDequeuedBuffers GUARDED_BY(mMutex) = 1;
+ static constexpr int32_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
+ bool mAsyncMode GUARDED_BY(mMutex) = false;
+ bool mSharedBufferMode GUARDED_BY(mMutex) = false;
+
+ int32_t mNumDequeued GUARDED_BY(mMutex) = 0;
+#endif
int32_t mNumFrameAvailable GUARDED_BY(mMutex) = 0;
int32_t mNumAcquired GUARDED_BY(mMutex) = 0;