Loading libs/gui/BLASTBufferQueue.cpp +130 −25 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ inline const char* boolToString(bool b) { namespace android { namespace android { // Macros to include adapter info in log messages // Macros to include adapter info in log messages #define BQA_LOGD(x, ...) \ ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) #define BQA_LOGV(x, ...) \ #define BQA_LOGV(x, ...) \ ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) // enable logs for a single layer // enable logs for a single layer Loading Loading @@ -244,6 +246,67 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, } } } } static std::optional<SurfaceControlStats> findMatchingStat( const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) { for (auto stat : stats) { if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) { return stat; } } return std::nullopt; } static void transactionCommittedCallbackThunk(void* context, nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { if (context == nullptr) { return; } sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context); bq->transactionCommittedCallback(latchTime, presentFence, stats); } void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/, const std::vector<SurfaceControlStats>& stats) { { std::unique_lock _lock{mMutex}; ATRACE_CALL(); BQA_LOGV("transactionCommittedCallback"); if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC); if (stat) { uint64_t currFrameNumber = stat->frameEventStats.frameNumber; // We need to check if we were waiting for a transaction callback in order to // process any pending buffers and unblock. It's possible to get transaction // callbacks for previous requests so we need to ensure the frame from this // transaction callback matches the last acquired buffer. Since acquireNextBuffer // will stop processing buffers when mWaitForTransactionCallback is set, we know // that mLastAcquiredFrameNumber is the frame we're waiting on. // We also want to check if mNextTransaction is null because it's possible another // sync request came in while waiting, but it hasn't started processing yet. In that // case, we don't actually want to flush the frames in between since they will get // processed and merged with the sync transaction and released earlier than if they // were sent to SF if (mWaitForTransactionCallback && mNextTransaction == nullptr && currFrameNumber >= mLastAcquiredFrameNumber) { mWaitForTransactionCallback = false; flushShadowQueue(); } } else { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } else { BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was " "empty."); } decStrong((void*)transactionCommittedCallbackThunk); } } static void transactionCallbackThunk(void* context, nsecs_t latchTime, static void transactionCallbackThunk(void* context, nsecs_t latchTime, const sp<Fence>& presentFence, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { const std::vector<SurfaceControlStats>& stats) { Loading @@ -267,12 +330,9 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence if (!mSurfaceControlsWithPendingCallback.empty()) { if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); mSurfaceControlsWithPendingCallback.pop(); mSurfaceControlsWithPendingCallback.pop(); bool found = false; std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC); for (auto stat : stats) { if (statsOptional) { if (!SurfaceControl::isSameSurface(pendingSC, stat.surfaceControl)) { SurfaceControlStats stat = *statsOptional; continue; } mTransformHint = stat.transformHint; mTransformHint = stat.transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); Loading Loading @@ -300,12 +360,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence transactionCompleteCallback = std::move(mTransactionCompleteCallback); transactionCompleteCallback = std::move(mTransactionCompleteCallback); mTransactionCompleteFrameNumber = 0; mTransactionCompleteFrameNumber = 0; } } } else { found = true; break; } if (!found) { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } } else { } else { Loading Loading @@ -336,6 +391,15 @@ static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const Relea } } } } void BLASTBufferQueue::flushShadowQueue() { BQA_LOGV("flushShadowQueue"); int numFramesToFlush = mNumFrameAvailable; while (numFramesToFlush > 0) { acquireNextBufferLocked(std::nullopt); numFramesToFlush--; } } void BLASTBufferQueue::releaseBufferCallback( void BLASTBufferQueue::releaseBufferCallback( const ReleaseCallbackId& id, const sp<Fence>& releaseFence, const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount) { std::optional<uint32_t> currentMaxAcquiredBufferCount) { Loading Loading @@ -374,7 +438,11 @@ void BLASTBufferQueue::releaseBufferCallback( BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mSubmitted.erase(it); mSubmitted.erase(it); processNextBufferLocked(false /* useNextTransaction */); // Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let // onFrameAvailable handle processing them since it will merge with the nextTransaction. if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); } } } ATRACE_INT("PendingRelease", mPendingRelease.size()); ATRACE_INT("PendingRelease", mPendingRelease.size()); Loading @@ -383,13 +451,15 @@ void BLASTBufferQueue::releaseBufferCallback( mCallbackCV.notify_all(); mCallbackCV.notify_all(); } } void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); ATRACE_CALL(); // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't // include the extra buffer when checking if we can acquire the next buffer. // include the extra buffer when checking if we can acquire the next buffer. const bool includeExtraAcquire = !useNextTransaction; const bool includeExtraAcquire = !transaction; if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) { const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); mCallbackCV.notify_all(); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; return; } } Loading @@ -401,9 +471,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { SurfaceComposerClient::Transaction localTransaction; SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; bool applyTransaction = true; SurfaceComposerClient::Transaction* t = &localTransaction; SurfaceComposerClient::Transaction* t = &localTransaction; if (mNextTransaction != nullptr && useNextTransaction) { if (transaction) { t = mNextTransaction; t = *transaction; mNextTransaction = nullptr; applyTransaction = false; applyTransaction = false; } } Loading Loading @@ -433,7 +502,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); processNextBufferLocked(useNextTransaction); acquireNextBufferLocked(transaction); return; return; } } Loading @@ -452,6 +521,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCommittedCallbackThunk); const bool sizeHasChanged = mRequestedSize != mSize; const bool sizeHasChanged = mRequestedSize != mSize; mSize = mRequestedSize; mSize = mRequestedSize; Loading @@ -471,6 +541,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); if (updateDestinationFrame) { if (updateDestinationFrame) { Loading Loading @@ -508,7 +579,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setApplyToken(mApplyToken).apply(); t->setApplyToken(mApplyToken).apply(); } } BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" " graphicBufferId=%" PRIu64 "%s transform=%d", " graphicBufferId=%" PRIu64 "%s transform=%d", mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), Loading @@ -524,17 +595,44 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { return item.mCrop; return item.mCrop; } } void BLASTBufferQueue::acquireAndReleaseBuffer() { BufferItem bufferItem; mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); mNumFrameAvailable--; } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); ATRACE_CALL(); std::unique_lock _lock{mMutex}; std::unique_lock _lock{mMutex}; const bool nextTransactionSet = mNextTransaction != nullptr; const bool nextTransactionSet = mNextTransaction != nullptr; BQA_LOGV("onFrameAvailable-start nextTransactionSet=%s", boolToString(nextTransactionSet)); if (nextTransactionSet) { if (nextTransactionSet) { while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) { if (mWaitForTransactionCallback) { BQA_LOGV("waiting in onFrameAvailable..."); // We are waiting on a previous sync's transaction callback so allow another sync // transaction to proceed. // // We need to first flush out the transactions that were in between the two syncs. // We do this by merging them into mNextTransaction so any buffer merging will get // a release callback invoked. The release callback will be async so we need to wait // on max acquired to make sure we have the capacity to acquire another buffer. if (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting to flush shadow queue..."); mCallbackCV.wait(_lock); mCallbackCV.wait(_lock); } } while (mNumFrameAvailable > 0) { // flush out the shadow queue acquireAndReleaseBuffer(); } } } while (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting for free buffer."); mCallbackCV.wait(_lock); } } // add to shadow queue // add to shadow queue mNumFrameAvailable++; mNumFrameAvailable++; ATRACE_INT(mQueuedBufferTrace.c_str(), ATRACE_INT(mQueuedBufferTrace.c_str(), Loading @@ -542,7 +640,14 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, boolToString(nextTransactionSet)); boolToString(nextTransactionSet)); processNextBufferLocked(nextTransactionSet /* useNextTransaction */); if (nextTransactionSet) { acquireNextBufferLocked(std::move(mNextTransaction)); mNextTransaction = nullptr; mWaitForTransactionCallback = true; } else if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); } } } void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) { void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) { Loading libs/gui/include/gui/BLASTBufferQueue.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -88,6 +88,8 @@ public: void onFrameDequeued(const uint64_t) override; void onFrameDequeued(const uint64_t) override; void onFrameCancelled(const uint64_t) override; void onFrameCancelled(const uint64_t) override; void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats); void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence, void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats); const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, Loading Loading @@ -120,7 +122,8 @@ private: void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer); sp<IGraphicBufferConsumer>* outConsumer); void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex); void acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex); Rect computeCrop(const BufferItem& item) REQUIRES(mMutex); Rect computeCrop(const BufferItem& item) REQUIRES(mMutex); // Return true if we need to reject the buffer based on the scaling mode and the buffer size. // Return true if we need to reject the buffer based on the scaling mode and the buffer size. bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex); bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex); Loading @@ -129,6 +132,9 @@ private: void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) REQUIRES(mMutex); REQUIRES(mMutex); void flushShadowQueue() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); std::string mName; std::string mName; // Represents the queued buffer count from buffer queue, // Represents the queued buffer count from buffer queue, // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + Loading Loading @@ -238,6 +244,7 @@ private: std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; }; }; } // namespace android } // namespace android Loading services/surfaceflinger/tests/utils/CallbackUtils.h→libs/gui/include/gui/test/CallbackUtils.h +4 −6 Original line number Original line Diff line number Diff line Loading @@ -134,10 +134,8 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { nsecs_t latchTime) const { const auto& const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; transformHint, frameEvents] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; << "bad acquire time"; Loading Loading @@ -199,7 +197,7 @@ public: std::this_thread::sleep_for(500ms); std::this_thread::sleep_for(500ms); std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received"; mCallbackDataQueue = {}; mCallbackDataQueue = {}; } } Loading @@ -209,5 +207,5 @@ public: std::condition_variable mConditionVariable; std::condition_variable mConditionVariable; std::queue<CallbackData> mCallbackDataQueue; std::queue<CallbackData> mCallbackDataQueue; }; }; } } // namespace } // namespace android } // namespace android libs/gui/tests/BLASTBufferQueue_test.cpp +266 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes services/surfaceflinger/tests/IPC_test.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <limits> #include <limits> #include <gui/test/CallbackUtils.h> #include "BufferGenerator.h" #include "BufferGenerator.h" #include "utils/CallbackUtils.h" #include "utils/ColorUtils.h" #include "utils/ColorUtils.h" #include "utils/TransactionUtils.h" #include "utils/TransactionUtils.h" Loading Loading
libs/gui/BLASTBufferQueue.cpp +130 −25 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ inline const char* boolToString(bool b) { namespace android { namespace android { // Macros to include adapter info in log messages // Macros to include adapter info in log messages #define BQA_LOGD(x, ...) \ ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) #define BQA_LOGV(x, ...) \ #define BQA_LOGV(x, ...) \ ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) // enable logs for a single layer // enable logs for a single layer Loading Loading @@ -244,6 +246,67 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, } } } } static std::optional<SurfaceControlStats> findMatchingStat( const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) { for (auto stat : stats) { if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) { return stat; } } return std::nullopt; } static void transactionCommittedCallbackThunk(void* context, nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { if (context == nullptr) { return; } sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context); bq->transactionCommittedCallback(latchTime, presentFence, stats); } void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/, const std::vector<SurfaceControlStats>& stats) { { std::unique_lock _lock{mMutex}; ATRACE_CALL(); BQA_LOGV("transactionCommittedCallback"); if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC); if (stat) { uint64_t currFrameNumber = stat->frameEventStats.frameNumber; // We need to check if we were waiting for a transaction callback in order to // process any pending buffers and unblock. It's possible to get transaction // callbacks for previous requests so we need to ensure the frame from this // transaction callback matches the last acquired buffer. Since acquireNextBuffer // will stop processing buffers when mWaitForTransactionCallback is set, we know // that mLastAcquiredFrameNumber is the frame we're waiting on. // We also want to check if mNextTransaction is null because it's possible another // sync request came in while waiting, but it hasn't started processing yet. In that // case, we don't actually want to flush the frames in between since they will get // processed and merged with the sync transaction and released earlier than if they // were sent to SF if (mWaitForTransactionCallback && mNextTransaction == nullptr && currFrameNumber >= mLastAcquiredFrameNumber) { mWaitForTransactionCallback = false; flushShadowQueue(); } } else { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } else { BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was " "empty."); } decStrong((void*)transactionCommittedCallbackThunk); } } static void transactionCallbackThunk(void* context, nsecs_t latchTime, static void transactionCallbackThunk(void* context, nsecs_t latchTime, const sp<Fence>& presentFence, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { const std::vector<SurfaceControlStats>& stats) { Loading @@ -267,12 +330,9 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence if (!mSurfaceControlsWithPendingCallback.empty()) { if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); mSurfaceControlsWithPendingCallback.pop(); mSurfaceControlsWithPendingCallback.pop(); bool found = false; std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC); for (auto stat : stats) { if (statsOptional) { if (!SurfaceControl::isSameSurface(pendingSC, stat.surfaceControl)) { SurfaceControlStats stat = *statsOptional; continue; } mTransformHint = stat.transformHint; mTransformHint = stat.transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); Loading Loading @@ -300,12 +360,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence transactionCompleteCallback = std::move(mTransactionCompleteCallback); transactionCompleteCallback = std::move(mTransactionCompleteCallback); mTransactionCompleteFrameNumber = 0; mTransactionCompleteFrameNumber = 0; } } } else { found = true; break; } if (!found) { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } } else { } else { Loading Loading @@ -336,6 +391,15 @@ static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const Relea } } } } void BLASTBufferQueue::flushShadowQueue() { BQA_LOGV("flushShadowQueue"); int numFramesToFlush = mNumFrameAvailable; while (numFramesToFlush > 0) { acquireNextBufferLocked(std::nullopt); numFramesToFlush--; } } void BLASTBufferQueue::releaseBufferCallback( void BLASTBufferQueue::releaseBufferCallback( const ReleaseCallbackId& id, const sp<Fence>& releaseFence, const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount) { std::optional<uint32_t> currentMaxAcquiredBufferCount) { Loading Loading @@ -374,7 +438,11 @@ void BLASTBufferQueue::releaseBufferCallback( BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mSubmitted.erase(it); mSubmitted.erase(it); processNextBufferLocked(false /* useNextTransaction */); // Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let // onFrameAvailable handle processing them since it will merge with the nextTransaction. if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); } } } ATRACE_INT("PendingRelease", mPendingRelease.size()); ATRACE_INT("PendingRelease", mPendingRelease.size()); Loading @@ -383,13 +451,15 @@ void BLASTBufferQueue::releaseBufferCallback( mCallbackCV.notify_all(); mCallbackCV.notify_all(); } } void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); ATRACE_CALL(); // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't // include the extra buffer when checking if we can acquire the next buffer. // include the extra buffer when checking if we can acquire the next buffer. const bool includeExtraAcquire = !useNextTransaction; const bool includeExtraAcquire = !transaction; if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) { const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); mCallbackCV.notify_all(); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; return; } } Loading @@ -401,9 +471,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { SurfaceComposerClient::Transaction localTransaction; SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; bool applyTransaction = true; SurfaceComposerClient::Transaction* t = &localTransaction; SurfaceComposerClient::Transaction* t = &localTransaction; if (mNextTransaction != nullptr && useNextTransaction) { if (transaction) { t = mNextTransaction; t = *transaction; mNextTransaction = nullptr; applyTransaction = false; applyTransaction = false; } } Loading Loading @@ -433,7 +502,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); processNextBufferLocked(useNextTransaction); acquireNextBufferLocked(transaction); return; return; } } Loading @@ -452,6 +521,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCommittedCallbackThunk); const bool sizeHasChanged = mRequestedSize != mSize; const bool sizeHasChanged = mRequestedSize != mSize; mSize = mRequestedSize; mSize = mRequestedSize; Loading @@ -471,6 +541,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); if (updateDestinationFrame) { if (updateDestinationFrame) { Loading Loading @@ -508,7 +579,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setApplyToken(mApplyToken).apply(); t->setApplyToken(mApplyToken).apply(); } } BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" " graphicBufferId=%" PRIu64 "%s transform=%d", " graphicBufferId=%" PRIu64 "%s transform=%d", mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), Loading @@ -524,17 +595,44 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { return item.mCrop; return item.mCrop; } } void BLASTBufferQueue::acquireAndReleaseBuffer() { BufferItem bufferItem; mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); mNumFrameAvailable--; } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); ATRACE_CALL(); std::unique_lock _lock{mMutex}; std::unique_lock _lock{mMutex}; const bool nextTransactionSet = mNextTransaction != nullptr; const bool nextTransactionSet = mNextTransaction != nullptr; BQA_LOGV("onFrameAvailable-start nextTransactionSet=%s", boolToString(nextTransactionSet)); if (nextTransactionSet) { if (nextTransactionSet) { while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) { if (mWaitForTransactionCallback) { BQA_LOGV("waiting in onFrameAvailable..."); // We are waiting on a previous sync's transaction callback so allow another sync // transaction to proceed. // // We need to first flush out the transactions that were in between the two syncs. // We do this by merging them into mNextTransaction so any buffer merging will get // a release callback invoked. The release callback will be async so we need to wait // on max acquired to make sure we have the capacity to acquire another buffer. if (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting to flush shadow queue..."); mCallbackCV.wait(_lock); mCallbackCV.wait(_lock); } } while (mNumFrameAvailable > 0) { // flush out the shadow queue acquireAndReleaseBuffer(); } } } while (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting for free buffer."); mCallbackCV.wait(_lock); } } // add to shadow queue // add to shadow queue mNumFrameAvailable++; mNumFrameAvailable++; ATRACE_INT(mQueuedBufferTrace.c_str(), ATRACE_INT(mQueuedBufferTrace.c_str(), Loading @@ -542,7 +640,14 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, boolToString(nextTransactionSet)); boolToString(nextTransactionSet)); processNextBufferLocked(nextTransactionSet /* useNextTransaction */); if (nextTransactionSet) { acquireNextBufferLocked(std::move(mNextTransaction)); mNextTransaction = nullptr; mWaitForTransactionCallback = true; } else if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); } } } void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) { void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) { Loading
libs/gui/include/gui/BLASTBufferQueue.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -88,6 +88,8 @@ public: void onFrameDequeued(const uint64_t) override; void onFrameDequeued(const uint64_t) override; void onFrameCancelled(const uint64_t) override; void onFrameCancelled(const uint64_t) override; void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats); void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence, void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats); const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, Loading Loading @@ -120,7 +122,8 @@ private: void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer); sp<IGraphicBufferConsumer>* outConsumer); void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex); void acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex); Rect computeCrop(const BufferItem& item) REQUIRES(mMutex); Rect computeCrop(const BufferItem& item) REQUIRES(mMutex); // Return true if we need to reject the buffer based on the scaling mode and the buffer size. // Return true if we need to reject the buffer based on the scaling mode and the buffer size. bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex); bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex); Loading @@ -129,6 +132,9 @@ private: void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) REQUIRES(mMutex); REQUIRES(mMutex); void flushShadowQueue() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); std::string mName; std::string mName; // Represents the queued buffer count from buffer queue, // Represents the queued buffer count from buffer queue, // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + Loading Loading @@ -238,6 +244,7 @@ private: std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; }; }; } // namespace android } // namespace android Loading
services/surfaceflinger/tests/utils/CallbackUtils.h→libs/gui/include/gui/test/CallbackUtils.h +4 −6 Original line number Original line Diff line number Diff line Loading @@ -134,10 +134,8 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { nsecs_t latchTime) const { const auto& const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; transformHint, frameEvents] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; << "bad acquire time"; Loading Loading @@ -199,7 +197,7 @@ public: std::this_thread::sleep_for(500ms); std::this_thread::sleep_for(500ms); std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received"; mCallbackDataQueue = {}; mCallbackDataQueue = {}; } } Loading @@ -209,5 +207,5 @@ public: std::condition_variable mConditionVariable; std::condition_variable mConditionVariable; std::queue<CallbackData> mCallbackDataQueue; std::queue<CallbackData> mCallbackDataQueue; }; }; } } // namespace } // namespace android } // namespace android
libs/gui/tests/BLASTBufferQueue_test.cpp +266 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/surfaceflinger/tests/IPC_test.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <limits> #include <limits> #include <gui/test/CallbackUtils.h> #include "BufferGenerator.h" #include "BufferGenerator.h" #include "utils/CallbackUtils.h" #include "utils/ColorUtils.h" #include "utils/ColorUtils.h" #include "utils/TransactionUtils.h" #include "utils/TransactionUtils.h" Loading