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

Commit fe34457d authored by Rob Carr's avatar Rob Carr Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE: Move blast sync handling to BBQ" into sc-v2-dev

parents ebff6bd2 2d2150ed
Loading
Loading
Loading
Loading
+135 −25
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ inline const char* boolToString(bool b) {
namespace android {

// Macros to include adapter info in log messages
#define BQA_LOGD(x, ...) \
    ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
#define BQA_LOGV(x, ...) \
    ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
// enable logs for a single layer
@@ -243,6 +245,67 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    }
}

static std::optional<SurfaceControlStats> findMatchingStat(
        const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) {
    for (auto stat : stats) {
        if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) {
            return stat;
        }
    }
    return std::nullopt;
}

static void transactionCommittedCallbackThunk(void* context, nsecs_t latchTime,
                                              const sp<Fence>& presentFence,
                                              const std::vector<SurfaceControlStats>& stats) {
    if (context == nullptr) {
        return;
    }
    sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context);
    bq->transactionCommittedCallback(latchTime, presentFence, stats);
}

void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/,
                                                    const sp<Fence>& /*presentFence*/,
                                                    const std::vector<SurfaceControlStats>& stats) {
    {
        std::unique_lock _lock{mMutex};
        ATRACE_CALL();
        BQA_LOGV("transactionCommittedCallback");
        if (!mSurfaceControlsWithPendingCallback.empty()) {
            sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
            std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC);
            if (stat) {
                uint64_t currFrameNumber = stat->frameEventStats.frameNumber;

                // We need to check if we were waiting for a transaction callback in order to
                // process any pending buffers and unblock. It's possible to get transaction
                // callbacks for previous requests so we need to ensure the frame from this
                // transaction callback matches the last acquired buffer. Since acquireNextBuffer
                // will stop processing buffers when mWaitForTransactionCallback is set, we know
                // that mLastAcquiredFrameNumber is the frame we're waiting on.
                // We also want to check if mNextTransaction is null because it's possible another
                // sync request came in while waiting, but it hasn't started processing yet. In that
                // case, we don't actually want to flush the frames in between since they will get
                // processed and merged with the sync transaction and released earlier than if they
                // were sent to SF
                if (mWaitForTransactionCallback && mNextTransaction == nullptr &&
                    currFrameNumber >= mLastAcquiredFrameNumber) {
                    mWaitForTransactionCallback = false;
                    flushShadowQueueLocked();
                }
            } else {
                BQA_LOGE("Failed to find matching SurfaceControl in transaction callback");
            }
        } else {
            BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
                     "empty.");
        }

        decStrong((void*)transactionCommittedCallbackThunk);
    }
}

static void transactionCallbackThunk(void* context, nsecs_t latchTime,
                                     const sp<Fence>& presentFence,
                                     const std::vector<SurfaceControlStats>& stats) {
@@ -266,12 +329,9 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
        if (!mSurfaceControlsWithPendingCallback.empty()) {
            sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
            mSurfaceControlsWithPendingCallback.pop();
            bool found = false;
            for (auto stat : stats) {
                if (!SurfaceControl::isSameSurface(pendingSC, stat.surfaceControl)) {
                    continue;
                }

            std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC);
            if (statsOptional) {
                SurfaceControlStats stat = *statsOptional;
                mTransformHint = stat.transformHint;
                mBufferItemConsumer->setTransformHint(mTransformHint);
                BQA_LOGV("updated mTransformHint=%d", mTransformHint);
@@ -299,12 +359,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                    transactionCompleteCallback = std::move(mTransactionCompleteCallback);
                    mTransactionCompleteFrameNumber = 0;
                }

                found = true;
                break;
            }

            if (!found) {
            } else {
                BQA_LOGE("Failed to find matching SurfaceControl in transaction callback");
            }
        } else {
@@ -336,6 +391,20 @@ static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const Relea
    }
}

