Loading libs/gui/BLASTBufferQueue.cpp +54 −31 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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; Loading @@ -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(); Loading @@ -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) { Loading libs/gui/include/gui/BLASTBufferQueue.h +11 −9 Original line number Diff line number Diff line Loading @@ -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; Loading libs/gui/tests/BLASTBufferQueue_test.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -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); } } Loading Loading @@ -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; Loading Loading
libs/gui/BLASTBufferQueue.cpp +54 −31 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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; Loading @@ -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(); Loading @@ -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) { Loading
libs/gui/include/gui/BLASTBufferQueue.h +11 −9 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -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); } } Loading Loading @@ -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; Loading