Loading libs/gui/BLASTBufferQueue.cpp +64 −32 Original line number Diff line number Diff line Loading @@ -407,18 +407,9 @@ void BLASTBufferQueue::releaseBufferCallback( // Release all buffers that are beyond the ones that we need to hold while (mPendingRelease.size() > numPendingBuffersToHold) { const auto releaseBuffer = mPendingRelease.front(); const auto releasedBuffer = mPendingRelease.front(); mPendingRelease.pop_front(); auto it = mSubmitted.find(releaseBuffer.callbackId); if (it == mSubmitted.end()) { BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s", releaseBuffer.callbackId.to_string().c_str()); return; } mNumAcquired--; BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mSubmitted.erase(it); releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence); // Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let // onFrameAvailable handle processing them since it will merge with the syncTransaction. if (!mWaitForTransactionCallback) { Loading @@ -432,6 +423,20 @@ void BLASTBufferQueue::releaseBufferCallback( mCallbackCV.notify_all(); } void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence) { auto it = mSubmitted.find(callbackId); if (it == mSubmitted.end()) { BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s", callbackId.to_string().c_str()); return; } mNumAcquired--; BQA_LOGV("released %s", callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseFence); mSubmitted.erase(it); } void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); Loading Loading @@ -589,14 +594,8 @@ void BLASTBufferQueue::acquireAndReleaseBuffer() { mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence); } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool syncTransactionSet = mSyncTransaction != nullptr; BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet)); if (syncTransactionSet) { if (mWaitForTransactionCallback) { void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) { if (mWaitForTransactionCallback && mNumFrameAvailable > 0) { // We are waiting on a previous sync's transaction callback so allow another sync // transaction to proceed. // Loading @@ -606,7 +605,7 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { // 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 Loading @@ -616,7 +615,36 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { while (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting for free buffer."); mCallbackCV.wait(_lock); mCallbackCV.wait(lock); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool syncTransactionSet = mSyncTransaction != nullptr; BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet)); if (syncTransactionSet) { bool mayNeedToWaitForBuffer = true; // If we are going to re-use the same mSyncTransaction, release the buffer that may already // be set in the Transaction. This is to allow us a free slot early to continue processing // a new buffer. if (!mAcquireSingleBuffer) { auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl); if (bufferData) { BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64, bufferData->frameNumber); releaseBuffer(bufferData->releaseCallbackId, bufferData->acquireFence); // Because we just released a buffer, we know there's no need to wait for a free // buffer. mayNeedToWaitForBuffer = false; } } if (mayNeedToWaitForBuffer) { flushAndWaitForFreeBuffer(_lock); } } Loading @@ -629,8 +657,10 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { boolToString(syncTransactionSet)); if (syncTransactionSet) { acquireNextBufferLocked(std::move(mSyncTransaction)); acquireNextBufferLocked(mSyncTransaction); if (mAcquireSingleBuffer) { mSyncTransaction = nullptr; } mWaitForTransactionCallback = true; } else if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); Loading @@ -652,9 +682,11 @@ void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { mDequeueTimestamps.erase(bufferId); }; void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t) { void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t, bool acquireSingleBuffer) { std::lock_guard _lock{mMutex}; mSyncTransaction = t; mAcquireSingleBuffer = mSyncTransaction ? acquireSingleBuffer : true; } bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { Loading libs/gui/SurfaceComposerClient.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,14 @@ ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLock return callback; } void TransactionCompletedListener::removeReleaseBufferCallback( const ReleaseCallbackId& callbackId) { { std::scoped_lock<std::mutex> lock(mMutex); popReleaseBufferCallbackLocked(callbackId); } } // --------------------------------------------------------------------------- void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId); Loading Loading @@ -1307,6 +1315,28 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<Surfac return *this; } std::optional<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); if (!s) { return std::nullopt; } if (!(s->what & layer_state_t::eBufferChanged)) { return std::nullopt; } BufferData bufferData = s->bufferData; TransactionCompletedListener::getInstance()->removeReleaseBufferCallback( bufferData.releaseCallbackId); BufferData emptyBufferData; s->what &= ~layer_state_t::eBufferChanged; s->bufferData = emptyBufferData; mContainsBuffer = false; return bufferData; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, Loading libs/gui/include/gui/BLASTBufferQueue.h +9 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ public: const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount); void setSyncTransaction(SurfaceComposerClient::Transaction* t); void setSyncTransaction(SurfaceComposerClient::Transaction* t, bool acquireSingleBuffer = true); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void applyPendingTransactions(uint64_t frameNumber); Loading Loading @@ -132,6 +132,9 @@ private: void flushShadowQueue() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); void releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence) REQUIRES(mMutex); void flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock); std::string mName; // Represents the queued buffer count from buffer queue, Loading Loading @@ -239,7 +242,11 @@ private: std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; bool mWaitForTransactionCallback GUARDED_BY(mMutex) = false; // Flag to determine if syncTransaction should only acquire a single buffer and then clear or // continue to acquire buffers until explicitly cleared bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true; }; } // namespace android Loading libs/gui/include/gui/SurfaceComposerClient.h +3 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,7 @@ public: const std::optional<uint64_t>& frameNumber = std::nullopt, const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID, ReleaseBufferCallback callback = nullptr); std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc); Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace); Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata); Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc, Loading Loading @@ -751,6 +752,8 @@ public: void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t currentMaxAcquiredBufferCount) override; void removeReleaseBufferCallback(const ReleaseCallbackId& callbackId); // For Testing Only static void setInstance(const sp<TransactionCompletedListener>&); Loading libs/gui/tests/BLASTBufferQueue_test.cpp +48 −4 Original line number Diff line number Diff line Loading @@ -109,8 +109,8 @@ public: mBlastBufferQueueAdapter->update(sc, width, height, PIXEL_FORMAT_RGBA_8888); } void setSyncTransaction(Transaction* sync) { mBlastBufferQueueAdapter->setSyncTransaction(sync); void setSyncTransaction(Transaction* next, bool acquireSingleBuffer = true) { mBlastBufferQueueAdapter->setSyncTransaction(next, acquireSingleBuffer); } int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } Loading Loading @@ -143,6 +143,11 @@ public: mBlastBufferQueueAdapter->waitForCallback(frameNumber); } void validateNumFramesSubmitted(int64_t numFramesSubmitted) { std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; ASSERT_EQ(numFramesSubmitted, mBlastBufferQueueAdapter->mSubmitted.size()); } private: sp<TestBLASTBufferQueue> mBlastBufferQueueAdapter; }; Loading Loading @@ -298,7 +303,7 @@ protected: auto ret = igbp->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight, PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); ASSERT_TRUE(ret == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION || ret == NO_ERROR); ASSERT_EQ(OK, igbp->requestBuffer(slot, &buf)); uint32_t* bufData; Loading Loading @@ -818,7 +823,7 @@ TEST_F(BLASTBufferQueueTest, SyncThenNoSync) { CallbackData callbackData; transactionCallback.getCallbackData(&callbackData); // capture screen and verify that it is red // capture screen and verify that it is green ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); Loading Loading @@ -1025,6 +1030,45 @@ TEST_F(BLASTBufferQueueTest, RunOutOfBuffersWaitingOnSF) { checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } TEST_F(BLASTBufferQueueTest, SetSyncTransactionAcquireMultipleBuffers) { BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); Transaction next; adapter.setSyncTransaction(&next, false); queueBuffer(igbProducer, 0, 255, 0, 0); queueBuffer(igbProducer, 0, 0, 255, 0); // There should only be one frame submitted since the first frame will be released. adapter.validateNumFramesSubmitted(1); adapter.setSyncTransaction(nullptr); // queue non sync buffer, so this one should get blocked // Add a present delay to allow the first screenshot to get taken. nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count(); queueBuffer(igbProducer, 255, 0, 0, presentTimeDelay); CallbackHelper transactionCallback; next.addTransactionCompletedCallback(transactionCallback.function, transactionCallback.getContext()) .apply(); CallbackData callbackData; transactionCallback.getCallbackData(&callbackData); // capture screen and verify that it is blue ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); mProducerListener->waitOnNumberReleased(2); // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } class TestProducerListener : public BnProducerListener { public: sp<IGraphicBufferProducer> mIgbp; Loading Loading
libs/gui/BLASTBufferQueue.cpp +64 −32 Original line number Diff line number Diff line Loading @@ -407,18 +407,9 @@ void BLASTBufferQueue::releaseBufferCallback( // Release all buffers that are beyond the ones that we need to hold while (mPendingRelease.size() > numPendingBuffersToHold) { const auto releaseBuffer = mPendingRelease.front(); const auto releasedBuffer = mPendingRelease.front(); mPendingRelease.pop_front(); auto it = mSubmitted.find(releaseBuffer.callbackId); if (it == mSubmitted.end()) { BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s", releaseBuffer.callbackId.to_string().c_str()); return; } mNumAcquired--; BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); mSubmitted.erase(it); releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence); // Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let // onFrameAvailable handle processing them since it will merge with the syncTransaction. if (!mWaitForTransactionCallback) { Loading @@ -432,6 +423,20 @@ void BLASTBufferQueue::releaseBufferCallback( mCallbackCV.notify_all(); } void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence) { auto it = mSubmitted.find(callbackId); if (it == mSubmitted.end()) { BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s", callbackId.to_string().c_str()); return; } mNumAcquired--; BQA_LOGV("released %s", callbackId.to_string().c_str()); mBufferItemConsumer->releaseBuffer(it->second, releaseFence); mSubmitted.erase(it); } void BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { ATRACE_CALL(); Loading Loading @@ -589,14 +594,8 @@ void BLASTBufferQueue::acquireAndReleaseBuffer() { mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence); } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool syncTransactionSet = mSyncTransaction != nullptr; BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet)); if (syncTransactionSet) { if (mWaitForTransactionCallback) { void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) { if (mWaitForTransactionCallback && mNumFrameAvailable > 0) { // We are waiting on a previous sync's transaction callback so allow another sync // transaction to proceed. // Loading @@ -606,7 +605,7 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { // 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 Loading @@ -616,7 +615,36 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { while (maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGD("waiting for free buffer."); mCallbackCV.wait(_lock); mCallbackCV.wait(lock); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; const bool syncTransactionSet = mSyncTransaction != nullptr; BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet)); if (syncTransactionSet) { bool mayNeedToWaitForBuffer = true; // If we are going to re-use the same mSyncTransaction, release the buffer that may already // be set in the Transaction. This is to allow us a free slot early to continue processing // a new buffer. if (!mAcquireSingleBuffer) { auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl); if (bufferData) { BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64, bufferData->frameNumber); releaseBuffer(bufferData->releaseCallbackId, bufferData->acquireFence); // Because we just released a buffer, we know there's no need to wait for a free // buffer. mayNeedToWaitForBuffer = false; } } if (mayNeedToWaitForBuffer) { flushAndWaitForFreeBuffer(_lock); } } Loading @@ -629,8 +657,10 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { boolToString(syncTransactionSet)); if (syncTransactionSet) { acquireNextBufferLocked(std::move(mSyncTransaction)); acquireNextBufferLocked(mSyncTransaction); if (mAcquireSingleBuffer) { mSyncTransaction = nullptr; } mWaitForTransactionCallback = true; } else if (!mWaitForTransactionCallback) { acquireNextBufferLocked(std::nullopt); Loading @@ -652,9 +682,11 @@ void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { mDequeueTimestamps.erase(bufferId); }; void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t) { void BLASTBufferQueue::setSyncTransaction(SurfaceComposerClient::Transaction* t, bool acquireSingleBuffer) { std::lock_guard _lock{mMutex}; mSyncTransaction = t; mAcquireSingleBuffer = mSyncTransaction ? acquireSingleBuffer : true; } bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { Loading
libs/gui/SurfaceComposerClient.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,14 @@ ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLock return callback; } void TransactionCompletedListener::removeReleaseBufferCallback( const ReleaseCallbackId& callbackId) { { std::scoped_lock<std::mutex> lock(mMutex); popReleaseBufferCallbackLocked(callbackId); } } // --------------------------------------------------------------------------- void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId); Loading Loading @@ -1307,6 +1315,28 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<Surfac return *this; } std::optional<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); if (!s) { return std::nullopt; } if (!(s->what & layer_state_t::eBufferChanged)) { return std::nullopt; } BufferData bufferData = s->bufferData; TransactionCompletedListener::getInstance()->removeReleaseBufferCallback( bufferData.releaseCallbackId); BufferData emptyBufferData; s->what &= ~layer_state_t::eBufferChanged; s->bufferData = emptyBufferData; mContainsBuffer = false; return bufferData; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, Loading
libs/gui/include/gui/BLASTBufferQueue.h +9 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ public: const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence, std::optional<uint32_t> currentMaxAcquiredBufferCount); void setSyncTransaction(SurfaceComposerClient::Transaction* t); void setSyncTransaction(SurfaceComposerClient::Transaction* t, bool acquireSingleBuffer = true); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void applyPendingTransactions(uint64_t frameNumber); Loading Loading @@ -132,6 +132,9 @@ private: void flushShadowQueue() REQUIRES(mMutex); void acquireAndReleaseBuffer() REQUIRES(mMutex); void releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence) REQUIRES(mMutex); void flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock); std::string mName; // Represents the queued buffer count from buffer queue, Loading Loading @@ -239,7 +242,11 @@ private: std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex); uint32_t mCurrentMaxAcquiredBufferCount; bool mWaitForTransactionCallback = false; bool mWaitForTransactionCallback GUARDED_BY(mMutex) = false; // Flag to determine if syncTransaction should only acquire a single buffer and then clear or // continue to acquire buffers until explicitly cleared bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true; }; } // namespace android Loading
libs/gui/include/gui/SurfaceComposerClient.h +3 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,7 @@ public: const std::optional<uint64_t>& frameNumber = std::nullopt, const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID, ReleaseBufferCallback callback = nullptr); std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc); Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace); Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata); Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc, Loading Loading @@ -751,6 +752,8 @@ public: void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t currentMaxAcquiredBufferCount) override; void removeReleaseBufferCallback(const ReleaseCallbackId& callbackId); // For Testing Only static void setInstance(const sp<TransactionCompletedListener>&); Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +48 −4 Original line number Diff line number Diff line Loading @@ -109,8 +109,8 @@ public: mBlastBufferQueueAdapter->update(sc, width, height, PIXEL_FORMAT_RGBA_8888); } void setSyncTransaction(Transaction* sync) { mBlastBufferQueueAdapter->setSyncTransaction(sync); void setSyncTransaction(Transaction* next, bool acquireSingleBuffer = true) { mBlastBufferQueueAdapter->setSyncTransaction(next, acquireSingleBuffer); } int getWidth() { return mBlastBufferQueueAdapter->mSize.width; } Loading Loading @@ -143,6 +143,11 @@ public: mBlastBufferQueueAdapter->waitForCallback(frameNumber); } void validateNumFramesSubmitted(int64_t numFramesSubmitted) { std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; ASSERT_EQ(numFramesSubmitted, mBlastBufferQueueAdapter->mSubmitted.size()); } private: sp<TestBLASTBufferQueue> mBlastBufferQueueAdapter; }; Loading Loading @@ -298,7 +303,7 @@ protected: auto ret = igbp->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight, PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); ASSERT_TRUE(ret == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION || ret == NO_ERROR); ASSERT_EQ(OK, igbp->requestBuffer(slot, &buf)); uint32_t* bufData; Loading Loading @@ -818,7 +823,7 @@ TEST_F(BLASTBufferQueueTest, SyncThenNoSync) { CallbackData callbackData; transactionCallback.getCallbackData(&callbackData); // capture screen and verify that it is red // capture screen and verify that it is green ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 255, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); Loading Loading @@ -1025,6 +1030,45 @@ TEST_F(BLASTBufferQueueTest, RunOutOfBuffersWaitingOnSF) { checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } TEST_F(BLASTBufferQueueTest, SetSyncTransactionAcquireMultipleBuffers) { BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); sp<IGraphicBufferProducer> igbProducer; setUpProducer(adapter, igbProducer); Transaction next; adapter.setSyncTransaction(&next, false); queueBuffer(igbProducer, 0, 255, 0, 0); queueBuffer(igbProducer, 0, 0, 255, 0); // There should only be one frame submitted since the first frame will be released. adapter.validateNumFramesSubmitted(1); adapter.setSyncTransaction(nullptr); // queue non sync buffer, so this one should get blocked // Add a present delay to allow the first screenshot to get taken. nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count(); queueBuffer(igbProducer, 255, 0, 0, presentTimeDelay); CallbackHelper transactionCallback; next.addTransactionCompletedCallback(transactionCallback.function, transactionCallback.getContext()) .apply(); CallbackData callbackData; transactionCallback.getCallbackData(&callbackData); // capture screen and verify that it is blue ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(0, 0, 255, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); mProducerListener->waitOnNumberReleased(2); // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(255, 0, 0, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } class TestProducerListener : public BnProducerListener { public: sp<IGraphicBufferProducer> mIgbp; Loading