void BLASTBufferQueue::flushShadowQueueLocked() {
    BQA_LOGV("flushShadowQueueLocked");
    int numFramesToFlush = mNumFrameAvailable;
    while (numFramesToFlush > 0) {
        acquireNextBufferLocked(std::nullopt);
        numFramesToFlush--;
    }
}

void BLASTBufferQueue::flushShadowQueue() {
    std::unique_lock _lock{mMutex};
    flushShadowQueueLocked();
}

void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
                                             const sp<Fence>& releaseFence, uint32_t transformHint,
                                             uint32_t currentMaxAcquiredBufferCount) {
@@ -377,7 +446,11 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
        BQA_LOGV("released %s", id.to_string().c_str());
        mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
        mSubmitted.erase(it);
        processNextBufferLocked(false /* useNextTransaction */);
        // Don't process the transactions here if mWaitForTransactionCallback is set. Instead, let
        // onFrameAvailable handle processing them since it will merge with the nextTransaction.
        if (!mWaitForTransactionCallback) {
            acquireNextBufferLocked(std::nullopt);
        }
    }

    ATRACE_INT("PendingRelease", mPendingRelease.size());
@@ -386,13 +459,15 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
    mCallbackCV.notify_all();
}

void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
void BLASTBufferQueue::acquireNextBufferLocked(
        const std::optional<SurfaceComposerClient::Transaction*> transaction) {
    ATRACE_CALL();
    // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't
    // include the extra buffer when checking if we can acquire the next buffer.
    const bool includeExtraAcquire = !useNextTransaction;
    if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) {
        mCallbackCV.notify_all();
    const bool includeExtraAcquire = !transaction;
    const bool maxAcquired = maxBuffersAcquired(includeExtraAcquire);
    if (mNumFrameAvailable == 0 || maxAcquired) {
        BQA_LOGV("Can't process next buffer maxBuffersAcquired=%s", boolToString(maxAcquired));
        return;
    }

@@ -404,9 +479,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    SurfaceComposerClient::Transaction localTransaction;
    bool applyTransaction = true;
    SurfaceComposerClient::Transaction* t = &localTransaction;
    if (mNextTransaction != nullptr && useNextTransaction) {
        t = mNextTransaction;
        mNextTransaction = nullptr;
    if (transaction) {
        t = *transaction;
        applyTransaction = false;
    }

@@ -436,7 +510,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
                 mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
                 buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
        mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
        processNextBufferLocked(useNextTransaction);
        acquireNextBufferLocked(transaction);
        return;
    }

@@ -455,6 +529,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {

    // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
    incStrong((void*)transactionCallbackThunk);
    incStrong((void*)transactionCommittedCallbackThunk);

    const bool sizeHasChanged = mRequestedSize != mSize;
    mSize = mRequestedSize;
@@ -475,6 +550,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    t->setAcquireFence(mSurfaceControl,
                       bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
    t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
    t->addTransactionCommittedCallback(transactionCommittedCallbackThunk, static_cast<void*>(this));
    mSurfaceControlsWithPendingCallback.push(mSurfaceControl);

    if (updateDestinationFrame) {
@@ -527,7 +603,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
        t->setApplyToken(mApplyToken).apply();
    }

    BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
    BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
             " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
             " graphicBufferId=%" PRIu64 "%s transform=%d",
             mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),
@@ -543,17 +619,44 @@ Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
    return item.mCrop;
}

void BLASTBufferQueue::acquireAndReleaseBuffer() {
    BufferItem bufferItem;
    mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
    mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
    mNumFrameAvailable--;
}

void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
    ATRACE_CALL();
    std::unique_lock _lock{mMutex};

    const bool nextTransactionSet = mNextTransaction != nullptr;
    BQA_LOGV("onFrameAvailable-start nextTransactionSet=%s", boolToString(nextTransactionSet));
    if (nextTransactionSet) {
        while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) {
            BQA_LOGV("waiting in onFrameAvailable...");
        if (mWaitForTransactionCallback) {
            // We are waiting on a previous sync's transaction callback so allow another sync
            // transaction to proceed.
            //
            // We need to first flush out the transactions that were in between the two syncs.
            // We do this by merging them into mNextTransaction so any buffer merging will get
            // a release callback invoked. The release callback will be async so we need to wait
            // on max acquired to make sure we have the capacity to acquire another buffer.
            if (maxBuffersAcquired(false /* includeExtraAcquire */)) {
                BQA_LOGD("waiting to flush shadow queue...");
                mCallbackCV.wait(_lock);
            }
            while (mNumFrameAvailable > 0) {
                // flush out the shadow queue
                acquireAndReleaseBuffer();
            }
        }

        while (maxBuffersAcquired(false /* includeExtraAcquire */)) {
            BQA_LOGD("waiting for free buffer.");
            mCallbackCV.wait(_lock);
        }
    }

    // add to shadow queue
    mNumFrameAvailable++;
    ATRACE_INT(mQueuedBufferTrace.c_str(),
@@ -561,7 +664,14 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {

    BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber,
             boolToString(nextTransactionSet));
    processNextBufferLocked(nextTransactionSet /* useNextTransaction */);

    if (nextTransactionSet) {
        acquireNextBufferLocked(std::move(mNextTransaction));
        mNextTransaction = nullptr;
        mWaitForTransactionCallback = true;
    } else if (!mWaitForTransactionCallback) {
        acquireNextBufferLocked(std::nullopt);
    }
}

void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) {
+11 −2
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ public:
    void onFrameDequeued(const uint64_t) override;
    void onFrameCancelled(const uint64_t) override;

    void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
                                      const std::vector<SurfaceControlStats>& stats);
    void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
            const std::vector<SurfaceControlStats>& stats);
    void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
