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

Commit 048c6517 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Call release buffer if the buffer is overwritten in the client"

parents 8ced9052 69058fb4
Loading
Loading
Loading
Loading
+14 −18
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont

    ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
    mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
    mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;

    mTransformHint = mSurfaceControl->getTransformHint();
    mBufferItemConsumer->setTransformHint(mTransformHint);
@@ -325,31 +326,23 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
// So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
// Otherwise, this is a no-op.
static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const ReleaseCallbackId& id,
                                       const sp<Fence>& releaseFence, uint32_t transformHint,
                                       uint32_t currentMaxAcquiredBufferCount) {
                                       const sp<Fence>& releaseFence,
                                       std::optional<uint32_t> currentMaxAcquiredBufferCount) {
    sp<BLASTBufferQueue> blastBufferQueue = context.promote();
    if (blastBufferQueue) {
        blastBufferQueue->releaseBufferCallback(id, releaseFence, transformHint,
                                                currentMaxAcquiredBufferCount);
        blastBufferQueue->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
    } else {
        ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
    }
}

void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
                                             const sp<Fence>& releaseFence, uint32_t transformHint,
                                             uint32_t currentMaxAcquiredBufferCount) {
void BLASTBufferQueue::releaseBufferCallback(
        const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
        std::optional<uint32_t> currentMaxAcquiredBufferCount) {
    ATRACE_CALL();
    std::unique_lock _lock{mMutex};
    BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());

    if (mSurfaceControl != nullptr) {
        mTransformHint = transformHint;
        mSurfaceControl->setTransformHint(transformHint);
        mBufferItemConsumer->setTransformHint(mTransformHint);
        BQA_LOGV("updated mTransformHint=%d", mTransformHint);
    }

    // Calculate how many buffers we need to hold before we release them back
    // to the buffer queue. This will prevent higher latency when we are running
    // on a lower refresh rate than the max supported. We only do that for EGL
@@ -359,8 +352,12 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
        return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
    }();

    if (currentMaxAcquiredBufferCount) {
        mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
    }

    const auto numPendingBuffersToHold =
            isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0;
            isEGL ? std::max(0u, mMaxAcquiredBuffers - mCurrentMaxAcquiredBufferCount) : 0;
    mPendingRelease.emplace_back(ReleasedBuffer{id, releaseFence});

    // Release all buffers that are beyond the ones that we need to hold
@@ -374,7 +371,7 @@ void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
            return;
        }
        mNumAcquired--;
        BQA_LOGV("released %s", id.to_string().c_str());
        BQA_LOGV("released %s", releaseBuffer.callbackId.to_string().c_str());
        mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
        mSubmitted.erase(it);
        processNextBufferLocked(false /* useNextTransaction */);
@@ -466,8 +463,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {

    auto releaseBufferCallback =
            std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
                      std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
                      std::placeholders::_4);
                      std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId,
                 releaseBufferCallback);
+1 −2
Original line number Diff line number Diff line
@@ -254,11 +254,10 @@ public:
    }

    void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                         uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override {
                         uint32_t currentMaxAcquiredBufferCount) override {
        callRemoteAsync<decltype(
                &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
                                                                  callbackId, releaseFence,
                                                                  transformHint,
                                                                  currentMaxAcquiredBufferCount);
    }
};
+71 −19
Original line number Diff line number Diff line
@@ -214,12 +214,6 @@ void TransactionCompletedListener::setReleaseBufferCallback(const ReleaseCallbac
    mReleaseBufferCallbacks[callbackId] = listener;
}

void TransactionCompletedListener::removeReleaseBufferCallback(
        const ReleaseCallbackId& callbackId) {
    std::scoped_lock<std::mutex> lock(mMutex);
    mReleaseBufferCallbacks.erase(callbackId);
}

void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie,
        sp<SurfaceControl> surfaceControl, SurfaceStatsCallback listener) {
    std::scoped_lock<std::recursive_mutex> lock(mSurfaceStatsListenerMutex);
@@ -343,7 +337,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
                                 surfaceStats.previousReleaseFence
                                         ? surfaceStats.previousReleaseFence
                                         : Fence::NO_FENCE,
                                 surfaceStats.transformHint,
                                 surfaceStats.currentMaxAcquiredBufferCount);
                    }
                }
@@ -389,7 +382,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
}

