Loading libs/gui/BLASTBufferQueue.cpp +15 −5 Original line number Original line Diff line number Diff line Loading @@ -182,7 +182,8 @@ BLASTBufferQueue::~BLASTBufferQueue() { static_cast<uint32_t>(mPendingTransactions.size())); static_cast<uint32_t>(mPendingTransactions.size())); SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, Loading Loading @@ -230,7 +231,8 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, } } } } if (applyTransaction) { if (applyTransaction) { t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } } } Loading Loading @@ -551,7 +553,13 @@ void BLASTBufferQueue::acquireNextBufferLocked( mergePendingTransactions(t, bufferItem.mFrameNumber); mergePendingTransactions(t, bufferItem.mFrameNumber); if (applyTransaction) { if (applyTransaction) { t->setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t->setApplyToken(mApplyToken).apply(false, true); mAppliedLastTransaction = true; mLastAppliedFrameNumber = bufferItem.mFrameNumber; } else { t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber); mAppliedLastTransaction = false; } } BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 Loading Loading @@ -857,7 +865,8 @@ void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) { SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, frameNumber); mergePendingTransactions(&t, frameNumber); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, Loading Loading @@ -1050,7 +1059,8 @@ void BLASTBufferQueue::abandon() { static_cast<uint32_t>(mPendingTransactions.size())); static_cast<uint32_t>(mPendingTransactions.size())); SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } // Clear sync states // Clear sync states Loading libs/gui/ISurfaceComposer.cpp +7 −1 Original line number Original line Diff line number Diff line Loading @@ -111,7 +111,13 @@ public: SAFE_PARCEL(data.writeUint64, transactionId); SAFE_PARCEL(data.writeUint64, transactionId); return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); if (flags & ISurfaceComposer::eOneWay) { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply, IBinder::FLAG_ONEWAY); } else { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } } } void bootFinished() override { void bootFinished() override { Loading libs/gui/LayerState.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -796,6 +796,8 @@ status_t BufferData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote()); SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote()); SAFE_PARCEL(output->writeUint64, cachedBuffer.id); SAFE_PARCEL(output->writeUint64, cachedBuffer.id); SAFE_PARCEL(output->writeBool, hasBarrier); SAFE_PARCEL(output->writeUint64, barrierFrameNumber); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -832,6 +834,9 @@ status_t BufferData::readFromParcel(const Parcel* input) { cachedBuffer.token = tmpBinder; cachedBuffer.token = tmpBinder; SAFE_PARCEL(input->readUint64, &cachedBuffer.id); SAFE_PARCEL(input->readUint64, &cachedBuffer.id); SAFE_PARCEL(input->readBool, &hasBarrier); SAFE_PARCEL(input->readUint64, &barrierFrameNumber); return NO_ERROR; return NO_ERROR; } } Loading libs/gui/SurfaceComposerClient.cpp +21 −1 Original line number Original line Diff line number Diff line Loading @@ -930,7 +930,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { } } } } status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay) { if (mStatus != NO_ERROR) { if (mStatus != NO_ERROR) { return mStatus; return mStatus; } } Loading Loading @@ -984,6 +984,14 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mAnimation) { if (mAnimation) { flags |= ISurfaceComposer::eAnimation; flags |= ISurfaceComposer::eAnimation; } } if (oneWay) { if (mForceSynchronous) { ALOGE("Transaction attempted to set synchronous and one way at the same time" " this is an invalid request. Synchronous will win for safety"); } else { flags |= ISurfaceComposer::eOneWay; } } // If both mEarlyWakeupStart and mEarlyWakeupEnd are set // If both mEarlyWakeupStart and mEarlyWakeupEnd are set // it is equivalent for none // it is equivalent for none Loading Loading @@ -1399,6 +1407,18 @@ std::shared_ptr<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffe return bufferData; return bufferData; } } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBufferHasBarrier( const sp<SurfaceControl>& sc, uint64_t barrierFrameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->bufferData->hasBarrier = true; s->bufferData->barrierFrameNumber = barrierFrameNumber; return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, Loading libs/gui/include/gui/BLASTBufferQueue.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -254,6 +254,21 @@ private: // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with // additional scales in the hierarchy. // additional scales in the hierarchy. bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true; bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true; // We send all transactions on our apply token over one-way binder calls to avoid blocking // client threads. All of our transactions remain in order, since they are one-way binder calls // from a single process, to a single interface. However once we give up a Transaction for sync // we can start to have ordering issues. When we return from sync to normal frame production, // we wait on the commit callback of sync frames ensuring ordering, however we don't want to // wait on the commit callback for every normal frame (since even emitting them has a // performance cost) this means we need a method to ensure frames are in order when switching // from one-way application on our apply token, to application on some other apply token. We // make use of setBufferHasBarrier to declare this ordering. This boolean simply tracks when we // need to set this flag, notably only in the case where we are transitioning from a previous // transaction applied by us (one way, may not yet have reached server) and an upcoming // transaction that will be applied by some sync consumer. bool mAppliedLastTransaction = false; uint64_t mLastAppliedFrameNumber = 0; }; }; } // namespace android } // namespace android Loading Loading
libs/gui/BLASTBufferQueue.cpp +15 −5 Original line number Original line Diff line number Diff line Loading @@ -182,7 +182,8 @@ BLASTBufferQueue::~BLASTBufferQueue() { static_cast<uint32_t>(mPendingTransactions.size())); static_cast<uint32_t>(mPendingTransactions.size())); SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, Loading Loading @@ -230,7 +231,8 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, } } } } if (applyTransaction) { if (applyTransaction) { t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } } } Loading Loading @@ -551,7 +553,13 @@ void BLASTBufferQueue::acquireNextBufferLocked( mergePendingTransactions(t, bufferItem.mFrameNumber); mergePendingTransactions(t, bufferItem.mFrameNumber); if (applyTransaction) { if (applyTransaction) { t->setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t->setApplyToken(mApplyToken).apply(false, true); mAppliedLastTransaction = true; mLastAppliedFrameNumber = bufferItem.mFrameNumber; } else { t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber); mAppliedLastTransaction = false; } } BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 Loading Loading @@ -857,7 +865,8 @@ void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) { SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, frameNumber); mergePendingTransactions(&t, frameNumber); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, Loading Loading @@ -1050,7 +1059,8 @@ void BLASTBufferQueue::abandon() { static_cast<uint32_t>(mPendingTransactions.size())); static_cast<uint32_t>(mPendingTransactions.size())); SurfaceComposerClient::Transaction t; SurfaceComposerClient::Transaction t; mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */); t.setApplyToken(mApplyToken).apply(); // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction t.setApplyToken(mApplyToken).apply(false, true); } } // Clear sync states // Clear sync states Loading
libs/gui/ISurfaceComposer.cpp +7 −1 Original line number Original line Diff line number Diff line Loading @@ -111,7 +111,13 @@ public: SAFE_PARCEL(data.writeUint64, transactionId); SAFE_PARCEL(data.writeUint64, transactionId); return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); if (flags & ISurfaceComposer::eOneWay) { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply, IBinder::FLAG_ONEWAY); } else { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } } } void bootFinished() override { void bootFinished() override { Loading
libs/gui/LayerState.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -796,6 +796,8 @@ status_t BufferData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote()); SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote()); SAFE_PARCEL(output->writeUint64, cachedBuffer.id); SAFE_PARCEL(output->writeUint64, cachedBuffer.id); SAFE_PARCEL(output->writeBool, hasBarrier); SAFE_PARCEL(output->writeUint64, barrierFrameNumber); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -832,6 +834,9 @@ status_t BufferData::readFromParcel(const Parcel* input) { cachedBuffer.token = tmpBinder; cachedBuffer.token = tmpBinder; SAFE_PARCEL(input->readUint64, &cachedBuffer.id); SAFE_PARCEL(input->readUint64, &cachedBuffer.id); SAFE_PARCEL(input->readBool, &hasBarrier); SAFE_PARCEL(input->readUint64, &barrierFrameNumber); return NO_ERROR; return NO_ERROR; } } Loading
libs/gui/SurfaceComposerClient.cpp +21 −1 Original line number Original line Diff line number Diff line Loading @@ -930,7 +930,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { } } } } status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay) { if (mStatus != NO_ERROR) { if (mStatus != NO_ERROR) { return mStatus; return mStatus; } } Loading Loading @@ -984,6 +984,14 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mAnimation) { if (mAnimation) { flags |= ISurfaceComposer::eAnimation; flags |= ISurfaceComposer::eAnimation; } } if (oneWay) { if (mForceSynchronous) { ALOGE("Transaction attempted to set synchronous and one way at the same time" " this is an invalid request. Synchronous will win for safety"); } else { flags |= ISurfaceComposer::eOneWay; } } // If both mEarlyWakeupStart and mEarlyWakeupEnd are set // If both mEarlyWakeupStart and mEarlyWakeupEnd are set // it is equivalent for none // it is equivalent for none Loading Loading @@ -1399,6 +1407,18 @@ std::shared_ptr<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffe return bufferData; return bufferData; } } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBufferHasBarrier( const sp<SurfaceControl>& sc, uint64_t barrierFrameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->bufferData->hasBarrier = true; s->bufferData->barrierFrameNumber = barrierFrameNumber; return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber, Loading
libs/gui/include/gui/BLASTBufferQueue.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -254,6 +254,21 @@ private: // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with // additional scales in the hierarchy. // additional scales in the hierarchy. bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true; bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true; // We send all transactions on our apply token over one-way binder calls to avoid blocking // client threads. All of our transactions remain in order, since they are one-way binder calls // from a single process, to a single interface. However once we give up a Transaction for sync // we can start to have ordering issues. When we return from sync to normal frame production, // we wait on the commit callback of sync frames ensuring ordering, however we don't want to // wait on the commit callback for every normal frame (since even emitting them has a // performance cost) this means we need a method to ensure frames are in order when switching // from one-way application on our apply token, to application on some other apply token. We // make use of setBufferHasBarrier to declare this ordering. This boolean simply tracks when we // need to set this flag, notably only in the case where we are transitioning from a previous // transaction applied by us (one way, may not yet have reached server) and an upcoming // transaction that will be applied by some sync consumer. bool mAppliedLastTransaction = false; uint64_t mLastAppliedFrameNumber = 0; }; }; } // namespace android } // namespace android Loading