@@ -99,7 +101,6 @@ public:

    void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format,
                SurfaceComposerClient::Transaction* outTransaction = nullptr);
    void flushShadowQueue() {}

    status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
    status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
@@ -107,6 +108,7 @@ public:
    void setSidebandStream(const sp<NativeHandle>& stream);

    uint32_t getLastTransformHint() const;
    void flushShadowQueue();

    virtual ~BLASTBufferQueue();

@@ -119,13 +121,17 @@ private:
    void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                           sp<IGraphicBufferConsumer>* outConsumer);

    void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex);
    void acquireNextBufferLocked(
            const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex);
    Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
    // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
    bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
    bool maxBuffersAcquired(bool includeExtraAcquire) const REQUIRES(mMutex);
    static PixelFormat convertBufferFormat(PixelFormat& format);

    void flushShadowQueueLocked() REQUIRES(mMutex);
    void acquireAndReleaseBuffer() REQUIRES(mMutex);

    std::string mName;
    // Represents the queued buffer count from buffer queue,
    // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) +
@@ -233,6 +239,9 @@ private:
    // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a
    // callback for them.
    std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex);

    uint32_t mCurrentMaxAcquiredBufferCount;
    bool mWaitForTransactionCallback = false;
};

} // namespace android
+4 −6
Original line number Diff line number Diff line
@@ -134,10 +134,8 @@ private:

        void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,
                                       nsecs_t latchTime) const {
            const auto&
                    [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
                     transformHint,
                     frameEvents] = surfaceControlStats;
            const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence,
                         transformHint, frameEvents] = surfaceControlStats;

            ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
                    << "bad acquire time";
@@ -199,7 +197,7 @@ public:
        std::this_thread::sleep_for(500ms);

        std::lock_guard lock(mMutex);
        EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received";
        EXPECT_EQ(mCallbackDataQueue.size(), 0U) << "extra callbacks received";
        mCallbackDataQueue = {};
    }

@@ -209,5 +207,5 @@ public:
    std::condition_variable mConditionVariable;
    std::queue<CallbackData> mCallbackDataQueue;
};
}
} // namespace
} // namespace android
+266 −6

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@

#include <limits>

#include <gui/test/CallbackUtils.h>
#include "BufferGenerator.h"
#include "utils/CallbackUtils.h"
#include "utils/ColorUtils.h"
#include "utils/TransactionUtils.h"

Loading