diff options
| -rw-r--r-- | libs/gui/BLASTBufferQueue.cpp | 85 | ||||
| -rw-r--r-- | libs/gui/include/gui/BLASTBufferQueue.h | 20 | ||||
| -rw-r--r-- | libs/gui/tests/BLASTBufferQueue_test.cpp | 4 |
3 files changed, 67 insertions, 42 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index b9cf9e1285..a5e5693ff4 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -17,10 +17,14 @@ #undef LOG_TAG #define LOG_TAG "BLASTBufferQueue" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + #include <gui/BLASTBufferQueue.h> #include <gui/BufferItemConsumer.h> #include <gui/GLConsumer.h> +#include <utils/Trace.h> + #include <chrono> using namespace std::chrono_literals; @@ -29,23 +33,29 @@ namespace android { BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height) : mSurfaceControl(surface), - mPendingCallbacks(0), mWidth(width), mHeight(height), mNextTransaction(nullptr) { BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setMaxBufferCount(MAX_BUFFERS); mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1); + mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS); mBufferItemConsumer = new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); - mBufferItemConsumer->setName(String8("BLAST Consumer")); + static int32_t id = 0; + auto name = std::string("BLAST Consumer") + std::to_string(id); + id++; + mBufferItemConsumer->setName(String8(name.c_str())); mBufferItemConsumer->setFrameAvailableListener(this); mBufferItemConsumer->setBufferFreedListener(this); mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888); mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint()); - mAcquired = false; + mNumAcquired = 0; + mNumFrameAvailable = 0; + mPendingReleaseItem.item = BufferItem(); + mPendingReleaseItem.releaseFence = nullptr; } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) { @@ -70,34 +80,46 @@ static void transactionCallbackThunk(void* context, nsecs_t latchTime, void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/, const std::vector<SurfaceControlStats>& stats) { std::unique_lock _lock{mMutex}; - - if (stats.size() > 0 && !mShadowQueue.empty()) { - mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem, - stats[0].previousReleaseFence - ? stats[0].previousReleaseFence + ATRACE_CALL(); + + if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { + if (stats.size() > 0) { + mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; + mTransformHint = stats[0].transformHint; + } else { + ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback"); + mPendingReleaseItem.releaseFence = nullptr; + } + mBufferItemConsumer->releaseBuffer(mPendingReleaseItem.item, + mPendingReleaseItem.releaseFence + ? mPendingReleaseItem.releaseFence : Fence::NO_FENCE); - mAcquired = false; - mNextCallbackBufferItem = BufferItem(); - mBufferItemConsumer->setTransformHint(stats[0].transformHint); + mNumAcquired--; + mPendingReleaseItem.item = BufferItem(); + mPendingReleaseItem.releaseFence = nullptr; + } + + if (mSubmitted.empty()) { + ALOGE("ERROR: callback with no corresponding submitted buffer item"); } - mPendingCallbacks--; + mPendingReleaseItem.item = std::move(mSubmitted.front()); + mSubmitted.pop(); processNextBufferLocked(); mCallbackCV.notify_all(); decStrong((void*)transactionCallbackThunk); } void BLASTBufferQueue::processNextBufferLocked() { - if (mShadowQueue.empty()) { + ATRACE_CALL(); + if (mNumFrameAvailable == 0) { return; } - if (mAcquired) { + if (mSurfaceControl == nullptr) { + ALOGE("ERROR : surface control is null"); return; } - BufferItem item = std::move(mShadowQueue.front()); - mShadowQueue.pop(); - SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; SurfaceComposerClient::Transaction* t = &localTransaction; @@ -107,33 +129,34 @@ void BLASTBufferQueue::processNextBufferLocked() { applyTransaction = false; } - mNextCallbackBufferItem = mLastSubmittedBufferItem; - mLastSubmittedBufferItem = BufferItem(); + BufferItem bufferItem; - status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false); - mAcquired = true; + status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, -1, false); if (status != OK) { - ALOGE("Failed to acquire?"); + return; } - - auto buffer = mLastSubmittedBufferItem.mGraphicBuffer; + auto buffer = bufferItem.mGraphicBuffer; + mNumFrameAvailable--; if (buffer == nullptr) { - ALOGE("Null buffer"); + mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); return; } + mNumAcquired++; + mSubmitted.push(bufferItem); + // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); t->setBuffer(mSurfaceControl, buffer); t->setAcquireFence(mSurfaceControl, - item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE); + bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()}); - t->setCrop(mSurfaceControl, computeCrop(mLastSubmittedBufferItem)); - t->setTransform(mSurfaceControl, mLastSubmittedBufferItem.mTransform); + t->setCrop(mSurfaceControl, computeCrop(bufferItem)); + t->setTransform(mSurfaceControl, bufferItem.mTransform); if (applyTransaction) { t->apply(); @@ -147,13 +170,13 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { return item.mCrop; } -void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { +void BLASTBufferQueue::onFrameAvailable(const BufferItem& /*item*/) { + ATRACE_CALL(); std::lock_guard _lock{mMutex}; // add to shadow queue - mShadowQueue.push(item); + mNumFrameAvailable++; processNextBufferLocked(); - mPendingCallbacks++; } void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index dd0b4709e5..0a0a03c8f6 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -68,23 +68,25 @@ private: std::mutex mMutex; std::condition_variable mCallbackCV; - uint64_t mPendingCallbacks GUARDED_BY(mMutex); static const int MAX_BUFFERS = 3; - struct BufferInfo { - sp<GraphicBuffer> buffer; - int fence; + static const int MAX_ACQUIRED_BUFFERS = 2; + + int32_t mNumFrameAvailable GUARDED_BY(mMutex); + int32_t mNumAcquired GUARDED_BY(mMutex); + + struct PendingReleaseItem { + BufferItem item; + sp<Fence> releaseFence; }; - std::queue<const BufferItem> mShadowQueue GUARDED_BY(mMutex); - bool mAcquired GUARDED_BY(mMutex); + std::queue<const BufferItem> mSubmitted GUARDED_BY(mMutex); + PendingReleaseItem mPendingReleaseItem GUARDED_BY(mMutex); int mWidth GUARDED_BY(mMutex); int mHeight GUARDED_BY(mMutex); - BufferItem mLastSubmittedBufferItem GUARDED_BY(mMutex); - BufferItem mNextCallbackBufferItem GUARDED_BY(mMutex); - sp<Fence> mLastFence GUARDED_BY(mMutex); + uint32_t mTransformHint GUARDED_BY(mMutex); sp<IGraphicBufferConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 48a5cb63f3..0f618f181c 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -69,7 +69,7 @@ public: void waitForCallbacks() { std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; - while (mBlastBufferQueueAdapter->mPendingCallbacks > 0) { + while (mBlastBufferQueueAdapter->mSubmitted.size() > 0) { mBlastBufferQueueAdapter->mCallbackCV.wait(lock); } } @@ -302,7 +302,7 @@ TEST_F(BLASTBufferQueueTest, TripleBuffering) { igbProducer->cancelBuffer(allocated[i].first, allocated[i].second); } - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 100; i++) { int slot; sp<Fence> fence; sp<GraphicBuffer> buf; |