Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29bfcc33 authored by Vishnu Nair's avatar Vishnu Nair Committed by Android (Google) Code Review
Browse files

Merge "SF: Clean up flush transaction queues"

parents b33a8aa5 55e8f514
Loading
Loading
Loading
Loading
+16 −87
Original line number Diff line number Diff line
@@ -3621,39 +3621,21 @@ void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule sche
    }
}

bool SurfaceFlinger::stopTransactionProcessing(
        const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
                applyTokensWithUnsignaledTransactions) const {
    if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
        // if we are in LatchUnsignaledConfig::AutoSingleLayer
        // then we should have only one applyToken for processing.
        // so we can stop further transactions on this applyToken.
        return !applyTokensWithUnsignaledTransactions.empty();
    }

    return false;
}

int SurfaceFlinger::flushUnsignaledPendingTransactionQueues(
        std::vector<TransactionState>& transactions,
        std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent,
        std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions) {
    return flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                                         applyTokensWithUnsignaledTransactions,
                                         /*tryApplyUnsignaled*/ true);
}

int SurfaceFlinger::flushPendingTransactionQueues(
        std::vector<TransactionState>& transactions,
        std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent,
        std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions,
        bool tryApplyUnsignaled) {
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
    int transactionsPendingBarrier = 0;
    auto it = mPendingTransactionQueues.begin();
    while (it != mPendingTransactionQueues.end()) {
        auto& [applyToken, transactionQueue] = *it;
        while (!transactionQueue.empty()) {
            if (stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
            // if we are in LatchUnsignaledConfig::AutoSingleLayer
            // then we should have only one applyToken for processing.
            // so we can stop further transactions on this applyToken.
            if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer &&
                !applyTokensWithUnsignaledTransactions.empty()) {
                ATRACE_NAME("stopTransactionProcessing");
                break;
            }
@@ -3701,7 +3683,6 @@ int SurfaceFlinger::flushPendingTransactionQueues(

        if (transactionQueue.empty()) {
            it = mPendingTransactionQueues.erase(it);
            mTransactionQueueCV.broadcast();
        } else {
            it = std::next(it, 1);
        }
@@ -3716,68 +3697,16 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
    std::vector<TransactionState> transactions;
    // Layer handles that have transactions with buffers that are ready to be applied.
    std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>> bufferLayersReadyToPresent;
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
    {
        Mutex::Autolock _l(mStateLock);
        {
            int lastTransactionsPendingBarrier = 0;
            int transactionsPendingBarrier = 0;
            // First collect transactions from the pending transaction queues.
            // We are not allowing unsignaled buffers here as we want to
            // collect all the transactions from applyTokens that are ready first.
            transactionsPendingBarrier =
                    flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                            applyTokensWithUnsignaledTransactions, /*tryApplyUnsignaled*/ false);

            // Second, collect transactions from the transaction queue.
            // Here as well we are not allowing unsignaled buffers for the same
            // reason as above.
            while (!mLocklessTransactionQueue.isEmpty()) {
                auto maybeTransaction = mLocklessTransactionQueue.pop();
                if (!maybeTransaction.has_value()) {
                    break;
                }
                auto transaction = maybeTransaction.value();
                const bool pendingTransactions =
                        mPendingTransactionQueues.find(transaction.applyToken) !=
                        mPendingTransactionQueues.end();
                const auto ready = [&]() REQUIRES(mStateLock) {
                    if (pendingTransactions) {
                        ATRACE_NAME("pendingTransactions");
                        return TransactionReadiness::NotReady;
                    }

                    return transactionIsReadyToBeApplied(transaction, transaction.frameTimelineInfo,
                                                         transaction.isAutoTimestamp,
                                                         transaction.desiredPresentTime,
                                                         transaction.originUid, transaction.states,
                                                         bufferLayersReadyToPresent,
                                                         transactions.size(),
                                                         /*tryApplyUnsignaled*/ false);
                }();
                ATRACE_INT("TransactionReadiness", static_cast<int>(ready));
                if (ready != TransactionReadiness::Ready) {
                    if (ready == TransactionReadiness::NotReadyBarrier) {
                        transactionsPendingBarrier++;
                    }
                mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction));
                } else {
                    transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
                        const bool frameNumberChanged = state.bufferData->flags.test(
                                BufferData::BufferDataChange::frameNumberChanged);
                        if (frameNumberChanged) {
                            bufferLayersReadyToPresent[state.surface] = state.bufferData->frameNumber;
                        } else {
                            // Barrier function only used for BBQ which always includes a frame number.
                            // This value only used for barrier logic.
                            bufferLayersReadyToPresent[state.surface] =
                                std::numeric_limits<uint64_t>::max();
                        }
                    });
                    transactions.emplace_back(std::move(transaction));
                    mPendingTransactionCount--;
                    ATRACE_INT("TransactionQueue", mPendingTransactionCount.load());
                }
            }

            // Transactions with a buffer pending on a barrier may be on a different applyToken
@@ -3790,20 +3719,21 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
            // loop through flushPendingTransactionQueues until we perform an iteration
            // where the number of transactionsPendingBarrier doesn't change. This way
            // we can continue to resolve dependency chains of barriers as far as possible.
            while (lastTransactionsPendingBarrier != transactionsPendingBarrier) {
            int lastTransactionsPendingBarrier = 0;
            int transactionsPendingBarrier = 0;
            do {
                lastTransactionsPendingBarrier = transactionsPendingBarrier;
                transactionsPendingBarrier =
                        flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                        applyTokensWithUnsignaledTransactions,
                                                      /*tryApplyUnsignaled*/ false);
            }
            } while (lastTransactionsPendingBarrier != transactionsPendingBarrier);

            // We collected all transactions that could apply without latching unsignaled buffers.
            // If we are allowing latch unsignaled of some form, now it's the time to go over the
            // transactions that were not applied and try to apply them unsignaled.
            if (enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) {
                flushUnsignaledPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                                                        applyTokensWithUnsignaledTransactions);
                flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                                              /*tryApplyUnsignaled*/ true);
            }

            return applyTransactions(transactions, vsyncId);
