Loading libs/gui/BLASTBufferQueue.cpp +135 −25 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ inline const char* boolToString(bool b) { namespace android { // 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, ...) \ ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) // enable logs for a single layer Loading Loading @@ -243,6 +245,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; flushShadowQueueLocked(); } } 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, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { Loading @@ -266,12 +329,9 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); mSurfaceControlsWithPendingCallback.pop(); bool found = false; for (auto stat : stats) { if (!SurfaceControl::isSameSurface(pendingSC, stat.surfaceControl)) { continue; } std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC); if (statsOptional) { SurfaceControlStats stat = *statsOptional; mTransformHint = stat.transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); Loading Loading @@ -299,12 +359,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence transactionCompleteCallback = std::move(mTransactionCompleteCallback); mTransactionCompleteFrameNumber = 0; } found = true; break; } if (!found) { } else { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } else { Loading Loading @@ -336,6 +391,20 @@ static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const Relea } } void BLASTBufferQueue::flushShadowQueueLocked() { BQA_LOGV("flushShadowQueueLocked"); int numFramesToFlush = mNumFrameAvailable; while (numFramesToFlush > 0) { acquireNextBufferLocked(std::nullopt); numFramesToFlush--; } } void BLASTBufferQueue::flushShadowQueue() { std::unique_lock _lock{mMutex}; flushShadowQueueLocked(); } void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) { Loading Loading @@ -377,7 +446,11 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, BQA_LOGV("released %s", id.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); 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()); Loading @@ -386,13 +459,15 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, mCallbackCV.notify_all(); } void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); // 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. const bool includeExtraAcquire = !useNextTransaction; if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) { mCallbackCV.notify_all(); const bool includeExtraAcquire = !transaction; const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; } Loading @@ -404,9 +479,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; SurfaceComposerClient::Transaction* t = &localTransaction; if (mNextTransaction != nullptr && useNextTransaction) { t = mNextTransaction; mNextTransaction = nullptr; if (transaction) { t = *transaction; applyTransaction = false; } Loading Loading @@ -436,7 +510,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); processNextBufferLocked(useNextTransaction); acquireNextBufferLocked(transaction); return; } Loading @@ -455,6 +529,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCommittedCallbackThunk); const bool sizeHasChanged = mRequestedSize != mSize; mSize = mRequestedSize; Loading @@ -475,6 +550,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setAcquireFence(mSurfaceControl, bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); if (updateDestinationFrame) { Loading Loading @@ -527,7 +603,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { 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" " graphicBufferId=%" PRIu64 "%s transform=%d", mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), Loading @@ -543,17 +619,44 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { 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) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool nextTransactionSet = mNextTransaction != nullptr; BQA_LOGV("onFrameAvailable-start nextTransactionSet=%s", boolToString(nextTransactionSet)); if (nextTransactionSet) { while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGV("waiting in onFrameAvailable..."); if (mWaitForTransactionCallback) { // 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); } 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 mNumFrameAvailable++; ATRACE_INT(mQueuedBufferTrace.c_str(), Loading @@ -561,7 +664,14 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, 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) { Loading libs/gui/include/gui/BLASTBufferQueue.h +11 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ public: void onFrameDequeued(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, const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, Loading @@ -99,7 +101,6 @@ public: void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format, SurfaceComposerClient::Transaction* outTransaction = nullptr); void flushShadowQueue() {} status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineInfo(const FrameTimelineInfo& info); Loading @@ -107,6 +108,7 @@ public: void setSidebandStream(const sp<NativeHandle>& stream); uint32_t getLastTransformHint() const; void flushShadowQueue(); virtual ~BLASTBufferQueue(); Loading @@ -119,13 +121,17 @@ private: void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, 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); // 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 maxBuffersAcquired(bool includeExtraAcquire) const REQUIRES(mMutex); static PixelFormat convertBufferFormat(PixelFormat& format); void flushShadowQueueLocked() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); std::string mName; // Represents the queued buffer count from buffer queue, // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + Loading Loading @@ -233,6 +239,9 @@ private: // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a // callback for them. std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; }; } // namespace android Loading services/surfaceflinger/tests/utils/CallbackUtils.h→libs/gui/include/gui/test/CallbackUtils.h +4 −6 Original line number Diff line number Diff line Loading @@ -134,10 +134,8 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; Loading Loading @@ -199,7 +197,7 @@ public: std::this_thread::sleep_for(500ms); std::lock_guard lock(mMutex); EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received"; mCallbackDataQueue = {}; } Loading @@ -209,5 +207,5 @@ public: std::condition_variable mConditionVariable; std::queue<CallbackData> mCallbackDataQueue; }; } } // namespace } // 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 Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <limits> #include <gui/test/CallbackUtils.h> #include "BufferGenerator.h" #include "utils/CallbackUtils.h" #include "utils/ColorUtils.h" #include "utils/TransactionUtils.h" Loading Loading
libs/gui/BLASTBufferQueue.cpp +135 −25 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ inline const char* boolToString(bool b) { namespace android { // 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, ...) \ ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__) // enable logs for a single layer Loading Loading @@ -243,6 +245,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; flushShadowQueueLocked(); } } 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, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats) { Loading @@ -266,12 +329,9 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence if (!mSurfaceControlsWithPendingCallback.empty()) { sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front(); mSurfaceControlsWithPendingCallback.pop(); bool found = false; for (auto stat : stats) { if (!SurfaceControl::isSameSurface(pendingSC, stat.surfaceControl)) { continue; } std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC); if (statsOptional) { SurfaceControlStats stat = *statsOptional; mTransformHint = stat.transformHint; mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); Loading Loading @@ -299,12 +359,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence transactionCompleteCallback = std::move(mTransactionCompleteCallback); mTransactionCompleteFrameNumber = 0; } found = true; break; } if (!found) { } else { BQA_LOGE("Failed to find matching SurfaceControl in transaction callback"); } } else { Loading Loading @@ -336,6 +391,20 @@ static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const Relea } } void BLASTBufferQueue::flushShadowQueueLocked() { BQA_LOGV("flushShadowQueueLocked"); int numFramesToFlush = mNumFrameAvailable; while (numFramesToFlush > 0) { acquireNextBufferLocked(std::nullopt); numFramesToFlush--; } } void BLASTBufferQueue::flushShadowQueue() { std::unique_lock _lock{mMutex}; flushShadowQueueLocked(); } void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) { Loading Loading @@ -377,7 +446,11 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, BQA_LOGV("released %s", id.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); 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()); Loading @@ -386,13 +459,15 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id, mCallbackCV.notify_all(); } void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); // 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. const bool includeExtraAcquire = !useNextTransaction; if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) { mCallbackCV.notify_all(); const bool includeExtraAcquire = !transaction; const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; } Loading @@ -404,9 +479,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { SurfaceComposerClient::Transaction localTransaction; bool applyTransaction = true; SurfaceComposerClient::Transaction* t = &localTransaction; if (mNextTransaction != nullptr && useNextTransaction) { t = mNextTransaction; mNextTransaction = nullptr; if (transaction) { t = *transaction; applyTransaction = false; } Loading Loading @@ -436,7 +510,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); processNextBufferLocked(useNextTransaction); acquireNextBufferLocked(transaction); return; } Loading @@ -455,6 +529,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); incStrong((void*)transactionCommittedCallbackThunk); const bool sizeHasChanged = mRequestedSize != mSize; mSize = mRequestedSize; Loading @@ -475,6 +550,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setAcquireFence(mSurfaceControl, bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); if (updateDestinationFrame) { Loading Loading @@ -527,7 +603,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { 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" " graphicBufferId=%" PRIu64 "%s transform=%d", mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction), Loading @@ -543,17 +619,44 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { 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) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool nextTransactionSet = mNextTransaction != nullptr; BQA_LOGV("onFrameAvailable-start nextTransactionSet=%s", boolToString(nextTransactionSet)); if (nextTransactionSet) { while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGV("waiting in onFrameAvailable..."); if (mWaitForTransactionCallback) { // 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); } 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 mNumFrameAvailable++; ATRACE_INT(mQueuedBufferTrace.c_str(), Loading @@ -561,7 +664,14 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, 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) { Loading
libs/gui/include/gui/BLASTBufferQueue.h +11 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,8 @@ public: void onFrameDequeued(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, const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, Loading @@ -99,7 +101,6 @@ public: void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format, SurfaceComposerClient::Transaction* outTransaction = nullptr); void flushShadowQueue() {} status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineInfo(const FrameTimelineInfo& info); Loading @@ -107,6 +108,7 @@ public: void setSidebandStream(const sp<NativeHandle>& stream); uint32_t getLastTransformHint() const; void flushShadowQueue(); virtual ~BLASTBufferQueue(); Loading @@ -119,13 +121,17 @@ private: void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, 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); // 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 maxBuffersAcquired(bool includeExtraAcquire) const REQUIRES(mMutex); static PixelFormat convertBufferFormat(PixelFormat& format); void flushShadowQueueLocked() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); std::string mName; // Represents the queued buffer count from buffer queue, // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) + Loading Loading @@ -233,6 +239,9 @@ private: // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a // callback for them. std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; }; } // namespace android Loading
services/surfaceflinger/tests/utils/CallbackUtils.h→libs/gui/include/gui/test/CallbackUtils.h +4 −6 Original line number Diff line number Diff line Loading @@ -134,10 +134,8 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; Loading Loading @@ -199,7 +197,7 @@ public: std::this_thread::sleep_for(500ms); std::lock_guard lock(mMutex); EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received"; mCallbackDataQueue = {}; } Loading @@ -209,5 +207,5 @@ public: std::condition_variable mConditionVariable; std::queue<CallbackData> mCallbackDataQueue; }; } } // namespace } // 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 Diff line number Diff line Loading @@ -28,8 +28,8 @@ #include <limits> #include <gui/test/CallbackUtils.h> #include "BufferGenerator.h" #include "utils/CallbackUtils.h" #include "utils/ColorUtils.h" #include "utils/TransactionUtils.h" Loading