Loading libs/gui/BLASTBufferQueue.cpp +32 −27 Original line number Diff line number Diff line Loading @@ -801,34 +801,24 @@ void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { mDequeueTimestamps.erase(bufferId); }; void BLASTBufferQueue::syncNextTransaction( bool BLASTBufferQueue::syncNextTransaction( std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer) { std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr; SurfaceComposerClient::Transaction* prevTransaction = nullptr; LOG_ALWAYS_FATAL_IF(!callback, "BLASTBufferQueue: callback passed in to syncNextTransaction must not be " "NULL"); { std::lock_guard _lock{mMutex}; BBQ_TRACE(); // We're about to overwrite the previous call so we should invoke that callback // immediately. if (mTransactionReadyCallback) { prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; ALOGW("Attempting to overwrite transaction callback in syncNextTransaction"); return false; } mTransactionReadyCallback = callback; if (callback) { mSyncTransaction = new SurfaceComposerClient::Transaction(); } else { mSyncTransaction = nullptr; } mAcquireSingleBuffer = mTransactionReadyCallback ? acquireSingleBuffer : true; } if (prevCallback) { prevCallback(prevTransaction); } mAcquireSingleBuffer = acquireSingleBuffer; return true; } void BLASTBufferQueue::stopContinuousSyncTransaction() { Loading @@ -836,20 +826,35 @@ void BLASTBufferQueue::stopContinuousSyncTransaction() { SurfaceComposerClient::Transaction* prevTransaction = nullptr; { std::lock_guard _lock{mMutex}; bool invokeCallback = mTransactionReadyCallback && !mAcquireSingleBuffer; if (invokeCallback) { if (mAcquireSingleBuffer || !mTransactionReadyCallback) { ALOGW("Attempting to stop continuous sync when none are active"); return; } prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; } mTransactionReadyCallback = nullptr; mSyncTransaction = nullptr; mAcquireSingleBuffer = true; } if (prevCallback) { prevCallback(prevTransaction); } } void BLASTBufferQueue::clearSyncTransaction() { std::lock_guard _lock{mMutex}; if (!mAcquireSingleBuffer) { ALOGW("Attempting to clear sync transaction when none are active"); return; } mTransactionReadyCallback = nullptr; mSyncTransaction = nullptr; } bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // Only reject buffers if scaling mode is freeze. Loading libs/gui/include/gui/BLASTBufferQueue.h +2 −1 Original line number Diff line number Diff line Loading @@ -97,9 +97,10 @@ public: void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) REQUIRES(mMutex); void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer = true); void stopContinuousSyncTransaction(); void clearSyncTransaction(); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void applyPendingTransactions(uint64_t frameNumber); Loading libs/gui/tests/BLASTBufferQueue_test.cpp +40 −3 Original line number Diff line number Diff line Loading @@ -117,15 +117,17 @@ public: mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } void syncNextTransaction(std::function<void(Transaction*)> callback, bool syncNextTransaction(std::function<void(Transaction*)> callback, bool acquireSingleBuffer = true) { mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); return mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } void stopContinuousSyncTransaction() { mBlastBufferQueueAdapter->stopContinuousSyncTransaction(); } void clearSyncTransaction() { mBlastBufferQueueAdapter->clearSyncTransaction(); } int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } int getHeight() { return mBlastBufferQueueAdapter->mSize.height; } Loading Loading @@ -1111,7 +1113,11 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); auto callback2 = [](Transaction*) {}; adapter.syncNextTransaction(callback2); ASSERT_FALSE(adapter.syncNextTransaction(callback2)); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); queueBuffer(igbProducer, 0, 255, 0, 0); std::unique_lock<std::mutex> lock(mutex); if (!receivedCallback) { Loading @@ -1123,6 +1129,37 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_TRUE(receivedCallback); } TEST_F(BLASTBufferQueueTest, ClearSyncTransaction) { std::mutex mutex; std::condition_variable callbackReceivedCv; bool receivedCallback = false; BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); ASSERT_EQ(nullptr, adapter.getTransactionReadyCallback()); auto callback = [&](Transaction*) { std::unique_lock<std::mutex> lock(mutex); receivedCallback = true; callbackReceivedCv.notify_one(); }; adapter.syncNextTransaction(callback); ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); adapter.clearSyncTransaction(); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); queueBuffer(igbProducer, 0, 255, 0, 0); std::unique_lock<std::mutex> lock(mutex); if (!receivedCallback) { ASSERT_EQ(callbackReceivedCv.wait_for(lock, std::chrono::seconds(3)), std::cv_status::timeout) << "did not receive callback"; } ASSERT_FALSE(receivedCallback); } TEST_F(BLASTBufferQueueTest, SyncNextTransactionDropBuffer) { uint8_t r = 255; uint8_t g = 0; Loading Loading
libs/gui/BLASTBufferQueue.cpp +32 −27 Original line number Diff line number Diff line Loading @@ -801,34 +801,24 @@ void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { mDequeueTimestamps.erase(bufferId); }; void BLASTBufferQueue::syncNextTransaction( bool BLASTBufferQueue::syncNextTransaction( std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer) { std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr; SurfaceComposerClient::Transaction* prevTransaction = nullptr; LOG_ALWAYS_FATAL_IF(!callback, "BLASTBufferQueue: callback passed in to syncNextTransaction must not be " "NULL"); { std::lock_guard _lock{mMutex}; BBQ_TRACE(); // We're about to overwrite the previous call so we should invoke that callback // immediately. if (mTransactionReadyCallback) { prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; ALOGW("Attempting to overwrite transaction callback in syncNextTransaction"); return false; } mTransactionReadyCallback = callback; if (callback) { mSyncTransaction = new SurfaceComposerClient::Transaction(); } else { mSyncTransaction = nullptr; } mAcquireSingleBuffer = mTransactionReadyCallback ? acquireSingleBuffer : true; } if (prevCallback) { prevCallback(prevTransaction); } mAcquireSingleBuffer = acquireSingleBuffer; return true; } void BLASTBufferQueue::stopContinuousSyncTransaction() { Loading @@ -836,20 +826,35 @@ void BLASTBufferQueue::stopContinuousSyncTransaction() { SurfaceComposerClient::Transaction* prevTransaction = nullptr; { std::lock_guard _lock{mMutex}; bool invokeCallback = mTransactionReadyCallback && !mAcquireSingleBuffer; if (invokeCallback) { if (mAcquireSingleBuffer || !mTransactionReadyCallback) { ALOGW("Attempting to stop continuous sync when none are active"); return; } prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; } mTransactionReadyCallback = nullptr; mSyncTransaction = nullptr; mAcquireSingleBuffer = true; } if (prevCallback) { prevCallback(prevTransaction); } } void BLASTBufferQueue::clearSyncTransaction() { std::lock_guard _lock{mMutex}; if (!mAcquireSingleBuffer) { ALOGW("Attempting to clear sync transaction when none are active"); return; } mTransactionReadyCallback = nullptr; mSyncTransaction = nullptr; } bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // Only reject buffers if scaling mode is freeze. Loading
libs/gui/include/gui/BLASTBufferQueue.h +2 −1 Original line number Diff line number Diff line Loading @@ -97,9 +97,10 @@ public: void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) REQUIRES(mMutex); void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback, bool acquireSingleBuffer = true); void stopContinuousSyncTransaction(); void clearSyncTransaction(); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void applyPendingTransactions(uint64_t frameNumber); Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +40 −3 Original line number Diff line number Diff line Loading @@ -117,15 +117,17 @@ public: mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } void syncNextTransaction(std::function<void(Transaction*)> callback, bool syncNextTransaction(std::function<void(Transaction*)> callback, bool acquireSingleBuffer = true) { mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); return mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer); } void stopContinuousSyncTransaction() { mBlastBufferQueueAdapter->stopContinuousSyncTransaction(); } void clearSyncTransaction() { mBlastBufferQueueAdapter->clearSyncTransaction(); } int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } int getHeight() { return mBlastBufferQueueAdapter->mSize.height; } Loading Loading @@ -1111,7 +1113,11 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); auto callback2 = [](Transaction*) {}; adapter.syncNextTransaction(callback2); ASSERT_FALSE(adapter.syncNextTransaction(callback2)); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); queueBuffer(igbProducer, 0, 255, 0, 0); std::unique_lock<std::mutex> lock(mutex); if (!receivedCallback) { Loading @@ -1123,6 +1129,37 @@ TEST_F(BLASTBufferQueueTest, SyncNextTransactionOverwrite) { ASSERT_TRUE(receivedCallback); } TEST_F(BLASTBufferQueueTest, ClearSyncTransaction) { std::mutex mutex; std::condition_variable callbackReceivedCv; bool receivedCallback = false; BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); ASSERT_EQ(nullptr, adapter.getTransactionReadyCallback()); auto callback = [&](Transaction*) { std::unique_lock<std::mutex> lock(mutex); receivedCallback = true; callbackReceivedCv.notify_one(); }; adapter.syncNextTransaction(callback); ASSERT_NE(nullptr, adapter.getTransactionReadyCallback()); adapter.clearSyncTransaction(); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); queueBuffer(igbProducer, 0, 255, 0, 0); std::unique_lock<std::mutex> lock(mutex); if (!receivedCallback) { ASSERT_EQ(callbackReceivedCv.wait_for(lock, std::chrono::seconds(3)), std::cv_status::timeout) << "did not receive callback"; } ASSERT_FALSE(receivedCallback); } TEST_F(BLASTBufferQueueTest, SyncNextTransactionDropBuffer) { uint8_t r = 255; uint8_t g = 0; Loading