Loading libs/gui/ITransactionCompletedListener.cpp +23 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,16 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { if (err != NO_ERROR) { return err; } return output->writeBool(releasePreviousBuffer); if (previousReleaseFence) { err = output->writeBool(true); if (err != NO_ERROR) { return err; } err = output->write(*previousReleaseFence); } else { err = output->writeBool(false); } return err; } status_t SurfaceStats::readFromParcel(const Parcel* input) { Loading @@ -51,7 +60,19 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { if (err != NO_ERROR) { return err; } return input->readBool(&releasePreviousBuffer); bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) { return err; } if (hasFence) { previousReleaseFence = new Fence(); err = input->read(*previousReleaseFence); if (err != NO_ERROR) { return err; } } return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { Loading libs/gui/include/gui/ITransactionCompletedListener.h +3 −3 Original line number Diff line number Diff line Loading @@ -52,12 +52,12 @@ public: status_t readFromParcel(const Parcel* input) override; SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, bool releasePrevBuffer) : surfaceControl(sc), acquireTime(time), releasePreviousBuffer(releasePrevBuffer) {} SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; bool releasePreviousBuffer = false; sp<Fence> previousReleaseFence; }; class TransactionStats : public Parcelable { Loading services/surfaceflinger/BufferStateLayer.cpp +31 −10 Original line number Diff line number Diff line Loading @@ -48,10 +48,28 @@ BufferStateLayer::~BufferStateLayer() = default; // Interface implementation for Layer // ----------------------------------------------------------------------- void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { // The transaction completed callback can only be sent if the release fence from the PREVIOUS // frame has fired. In practice, we should never actually wait on the previous release fence // but we should store it just in case. mPreviousReleaseFence = releaseFence; // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will // let the client know when that previous buffer is removed from the screen. // // Every other transaction on this layer does not need a release fence because no other // Transactions that were set on this layer this frame are going to have their preceeding buffer // removed from the display this frame. // // For example, if we have 3 transactions this frame. The first transaction doesn't contain a // buffer so it doesn't need a previous release fence because the layer still needs the previous // buffer. The second transaction contains a buffer so it needs a previous release fence because // the previous buffer will be released this frame. The third transaction also contains a // buffer. It replaces the buffer in the second transaction. The buffer in the second // transaction will now no longer be presented so it is released immediately and the third // transaction doesn't need a previous release fence. for (auto& handle : mDrawingState.callbackHandles) { if (handle->releasePreviousBuffer) { handle->previousReleaseFence = releaseFence; break; } } } void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { Loading @@ -60,7 +78,10 @@ void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { } void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { return; mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles( mDrawingState.callbackHandles); mDrawingState.callbackHandles = {}; } bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { Loading Loading @@ -257,14 +278,14 @@ bool BufferStateLayer::setTransactionCompletedListeners( // Notify the transaction completed thread that there is a pending latched callback // handle mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle); mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle); // Store so latched time and release fence can be set mCurrentState.callbackHandles.push_back(handle); } else { // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle); mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle); } } Loading Loading @@ -504,9 +525,9 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return BAD_VALUE; } mFlinger->getTransactionCompletedThread() .addLatchedCallbackHandles(getDrawingState().callbackHandles, latchTime, mPreviousReleaseFence); for (auto& handle : mDrawingState.callbackHandles) { handle->latchTime = latchTime; } // Handle sync fences if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) { Loading services/surfaceflinger/TransactionCompletedThread.cpp +8 −29 Original line number Diff line number Diff line Loading @@ -62,8 +62,7 @@ void TransactionCompletedThread::run() { mThread = std::thread(&TransactionCompletedThread::threadMain, this); } void TransactionCompletedThread::registerPendingLatchedCallbackHandle( const sp<CallbackHandle>& handle) { void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) { std::lock_guard lock(mMutex); sp<IBinder> listener = IInterface::asBinder(handle->listener); Loading @@ -72,19 +71,10 @@ void TransactionCompletedThread::registerPendingLatchedCallbackHandle( mPendingTransactions[listener][callbackIds]++; } void TransactionCompletedThread::addLatchedCallbackHandles( const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime, const sp<Fence>& previousReleaseFence) { void TransactionCompletedThread::addPresentedCallbackHandles( const std::deque<sp<CallbackHandle>>& handles) { std::lock_guard lock(mMutex); // If the previous release fences have not signaled, something as probably gone wrong. // Store the fences and check them again before sending a callback. if (previousReleaseFence && previousReleaseFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { ALOGD("release fence from the previous frame has not signaled"); mPreviousReleaseFences.push_back(previousReleaseFence); } for (const auto& handle : handles) { auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener)); auto& pendingCallbacks = listener->second; Loading @@ -101,17 +91,16 @@ void TransactionCompletedThread::addLatchedCallbackHandles( ALOGE("there are more latched callbacks than there were registered callbacks"); } addCallbackHandle(handle, latchTime); addCallbackHandle(handle); } } void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) { void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) { std::lock_guard lock(mMutex); addCallbackHandle(handle); } void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle, nsecs_t latchTime) { void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) { const sp<IBinder> listener = IInterface::asBinder(handle->listener); // If we don't already have a reference to this listener, linkToDeath so we get a notification Loading @@ -128,9 +117,9 @@ void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& han listenerStats.listener = handle->listener; auto& transactionStats = listenerStats.transactionStats[handle->callbackIds]; transactionStats.latchTime = latchTime; transactionStats.latchTime = handle->latchTime; transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime, handle->releasePreviousBuffer); handle->previousReleaseFence); } void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) { Loading @@ -151,15 +140,6 @@ void TransactionCompletedThread::threadMain() { while (mKeepRunning) { mConditionVariable.wait(mMutex); // We should never hit this case. The release fences from the previous frame should have // signaled long before the current frame is presented. for (const auto& fence : mPreviousReleaseFences) { status_t status = fence->wait(100); if (status != NO_ERROR) { ALOGE("previous release fence has not signaled, err %d", status); } } // For each listener auto it = mListenerStats.begin(); while (it != mListenerStats.end()) { Loading Loading @@ -200,7 +180,6 @@ void TransactionCompletedThread::threadMain() { if (mPresentFence) { mPresentFence.clear(); mPreviousReleaseFences.clear(); } } } Loading services/surfaceflinger/TransactionCompletedThread.h +7 −8 Original line number Diff line number Diff line Loading @@ -40,7 +40,9 @@ public: sp<IBinder> surfaceControl; bool releasePreviousBuffer = false; sp<Fence> previousReleaseFence; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; }; class TransactionCompletedThread { Loading @@ -54,14 +56,13 @@ public: // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and // presented. void registerPendingLatchedCallbackHandle(const sp<CallbackHandle>& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been latched. void addLatchedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime, const sp<Fence>& previousReleaseFence); void registerPendingCallbackHandle(const sp<CallbackHandle>& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented. void addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles); // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. void addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle); void addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle); void addPresentFence(const sp<Fence>& presentFence); Loading @@ -70,8 +71,7 @@ public: private: void threadMain(); void addCallbackHandle(const sp<CallbackHandle>& handle, nsecs_t latchTime = -1) REQUIRES(mMutex); void addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex); class ThreadDeathRecipient : public IBinder::DeathRecipient { public: Loading Loading @@ -110,7 +110,6 @@ private: bool mKeepRunning GUARDED_BY(mMutex) = true; sp<Fence> mPresentFence GUARDED_BY(mMutex); std::vector<sp<Fence>> mPreviousReleaseFences GUARDED_BY(mMutex); }; } // namespace android Loading
libs/gui/ITransactionCompletedListener.cpp +23 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,16 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { if (err != NO_ERROR) { return err; } return output->writeBool(releasePreviousBuffer); if (previousReleaseFence) { err = output->writeBool(true); if (err != NO_ERROR) { return err; } err = output->write(*previousReleaseFence); } else { err = output->writeBool(false); } return err; } status_t SurfaceStats::readFromParcel(const Parcel* input) { Loading @@ -51,7 +60,19 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { if (err != NO_ERROR) { return err; } return input->readBool(&releasePreviousBuffer); bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) { return err; } if (hasFence) { previousReleaseFence = new Fence(); err = input->read(*previousReleaseFence); if (err != NO_ERROR) { return err; } } return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { Loading
libs/gui/include/gui/ITransactionCompletedListener.h +3 −3 Original line number Diff line number Diff line Loading @@ -52,12 +52,12 @@ public: status_t readFromParcel(const Parcel* input) override; SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, bool releasePrevBuffer) : surfaceControl(sc), acquireTime(time), releasePreviousBuffer(releasePrevBuffer) {} SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence) {} sp<IBinder> surfaceControl; nsecs_t acquireTime = -1; bool releasePreviousBuffer = false; sp<Fence> previousReleaseFence; }; class TransactionStats : public Parcelable { Loading
services/surfaceflinger/BufferStateLayer.cpp +31 −10 Original line number Diff line number Diff line Loading @@ -48,10 +48,28 @@ BufferStateLayer::~BufferStateLayer() = default; // Interface implementation for Layer // ----------------------------------------------------------------------- void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { // The transaction completed callback can only be sent if the release fence from the PREVIOUS // frame has fired. In practice, we should never actually wait on the previous release fence // but we should store it just in case. mPreviousReleaseFence = releaseFence; // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will // let the client know when that previous buffer is removed from the screen. // // Every other transaction on this layer does not need a release fence because no other // Transactions that were set on this layer this frame are going to have their preceeding buffer // removed from the display this frame. // // For example, if we have 3 transactions this frame. The first transaction doesn't contain a // buffer so it doesn't need a previous release fence because the layer still needs the previous // buffer. The second transaction contains a buffer so it needs a previous release fence because // the previous buffer will be released this frame. The third transaction also contains a // buffer. It replaces the buffer in the second transaction. The buffer in the second // transaction will now no longer be presented so it is released immediately and the third // transaction doesn't need a previous release fence. for (auto& handle : mDrawingState.callbackHandles) { if (handle->releasePreviousBuffer) { handle->previousReleaseFence = releaseFence; break; } } } void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { Loading @@ -60,7 +78,10 @@ void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { } void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { return; mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles( mDrawingState.callbackHandles); mDrawingState.callbackHandles = {}; } bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { Loading Loading @@ -257,14 +278,14 @@ bool BufferStateLayer::setTransactionCompletedListeners( // Notify the transaction completed thread that there is a pending latched callback // handle mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle); mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle); // Store so latched time and release fence can be set mCurrentState.callbackHandles.push_back(handle); } else { // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle); mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle); } } Loading Loading @@ -504,9 +525,9 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return BAD_VALUE; } mFlinger->getTransactionCompletedThread() .addLatchedCallbackHandles(getDrawingState().callbackHandles, latchTime, mPreviousReleaseFence); for (auto& handle : mDrawingState.callbackHandles) { handle->latchTime = latchTime; } // Handle sync fences if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) { Loading
services/surfaceflinger/TransactionCompletedThread.cpp +8 −29 Original line number Diff line number Diff line Loading @@ -62,8 +62,7 @@ void TransactionCompletedThread::run() { mThread = std::thread(&TransactionCompletedThread::threadMain, this); } void TransactionCompletedThread::registerPendingLatchedCallbackHandle( const sp<CallbackHandle>& handle) { void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) { std::lock_guard lock(mMutex); sp<IBinder> listener = IInterface::asBinder(handle->listener); Loading @@ -72,19 +71,10 @@ void TransactionCompletedThread::registerPendingLatchedCallbackHandle( mPendingTransactions[listener][callbackIds]++; } void TransactionCompletedThread::addLatchedCallbackHandles( const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime, const sp<Fence>& previousReleaseFence) { void TransactionCompletedThread::addPresentedCallbackHandles( const std::deque<sp<CallbackHandle>>& handles) { std::lock_guard lock(mMutex); // If the previous release fences have not signaled, something as probably gone wrong. // Store the fences and check them again before sending a callback. if (previousReleaseFence && previousReleaseFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { ALOGD("release fence from the previous frame has not signaled"); mPreviousReleaseFences.push_back(previousReleaseFence); } for (const auto& handle : handles) { auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener)); auto& pendingCallbacks = listener->second; Loading @@ -101,17 +91,16 @@ void TransactionCompletedThread::addLatchedCallbackHandles( ALOGE("there are more latched callbacks than there were registered callbacks"); } addCallbackHandle(handle, latchTime); addCallbackHandle(handle); } } void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) { void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) { std::lock_guard lock(mMutex); addCallbackHandle(handle); } void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle, nsecs_t latchTime) { void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) { const sp<IBinder> listener = IInterface::asBinder(handle->listener); // If we don't already have a reference to this listener, linkToDeath so we get a notification Loading @@ -128,9 +117,9 @@ void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& han listenerStats.listener = handle->listener; auto& transactionStats = listenerStats.transactionStats[handle->callbackIds]; transactionStats.latchTime = latchTime; transactionStats.latchTime = handle->latchTime; transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime, handle->releasePreviousBuffer); handle->previousReleaseFence); } void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) { Loading @@ -151,15 +140,6 @@ void TransactionCompletedThread::threadMain() { while (mKeepRunning) { mConditionVariable.wait(mMutex); // We should never hit this case. The release fences from the previous frame should have // signaled long before the current frame is presented. for (const auto& fence : mPreviousReleaseFences) { status_t status = fence->wait(100); if (status != NO_ERROR) { ALOGE("previous release fence has not signaled, err %d", status); } } // For each listener auto it = mListenerStats.begin(); while (it != mListenerStats.end()) { Loading Loading @@ -200,7 +180,6 @@ void TransactionCompletedThread::threadMain() { if (mPresentFence) { mPresentFence.clear(); mPreviousReleaseFences.clear(); } } } Loading
services/surfaceflinger/TransactionCompletedThread.h +7 −8 Original line number Diff line number Diff line Loading @@ -40,7 +40,9 @@ public: sp<IBinder> surfaceControl; bool releasePreviousBuffer = false; sp<Fence> previousReleaseFence; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; }; class TransactionCompletedThread { Loading @@ -54,14 +56,13 @@ public: // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and // presented. void registerPendingLatchedCallbackHandle(const sp<CallbackHandle>& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been latched. void addLatchedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime, const sp<Fence>& previousReleaseFence); void registerPendingCallbackHandle(const sp<CallbackHandle>& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented. void addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles); // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. void addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle); void addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle); void addPresentFence(const sp<Fence>& presentFence); Loading @@ -70,8 +71,7 @@ public: private: void threadMain(); void addCallbackHandle(const sp<CallbackHandle>& handle, nsecs_t latchTime = -1) REQUIRES(mMutex); void addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex); class ThreadDeathRecipient : public IBinder::DeathRecipient { public: Loading Loading @@ -110,7 +110,6 @@ private: bool mKeepRunning GUARDED_BY(mMutex) = true; sp<Fence> mPresentFence GUARDED_BY(mMutex); std::vector<sp<Fence>> mPreviousReleaseFences GUARDED_BY(mMutex); }; } // namespace android