diff options
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 96a0c3cd75..89dfb6fb6b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -41,6 +41,16 @@ namespace android { using PresentState = frametimeline::SurfaceFrame::PresentState; +namespace { +void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener, + const sp<GraphicBuffer>& buffer, const sp<Fence>& releaseFence) { + if (!listener) { + return; + } + listener->onReleaseBuffer(buffer->getId(), releaseFence ? releaseFence : Fence::NO_FENCE); +} +} // namespace + // clang-format off const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{ 1, 0, 0, 0, @@ -65,7 +75,10 @@ BufferStateLayer::~BufferStateLayer() { // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. auto& engine(mFlinger->getRenderEngine()); - engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); + const uint64_t bufferId = mBufferInfo.mBuffer->getId(); + engine.unbindExternalTextureBuffer(bufferId); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, + mBufferInfo.mFence); } } @@ -74,6 +87,7 @@ status_t BufferStateLayer::addReleaseFence(const sp<CallbackHandle>& ch, if (ch == nullptr) { return OK; } + ch->previousBufferId = mPreviousBufferId; if (!ch->previousReleaseFence.get()) { ch->previousReleaseFence = fence; return OK; @@ -190,6 +204,19 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { handle->dequeueReadyTime = dequeueReadyTime; } + // If there are multiple transactions in this frame, set the previous id on the earliest + // transacton. We don't need to pass in the released buffer id to multiple transactions. + // The buffer id does not have to correspond to any particular transaction as long as the + // listening end point is the same but the client expects the first transaction callback that + // replaces the presented buffer to contain the release fence. This follows the same logic. + // see BufferStateLayer::onLayerDisplayed. + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer) { + handle->previousBufferId = mPreviousBufferId; + break; + } + } + std::vector<JankData> jankData; jankData.reserve(mPendingJankClassifications.size()); while (!mPendingJankClassifications.empty() @@ -344,8 +371,8 @@ bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional<nsecs_t> dequeueTime, - const FrameTimelineInfo& info) { + std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info, + const sp<ITransactionCompletedListener>& releaseBufferListener) { ATRACE_CALL(); if (mCurrentState.buffer) { @@ -353,7 +380,10 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence if (mCurrentState.buffer != mDrawingState.buffer) { // If mCurrentState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be - // dropped and we should decrement the pending buffer count. + // dropped and we should decrement the pending buffer count and + // call any release buffer callbacks if set. + callReleaseBufferCallback(mCurrentState.releaseBufferListener, mCurrentState.buffer, + mCurrentState.acquireFence); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { addSurfaceFrameDroppedForBuffer(mCurrentState.bufferSurfaceFrameTX); @@ -361,9 +391,8 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence } } } - mCurrentState.frameNumber = frameNumber; - + mCurrentState.releaseBufferListener = releaseBufferListener; mCurrentState.buffer = buffer; mCurrentState.clientCacheId = clientCacheId; mCurrentState.modified = true; @@ -889,15 +918,16 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) { ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } -uint32_t BufferStateLayer::doTransaction(uint32_t flags) { - if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer) { +void BufferStateLayer::bufferMayChange(sp<GraphicBuffer>& newBuffer) { + if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && + newBuffer != mDrawingState.buffer) { // If we are about to update mDrawingState.buffer but it has not yet latched - // then we will drop a buffer and should decrement the pending buffer count. - // This logic may not work perfectly in the face of a BufferStateLayer being the - // deferred side of a deferred transaction, but we don't expect this use case. + // then we will drop a buffer and should decrement the pending buffer count and + // call any release buffer callbacks if set. + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, + mDrawingState.acquireFence); decrementPendingBufferCount(); } - return Layer::doTransaction(flags); } } // namespace android |