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

Commit 3040c435 authored by Ady Abraham's avatar Ady Abraham Committed by Android (Google) Code Review
Browse files

Merge "SF: don't latch unsignaled if there are multiple apply tokens" into tm-dev

parents 2a77cb75 e1bfaacc
Loading
Loading
Loading
Loading
+72 −56
Original line number Diff line number Diff line
@@ -3647,19 +3647,11 @@ bool SurfaceFlinger::stopTransactionProcessing(
    return false;
}

bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
    // to prevent onHandleDestroyed from being called while the lock is held,
    // we must keep a copy of the transactions (specifically the composer
    // states) around outside the scope of the lock
    std::vector<TransactionState> transactions;
    // Layer handles that have transactions with buffers that are ready to be applied.
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent;
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
    {
        Mutex::Autolock _l(mStateLock);
        {
            Mutex::Autolock _l(mQueueLock);
            // Collect transactions from pending transaction queue.
void SurfaceFlinger::flushPendingTransactionQueues(
        std::vector<TransactionState>& transactions,
        std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
        std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions,
        bool tryApplyUnsignaled) {
    auto it = mPendingTransactionQueues.begin();
    while (it != mPendingTransactionQueues.end()) {
        auto& [applyToken, transactionQueue] = *it;
@@ -3675,8 +3667,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
                                                  transaction.isAutoTimestamp,
                                                  transaction.desiredPresentTime,
                                                  transaction.originUid, transaction.states,
                                                          bufferLayersReadyToPresent,
                                                          transactions.size());
                                                  bufferLayersReadyToPresent, transactions.size(),
                                                  tryApplyUnsignaled);
            ATRACE_INT("TransactionReadiness", static_cast<int>(ready));
            if (ready == TransactionReadiness::NotReady) {
                setTransactionFlags(eTransactionFlushNeeded);
@@ -3701,21 +3693,39 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
            it = std::next(it, 1);
        }
    }
}

bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
    // to prevent onHandleDestroyed from being called while the lock is held,
    // we must keep a copy of the transactions (specifically the composer
    // states) around outside the scope of the lock
    std::vector<TransactionState> transactions;
    // Layer handles that have transactions with buffers that are ready to be applied.
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent;
    std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
    {
        Mutex::Autolock _l(mStateLock);
        {
            Mutex::Autolock _l(mQueueLock);

            // 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.
            flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                                          applyTokensWithUnsignaledTransactions,
                                          /*tryApplyUnsignaled*/ false);

            // Collect transactions from current transaction queue or queue to pending transactions.
            // Case 1: push to pending when transactionIsReadyToBeApplied is false
            // or the first transaction was unsignaled.
            // Case 2: push to pending when there exist a pending queue.
            // Case 3: others are the transactions that are ready to apply.
            // Second, collect transactions from the transaction queue.
            // Here as well we are not allowing unsignaled buffers for the same
            // reason as above.
            while (!mTransactionQueue.empty()) {
                auto& transaction = mTransactionQueue.front();
                const bool pendingTransactions =
                        mPendingTransactionQueues.find(transaction.applyToken) !=
                        mPendingTransactionQueues.end();
                const auto ready = [&]() REQUIRES(mStateLock) {
                    if (pendingTransactions ||
                        stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
                        ATRACE_NAME("pendingTransactions || stopTransactionProcessing");
                    if (pendingTransactions) {
                        ATRACE_NAME("pendingTransactions");
                        return TransactionReadiness::NotReady;
                    }

@@ -3724,7 +3734,8 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
                                                         transaction.desiredPresentTime,
                                                         transaction.originUid, transaction.states,
                                                         bufferLayersReadyToPresent,
                                                         transactions.size());
                                                         transactions.size(),
                                                         /*tryApplyUnsignaled*/ false);
                }();
                ATRACE_INT("TransactionReadiness", static_cast<int>(ready));
                if (ready == TransactionReadiness::NotReady) {
@@ -3733,16 +3744,21 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
                    transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
                        bufferLayersReadyToPresent.insert(state.surface);
                    });
                    const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled);
                    if (appliedUnsignaled) {
                        applyTokensWithUnsignaledTransactions.insert(transaction.applyToken);
                    }
                    transactions.emplace_back(std::move(transaction));
                }
                mTransactionQueue.pop_front();
                ATRACE_INT("TransactionQueue", mTransactionQueue.size());
            }

            // 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) {
                flushPendingTransactionQueues(transactions, bufferLayersReadyToPresent,
                                              applyTokensWithUnsignaledTransactions,
                                              /*tryApplyUnsignaled*/ true);
            }

            return applyTransactions(transactions, vsyncId);
        }
    }