@@ -3977,7 +3907,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied(TransactionState& transaction

        if (fenceUnsignaled && !allowLatchUnsignaled) {
            if (!transaction.sentFenceTimeoutWarning &&
                queueProcessTime - transaction.queueTime > std::chrono::nanoseconds(4s).count()) {
                queueProcessTime - transaction.postTime > std::chrono::nanoseconds(4s).count()) {
                transaction.sentFenceTimeoutWarning = true;
                auto listener = s.bufferData->releaseBufferListener;
                if (listener) {
@@ -4004,7 +3934,6 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied(TransactionState& transaction
}

void SurfaceFlinger::queueTransaction(TransactionState& state) {
    state.queueTime = systemTime();
    // Generate a CountDownLatch pending state if this is a synchronous transaction.
    if (state.flags & eSynchronous) {
        state.transactionCommittedSignal =
+0 −10
Original line number Diff line number Diff line
@@ -754,15 +754,8 @@ private:
    int flushPendingTransactionQueues(
            std::vector<TransactionState>& transactions,
            std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent,
            std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions,
            bool tryApplyUnsignaled) REQUIRES(mStateLock);

    int flushUnsignaledPendingTransactionQueues(
            std::vector<TransactionState>& transactions,
            std::unordered_map<sp<IBinder>, uint64_t, SpHash<IBinder>>& bufferLayersReadyToPresent,
            std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions)
            REQUIRES(mStateLock);

    uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&,
                                  int64_t desiredPresentTime, bool isAutoTimestamp,
                                  int64_t postTime, uint32_t permissions) REQUIRES(mStateLock);
@@ -794,8 +787,6 @@ private:
    static LatchUnsignaledConfig getLatchUnsignaledConfig();
    bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates,
                               size_t totalTXapplied) const;
    bool stopTransactionProcessing(const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
                                           applyTokensWithUnsignaledTransactions) const;
    bool applyTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId)
            REQUIRES(mStateLock);
    uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
@@ -1245,7 +1236,6 @@ private:
    uint32_t mTexturePoolSize = 0;
    std::vector<uint32_t> mTexturePool;

    Condition mTransactionQueueCV;
    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
            mPendingTransactionQueues;
    LocklessQueue<TransactionState> mLocklessTransactionQueue;
+0 −1
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ struct TransactionState {
    int originUid;
    uint64_t id;
    std::shared_ptr<CountDownLatch> transactionCommittedSignal;
    int64_t queueTime = 0;
    bool sentFenceTimeoutWarning = false;
};