Loading libs/gui/BLASTBufferQueue.cpp +79 −65 Original line number Diff line number Diff line Loading @@ -485,20 +485,26 @@ void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId, mSyncedFrameNumbers.erase(callbackId.framenumber); } void BLASTBufferQueue::acquireNextBufferLocked( status_t BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { // 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 = !transaction; const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; // Check if we have frames available and we have not acquired the maximum number of buffers. // Even with this check, the consumer can fail to acquire an additional buffer if the consumer // has already acquired (mMaxAcquiredBuffers + 1) and the new buffer is not droppable. In this // case mBufferItemConsumer->acquireBuffer will return with NO_BUFFER_AVAILABLE. if (mNumFrameAvailable == 0) { BQA_LOGV("Can't acquire next buffer. No available frames"); return BufferQueue::NO_BUFFER_AVAILABLE; } if (mNumAcquired >= (mMaxAcquiredBuffers + 2)) { BQA_LOGV("Can't acquire next buffer. Already acquired max frames %d max:%d + 2", mNumAcquired, mMaxAcquiredBuffers); return BufferQueue::NO_BUFFER_AVAILABLE; } if (mSurfaceControl == nullptr) { BQA_LOGE("ERROR : surface control is null"); return; return NAME_NOT_FOUND; } SurfaceComposerClient::Transaction localTransaction; Loading @@ -515,10 +521,10 @@ void BLASTBufferQueue::acquireNextBufferLocked( mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false); if (status == BufferQueue::NO_BUFFER_AVAILABLE) { BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE"); return; return status; } else if (status != OK) { BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str()); return; return status; } auto buffer = bufferItem.mGraphicBuffer; Loading @@ -528,7 +534,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( if (buffer == nullptr) { mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); BQA_LOGE("Buffer was empty"); return; return BAD_VALUE; } if (rejectBuffer(bufferItem)) { Loading @@ -537,8 +543,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); acquireNextBufferLocked(transaction); return; return acquireNextBufferLocked(transaction); } mNumAcquired++; Loading Loading @@ -592,9 +597,23 @@ void BLASTBufferQueue::acquireNextBufferLocked( t->setDesiredPresentTime(bufferItem.mTimestamp); } if (!mNextFrameTimelineInfoQueue.empty()) { t->setFrameTimelineInfo(mNextFrameTimelineInfoQueue.front()); mNextFrameTimelineInfoQueue.pop(); // Drop stale frame timeline infos while (!mPendingFrameTimelines.empty() && mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) { ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64, mPendingFrameTimelines.front().first, mPendingFrameTimelines.front().second.vsyncId); mPendingFrameTimelines.pop(); } if (!mPendingFrameTimelines.empty() && mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) { ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64 " vsyncId: %" PRId64, bufferItem.mFrameNumber, mPendingFrameTimelines.front().second.vsyncId); t->setFrameTimelineInfo(mPendingFrameTimelines.front().second); mPendingFrameTimelines.pop(); } { Loading Loading @@ -626,6 +645,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "", static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(), bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform); return OK; } Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { Loading @@ -648,44 +668,19 @@ void BLASTBufferQueue::acquireAndReleaseBuffer() { mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence); } void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) { if (!mSyncedFrameNumbers.empty() && mNumFrameAvailable > 0) { // 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 mSyncTransaction 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); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr; SurfaceComposerClient::Transaction* prevTransaction = nullptr; bool waitForTransactionCallback = !mSyncedFrameNumbers.empty(); { BBQ_TRACE(); std::unique_lock _lock{mMutex}; BBQ_TRACE(); bool waitForTransactionCallback = !mSyncedFrameNumbers.empty(); const bool syncTransactionSet = mTransactionReadyCallback != 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. Loading @@ -696,14 +691,29 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { bufferData->frameNumber); releaseBuffer(bufferData->generateReleaseCallbackId(), 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); if (waitForTransactionCallback) { // 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 mSyncTransaction so any buffer merging will get // a release callback invoked. while (mNumFrameAvailable > 0) { // flush out the shadow queue acquireAndReleaseBuffer(); } } else { // Make sure the frame available count is 0 before proceeding with a sync to ensure // the correct frame is used for the sync. The only way mNumFrameAvailable would be // greater than 0 is if we already ran out of buffers previously. This means we // need to flush the buffers before proceeding with the sync. while (mNumFrameAvailable > 0) { BQA_LOGD("waiting until no queued buffers"); mCallbackCV.wait(_lock); } } } Loading @@ -719,14 +729,23 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { item.mFrameNumber, boolToString(syncTransactionSet)); if (syncTransactionSet) { acquireNextBufferLocked(mSyncTransaction); // Add to mSyncedFrameNumbers before waiting in case any buffers are released // while waiting for a free buffer. The release and commit callback will try to // acquire buffers if there are any available, but we don't want it to acquire // in the case where a sync transaction wants the buffer. mSyncedFrameNumbers.emplace(item.mFrameNumber); // If there's no available buffer and we're in a sync transaction, we need to wait // instead of returning since we guarantee a buffer will be acquired for the sync. while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) { BQA_LOGD("waiting for available buffer"); mCallbackCV.wait(_lock); } // Only need a commit callback when syncing to ensure the buffer that's synced has been // sent to SF incStrong((void*)transactionCommittedCallbackThunk); mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSyncedFrameNumbers.emplace(item.mFrameNumber); if (mAcquireSingleBuffer) { prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; Loading Loading @@ -829,15 +848,6 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } // Check if we have acquired the maximum number of buffers. // Consumer can acquire an additional buffer if that buffer is not droppable. Set // includeExtraAcquire is true to include this buffer to the count. Since this depends on the state // of the buffer, the next acquire may return with NO_BUFFER_AVAILABLE. bool BLASTBufferQueue::maxBuffersAcquired(bool includeExtraAcquire) const { int maxAcquiredBuffers = mMaxAcquiredBuffers + (includeExtraAcquire ? 2 : 1); return mNumAcquired >= maxAcquiredBuffers; } class BBQSurface : public Surface { private: std::mutex mMutex; Loading Loading @@ -874,12 +884,13 @@ public: return mBbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy); } status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override { status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& frameTimelineInfo) override { std::unique_lock _lock{mMutex}; if (mDestroyed) { return DEAD_OBJECT; } return mBbq->setFrameTimelineInfo(frameTimelineInfo); return mBbq->setFrameTimelineInfo(frameNumber, frameTimelineInfo); } void destroy() override { Loading @@ -901,9 +912,12 @@ status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility, return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply(); } status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { status_t BLASTBufferQueue::setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& frameTimelineInfo) { ATRACE_FORMAT("%s(%s) frameNumber: %" PRIu64 " vsyncId: %" PRId64, __func__, mName.c_str(), frameNumber, frameTimelineInfo.vsyncId); std::unique_lock _lock{mMutex}; mNextFrameTimelineInfoQueue.push(frameTimelineInfo); mPendingFrameTimelines.push({frameNumber, frameTimelineInfo}); return OK; } Loading libs/gui/Surface.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -1869,12 +1869,13 @@ int Surface::dispatchGetLastQueuedBuffer2(va_list args) { int Surface::dispatchSetFrameTimelineInfo(va_list args) { ATRACE_CALL(); auto frameNumber = static_cast<uint64_t>(va_arg(args, uint64_t)); auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t)); auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t)); auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t)); ALOGV("Surface::%s", __func__); return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId, startTimeNanos}); return setFrameTimelineInfo(frameNumber, {frameTimelineVsyncId, inputEventId, startTimeNanos}); } bool Surface::transformToDisplayInverse() const { Loading Loading @@ -2648,7 +2649,8 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility, changeFrameRateStrategy); } status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { status_t Surface::setFrameTimelineInfo(uint64_t /*frameNumber*/, const FrameTimelineInfo& frameTimelineInfo) { return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo); } Loading libs/gui/SurfaceComposerClient.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -1274,8 +1274,11 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha mStatus = BAD_INDEX; return *this; } if (alpha < 0.0f || alpha > 1.0f) { ALOGE("SurfaceComposerClient::Transaction::setAlpha: invalid alpha %f, clamping", alpha); } s->what |= layer_state_t::eAlphaChanged; s->alpha = alpha; s->alpha = std::clamp(alpha, 0.f, 1.f); registerSurfaceControlForCallback(sc); return *this; Loading libs/gui/include/gui/BLASTBufferQueue.h +3 −5 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ public: void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format); status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineInfo(const FrameTimelineInfo& info); status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); void setSidebandStream(const sp<NativeHandle>& stream); Loading Loading @@ -141,12 +141,11 @@ private: void resizeFrameEventHistory(size_t newSize); void acquireNextBufferLocked( status_t 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 mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) REQUIRES(mMutex); Loading @@ -155,7 +154,6 @@ private: 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 @@ -244,7 +242,7 @@ private: std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> mPendingTransactions GUARDED_BY(mMutex); std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex); // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; Loading libs/gui/include/gui/Surface.h +1 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,7 @@ public: virtual status_t setFrameRate(float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy); virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info); virtual status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); protected: virtual ~Surface(); Loading Loading
libs/gui/BLASTBufferQueue.cpp +79 −65 Original line number Diff line number Diff line Loading @@ -485,20 +485,26 @@ void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId, mSyncedFrameNumbers.erase(callbackId.framenumber); } void BLASTBufferQueue::acquireNextBufferLocked( status_t BLASTBufferQueue::acquireNextBufferLocked( const std::optional<SurfaceComposerClient::Transaction*> transaction) { // 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 = !transaction; const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire); if (mNumFrameAvailable == 0 || maxAcquired) { BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired)); return; // Check if we have frames available and we have not acquired the maximum number of buffers. // Even with this check, the consumer can fail to acquire an additional buffer if the consumer // has already acquired (mMaxAcquiredBuffers + 1) and the new buffer is not droppable. In this // case mBufferItemConsumer->acquireBuffer will return with NO_BUFFER_AVAILABLE. if (mNumFrameAvailable == 0) { BQA_LOGV("Can't acquire next buffer. No available frames"); return BufferQueue::NO_BUFFER_AVAILABLE; } if (mNumAcquired >= (mMaxAcquiredBuffers + 2)) { BQA_LOGV("Can't acquire next buffer. Already acquired max frames %d max:%d + 2", mNumAcquired, mMaxAcquiredBuffers); return BufferQueue::NO_BUFFER_AVAILABLE; } if (mSurfaceControl == nullptr) { BQA_LOGE("ERROR : surface control is null"); return; return NAME_NOT_FOUND; } SurfaceComposerClient::Transaction localTransaction; Loading @@ -515,10 +521,10 @@ void BLASTBufferQueue::acquireNextBufferLocked( mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false); if (status == BufferQueue::NO_BUFFER_AVAILABLE) { BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE"); return; return status; } else if (status != OK) { BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str()); return; return status; } auto buffer = bufferItem.mGraphicBuffer; Loading @@ -528,7 +534,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( if (buffer == nullptr) { mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); BQA_LOGE("Buffer was empty"); return; return BAD_VALUE; } if (rejectBuffer(bufferItem)) { Loading @@ -537,8 +543,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform); mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE); acquireNextBufferLocked(transaction); return; return acquireNextBufferLocked(transaction); } mNumAcquired++; Loading Loading @@ -592,9 +597,23 @@ void BLASTBufferQueue::acquireNextBufferLocked( t->setDesiredPresentTime(bufferItem.mTimestamp); } if (!mNextFrameTimelineInfoQueue.empty()) { t->setFrameTimelineInfo(mNextFrameTimelineInfoQueue.front()); mNextFrameTimelineInfoQueue.pop(); // Drop stale frame timeline infos while (!mPendingFrameTimelines.empty() && mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) { ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64, mPendingFrameTimelines.front().first, mPendingFrameTimelines.front().second.vsyncId); mPendingFrameTimelines.pop(); } if (!mPendingFrameTimelines.empty() && mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) { ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64 " vsyncId: %" PRId64, bufferItem.mFrameNumber, mPendingFrameTimelines.front().second.vsyncId); t->setFrameTimelineInfo(mPendingFrameTimelines.front().second); mPendingFrameTimelines.pop(); } { Loading Loading @@ -626,6 +645,7 @@ void BLASTBufferQueue::acquireNextBufferLocked( bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "", static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(), bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform); return OK; } Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { Loading @@ -648,44 +668,19 @@ void BLASTBufferQueue::acquireAndReleaseBuffer() { mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence); } void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) { if (!mSyncedFrameNumbers.empty() && mNumFrameAvailable > 0) { // 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 mSyncTransaction 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); } } void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr; SurfaceComposerClient::Transaction* prevTransaction = nullptr; bool waitForTransactionCallback = !mSyncedFrameNumbers.empty(); { BBQ_TRACE(); std::unique_lock _lock{mMutex}; BBQ_TRACE(); bool waitForTransactionCallback = !mSyncedFrameNumbers.empty(); const bool syncTransactionSet = mTransactionReadyCallback != 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. Loading @@ -696,14 +691,29 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { bufferData->frameNumber); releaseBuffer(bufferData->generateReleaseCallbackId(), 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); if (waitForTransactionCallback) { // 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 mSyncTransaction so any buffer merging will get // a release callback invoked. while (mNumFrameAvailable > 0) { // flush out the shadow queue acquireAndReleaseBuffer(); } } else { // Make sure the frame available count is 0 before proceeding with a sync to ensure // the correct frame is used for the sync. The only way mNumFrameAvailable would be // greater than 0 is if we already ran out of buffers previously. This means we // need to flush the buffers before proceeding with the sync. while (mNumFrameAvailable > 0) { BQA_LOGD("waiting until no queued buffers"); mCallbackCV.wait(_lock); } } } Loading @@ -719,14 +729,23 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { item.mFrameNumber, boolToString(syncTransactionSet)); if (syncTransactionSet) { acquireNextBufferLocked(mSyncTransaction); // Add to mSyncedFrameNumbers before waiting in case any buffers are released // while waiting for a free buffer. The release and commit callback will try to // acquire buffers if there are any available, but we don't want it to acquire // in the case where a sync transaction wants the buffer. mSyncedFrameNumbers.emplace(item.mFrameNumber); // If there's no available buffer and we're in a sync transaction, we need to wait // instead of returning since we guarantee a buffer will be acquired for the sync. while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) { BQA_LOGD("waiting for available buffer"); mCallbackCV.wait(_lock); } // Only need a commit callback when syncing to ensure the buffer that's synced has been // sent to SF incStrong((void*)transactionCommittedCallbackThunk); mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this)); mSyncedFrameNumbers.emplace(item.mFrameNumber); if (mAcquireSingleBuffer) { prevCallback = mTransactionReadyCallback; prevTransaction = mSyncTransaction; Loading Loading @@ -829,15 +848,6 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } // Check if we have acquired the maximum number of buffers. // Consumer can acquire an additional buffer if that buffer is not droppable. Set // includeExtraAcquire is true to include this buffer to the count. Since this depends on the state // of the buffer, the next acquire may return with NO_BUFFER_AVAILABLE. bool BLASTBufferQueue::maxBuffersAcquired(bool includeExtraAcquire) const { int maxAcquiredBuffers = mMaxAcquiredBuffers + (includeExtraAcquire ? 2 : 1); return mNumAcquired >= maxAcquiredBuffers; } class BBQSurface : public Surface { private: std::mutex mMutex; Loading Loading @@ -874,12 +884,13 @@ public: return mBbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy); } status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override { status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& frameTimelineInfo) override { std::unique_lock _lock{mMutex}; if (mDestroyed) { return DEAD_OBJECT; } return mBbq->setFrameTimelineInfo(frameTimelineInfo); return mBbq->setFrameTimelineInfo(frameNumber, frameTimelineInfo); } void destroy() override { Loading @@ -901,9 +912,12 @@ status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility, return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply(); } status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { status_t BLASTBufferQueue::setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& frameTimelineInfo) { ATRACE_FORMAT("%s(%s) frameNumber: %" PRIu64 " vsyncId: %" PRId64, __func__, mName.c_str(), frameNumber, frameTimelineInfo.vsyncId); std::unique_lock _lock{mMutex}; mNextFrameTimelineInfoQueue.push(frameTimelineInfo); mPendingFrameTimelines.push({frameNumber, frameTimelineInfo}); return OK; } Loading
libs/gui/Surface.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -1869,12 +1869,13 @@ int Surface::dispatchGetLastQueuedBuffer2(va_list args) { int Surface::dispatchSetFrameTimelineInfo(va_list args) { ATRACE_CALL(); auto frameNumber = static_cast<uint64_t>(va_arg(args, uint64_t)); auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t)); auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t)); auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t)); ALOGV("Surface::%s", __func__); return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId, startTimeNanos}); return setFrameTimelineInfo(frameNumber, {frameTimelineVsyncId, inputEventId, startTimeNanos}); } bool Surface::transformToDisplayInverse() const { Loading Loading @@ -2648,7 +2649,8 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility, changeFrameRateStrategy); } status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { status_t Surface::setFrameTimelineInfo(uint64_t /*frameNumber*/, const FrameTimelineInfo& frameTimelineInfo) { return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo); } Loading
libs/gui/SurfaceComposerClient.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -1274,8 +1274,11 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha mStatus = BAD_INDEX; return *this; } if (alpha < 0.0f || alpha > 1.0f) { ALOGE("SurfaceComposerClient::Transaction::setAlpha: invalid alpha %f, clamping", alpha); } s->what |= layer_state_t::eAlphaChanged; s->alpha = alpha; s->alpha = std::clamp(alpha, 0.f, 1.f); registerSurfaceControlForCallback(sc); return *this; Loading
libs/gui/include/gui/BLASTBufferQueue.h +3 −5 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ public: void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format); status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineInfo(const FrameTimelineInfo& info); status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); void setSidebandStream(const sp<NativeHandle>& stream); Loading Loading @@ -141,12 +141,11 @@ private: void resizeFrameEventHistory(size_t newSize); void acquireNextBufferLocked( status_t 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 mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) REQUIRES(mMutex); Loading @@ -155,7 +154,6 @@ private: 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 @@ -244,7 +242,7 @@ private: std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> mPendingTransactions GUARDED_BY(mMutex); std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex); // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; Loading
libs/gui/include/gui/Surface.h +1 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,7 @@ public: virtual status_t setFrameRate(float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy); virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info); virtual status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info); protected: virtual ~Surface(); Loading