void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
                                                   sp<Fence> releaseFence, uint32_t transformHint,
                                                   sp<Fence> releaseFence,
                                                   uint32_t currentMaxAcquiredBufferCount) {
    ReleaseBufferCallback callback;
    {
@@ -401,7 +394,11 @@ void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
              callbackId.to_string().c_str());
        return;
    }
    callback(callbackId, releaseFence, transformHint, currentMaxAcquiredBufferCount);
    std::optional<uint32_t> optionalMaxAcquiredBufferCount =
            currentMaxAcquiredBufferCount == UINT_MAX
            ? std::nullopt
            : std::make_optional<uint32_t>(currentMaxAcquiredBufferCount);
    callback(callbackId, releaseFence, optionalMaxAcquiredBufferCount);
}

ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked(
@@ -712,11 +709,34 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const
    return NO_ERROR;
}

void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_state_t& state) {
    if (!(state.what & layer_state_t::eBufferChanged)) {
        return;
    }

    auto listener = state.bufferData.releaseBufferListener;
    sp<Fence> fence =
            state.bufferData.acquireFence ? state.bufferData.acquireFence : Fence::NO_FENCE;
    if (state.bufferData.releaseBufferEndpoint ==
        IInterface::asBinder(TransactionCompletedListener::getIInstance())) {
        // if the callback is in process, run on a different thread to avoid any lock contigency
        // issues in the client.
        SurfaceComposerClient::getDefault()
                ->mReleaseCallbackThread.addReleaseCallback(state.bufferData.releaseCallbackId,
                                                            fence);
    } else {
        listener->onReleaseBuffer(state.bufferData.releaseCallbackId, fence, UINT_MAX);
    }
}

SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
    for (auto const& [handle, composerState] : other.mComposerStates) {
        if (mComposerStates.count(handle) == 0) {
            mComposerStates[handle] = composerState;
        } else {
            if (composerState.state.what & layer_state_t::eBufferChanged) {
                releaseBufferIfOverwriting(mComposerStates[handle].state);
            }
            mComposerStates[handle].state.merge(composerState.state);
        }
    }
@@ -1296,7 +1316,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe
        mStatus = BAD_INDEX;
        return *this;
    }
    removeReleaseBufferCallback(s);

    releaseBufferIfOverwriting(*s);

    BufferData bufferData;
    bufferData.buffer = buffer;
    if (frameNumber) {
@@ -1321,15 +1343,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe
    return *this;
}

void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) {
    if (!(s->what & layer_state_t::eBufferChanged)) {
        return;
    }

    auto listener = TransactionCompletedListener::getInstance();
    listener->removeReleaseBufferCallback(s->bufferData.releaseCallbackId);
}

void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
                                                                  const ReleaseCallbackId& id,
                                                                  ReleaseBufferCallback callback) {
@@ -2210,4 +2223,43 @@ status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs,
    return s->captureLayers(captureArgs, captureListener);
}

// ---------------------------------------------------------------------------------

void ReleaseCallbackThread::addReleaseCallback(const ReleaseCallbackId callbackId,
                                               sp<Fence> releaseFence) {
    std::scoped_lock<std::mutex> lock(mMutex);
    if (!mStarted) {
        mThread = std::thread(&ReleaseCallbackThread::threadMain, this);
        mStarted = true;
    }

    mCallbackInfos.emplace(callbackId, std::move(releaseFence));
    mReleaseCallbackPending.notify_one();
}

void ReleaseCallbackThread::threadMain() {
    const auto listener = TransactionCompletedListener::getInstance();
    std::queue<std::tuple<const ReleaseCallbackId, const sp<Fence>>> callbackInfos;
    while (true) {
        {
            std::unique_lock<std::mutex> lock(mMutex);
            callbackInfos = std::move(mCallbackInfos);
            mCallbackInfos = {};
        }

        while (!callbackInfos.empty()) {
            auto [callbackId, releaseFence] = callbackInfos.front();
            listener->onReleaseBuffer(callbackId, std::move(releaseFence), UINT_MAX);
            callbackInfos.pop();
        }

        {
            std::unique_lock<std::mutex> lock(mMutex);
            if (mCallbackInfos.size() == 0) {
                mReleaseCallbackPending.wait(lock);
            }
        }
    }
}

} // namespace android
+3 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ public:
    void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
            const std::vector<SurfaceControlStats>& stats);
    void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
                               uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount);
                               std::optional<uint32_t> currentMaxAcquiredBufferCount);
    void setNextTransaction(SurfaceComposerClient::Transaction *t);
    void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
    void applyPendingTransactions(uint64_t frameNumber);
@@ -236,6 +236,8 @@ 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;
};

} // namespace android
+0 −1
Original line number Diff line number Diff line
@@ -192,7 +192,6 @@ public:
    virtual void onTransactionCompleted(ListenerStats stats) = 0;

    virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                                 uint32_t transformHint,
                                 uint32_t currentMaxAcquiredBufferCount) = 0;
};

Loading