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

Commit 5a68a779 authored by Marissa Wall's avatar Marissa Wall
Browse files

blast: send back previous release fences

When sending a transaction callback, send a previous release fence
instead of a boolean.

Test: Transaction_test
Bug: 80477568, 120930690

Change-Id: I608fecc3cd31fd92fcfc2abb5fc084c529ee7806
parent def831d5
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -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) {
@@ -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 {
+3 −3
Original line number Diff line number Diff line
@@ -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 {
+31 −10
Original line number Diff line number Diff line
@@ -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 {
@@ -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 {
@@ -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);
        }
    }

@@ -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) {
+8 −29
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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
@@ -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) {
@@ -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()) {
@@ -200,7 +180,6 @@ void TransactionCompletedThread::threadMain() {

        if (mPresentFence) {
            mPresentFence.clear();
            mPreviousReleaseFences.clear();
        }
    }
}
+7 −8
Original line number Diff line number Diff line
@@ -40,7 +40,9 @@ public:
    sp<IBinder> surfaceControl;

    bool releasePreviousBuffer = false;
    sp<Fence> previousReleaseFence;
    nsecs_t acquireTime = -1;
    nsecs_t latchTime = -1;
};

class TransactionCompletedThread {
@@ -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);

@@ -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:
@@ -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