@@ -3850,7 +3866,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied(
        const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
        uid_t originUid, const Vector<ComposerState>& states,
        const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
        size_t totalTXapplied) const -> TransactionReadiness {
        size_t totalTXapplied, bool tryApplyUnsignaled) const -> TransactionReadiness {
    ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId);
    const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
    // Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3887,7 +3903,7 @@ auto SurfaceFlinger::transactionIsReadyToBeApplied(
            continue;
        }

        const bool allowLatchUnsignaled =
        const bool allowLatchUnsignaled = tryApplyUnsignaled &&
                shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied);
        ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(),
                      allowLatchUnsignaled ? "true" : "false");
+7 −1
Original line number Diff line number Diff line
@@ -750,6 +750,12 @@ private:
    // Returns true if there is at least one transaction that needs to be flushed
    bool transactionFlushNeeded();

    void flushPendingTransactionQueues(
            std::vector<TransactionState>& transactions,
            std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
            std::unordered_set<sp<IBinder>, SpHash<IBinder>>& applyTokensWithUnsignaledTransactions,
            bool tryApplyUnsignaled) REQUIRES(mStateLock, mQueueLock);

    uint32_t setClientStateLocked(const FrameTimelineInfo&, ComposerState&,
                                  int64_t desiredPresentTime, bool isAutoTimestamp,
                                  int64_t postTime, uint32_t permissions) REQUIRES(mStateLock);
@@ -780,7 +786,7 @@ private:
            const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
            uid_t originUid, const Vector<ComposerState>& states,
            const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
            size_t totalTXapplied) const REQUIRES(mStateLock);
            size_t totalTXapplied, bool tryApplyUnsignaled) const REQUIRES(mStateLock);
    static LatchUnsignaledConfig getLatchUnsignaledConfig();
    bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&, size_t numStates,
                               size_t totalTXapplied) const;
+52 −5
Original line number Diff line number Diff line
@@ -551,13 +551,52 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
                         kExpectedTransactionsPending);
}

TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledIntact) {
TEST_F(LatchUnsignaledAutoSingleLayerTest,
       UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) {
    const sp<IBinder> kApplyToken1 =
            IInterface::asBinder(TransactionCompletedListener::getIInstance());
    const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
    const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
    const auto kLayerId1 = 1;
    const auto kLayerId2 = 2;
    const auto kExpectedTransactionsApplied = 1u;
    const auto kExpectedTransactionsApplied = 2u;
    const auto kExpectedTransactionsPending = 1u;

    const auto unsignaledTransaction =
            createTransactionInfo(kApplyToken1,
                                  {
                                          createComposerState(kLayerId1,
                                                              fence(Fence::Status::Unsignaled),
                                                              layer_state_t::eBufferChanged),
                                  });

    const auto signaledTransaction =
            createTransactionInfo(kApplyToken2,
                                  {
                                          createComposerState(kLayerId2,
                                                              fence(Fence::Status::Signaled),
                                                              layer_state_t::eBufferChanged),
                                  });
    const auto signaledTransaction2 =
            createTransactionInfo(kApplyToken3,
                                  {
                                          createComposerState(kLayerId2,
                                                              fence(Fence::Status::Signaled),
                                                              layer_state_t::eBufferChanged),
                                  });

    setTransactionStates({unsignaledTransaction, signaledTransaction, signaledTransaction2},
                         kExpectedTransactionsApplied, kExpectedTransactionsPending);
}

TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) {
    const sp<IBinder> kApplyToken1 =
            IInterface::asBinder(TransactionCompletedListener::getIInstance());
    const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
    const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
    const auto kLayerId1 = 1;
    const auto kLayerId2 = 2;
    const auto kExpectedTransactionsApplied = 2u;
    const auto kExpectedTransactionsPending = 1u;

    const auto signaledTransaction =
@@ -567,15 +606,23 @@ TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledInt
                                                              fence(Fence::Status::Signaled),
                                                              layer_state_t::eBufferChanged),
                                  });
    const auto unsignaledTransaction =
    const auto signaledTransaction2 =
            createTransactionInfo(kApplyToken2,
                                  {
                                          createComposerState(kLayerId1,
                                                              fence(Fence::Status::Signaled),
                                                              layer_state_t::eBufferChanged),
                                  });
    const auto unsignaledTransaction =
            createTransactionInfo(kApplyToken3,
                                  {
                                          createComposerState(kLayerId2,
                                                              fence(Fence::Status::Unsignaled),
                                                              layer_state_t::eBufferChanged),
                                  });
    setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
                         kExpectedTransactionsPending);

    setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction},
                         kExpectedTransactionsApplied, kExpectedTransactionsPending);
}

TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {