diff options
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 88 |
1 files changed, 19 insertions, 69 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 132ee9d71b..454363ac3f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -70,69 +70,11 @@ BufferStateLayer::~BufferStateLayer() { } } -status_t BufferStateLayer::addReleaseFence(const sp<CallbackHandle>& ch, - const sp<Fence>& fence) { - if (ch == nullptr) { - return OK; - } - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - if (!ch->previousReleaseFence.get()) { - ch->previousReleaseFence = fence; - return OK; - } - - // Below logic is lifted from ConsumerBase.cpp: - // Check status of fences first because merging is expensive. - // Merging an invalid fence with any other fence results in an - // invalid fence. - auto currentStatus = ch->previousReleaseFence->getStatus(); - if (currentStatus == Fence::Status::Invalid) { - ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); - return BAD_VALUE; - } - - auto incomingStatus = fence->getStatus(); - if (incomingStatus == Fence::Status::Invalid) { - ALOGE("New fence has invalid state, layer: %s", mName.c_str()); - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (currentStatus == incomingStatus) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", mName.c_str()); - sp<Fence> mergedFence = Fence::merge( - fenceName, ch->previousReleaseFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences, layer: %s", mName.c_str()); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - ch->previousReleaseFence = mergedFence; - } else if (incomingStatus == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - ch->previousReleaseFence = fence; - } - // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. - - return OK; -} - // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { - +void BufferStateLayer::onLayerDisplayed( + std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) { // If a layer has been displayed again we may need to clear // the mLastClientComposition fence that we use for early release in setBuffer // (as we now have a new fence which won't pass through the client composition path in some cases @@ -146,9 +88,6 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { mLastClientCompositionDisplayed = true; } - if (!releaseFence->isValid()) { - return; - } // 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 @@ -173,17 +112,19 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { break; } } - auto status = addReleaseFence(ch, releaseFence); - if (status != OK) { - ALOGE("Failed to add release fence for layer %s", getName().c_str()); - } - mPreviousReleaseFence = releaseFence; + mListPreviousReleaseFences.emplace_back(futureRenderEngineResult); // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mPreviousReleasedFrameNumber = mPreviousFrameNumber; } + + if (ch != nullptr) { + ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; + ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->name = mName; + } } void BufferStateLayer::onSurfaceFrameCreated( @@ -231,9 +172,18 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mFlinger->getTransactionCallbackInvoker().addCallbackHandles( mDrawingState.callbackHandles, jankData); + sp<Fence> releaseFence = Fence::NO_FENCE; + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer && + mDrawingState.releaseBufferEndpoint == handle->listener) { + releaseFence = + handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE; + break; + } + } + mDrawingState.callbackHandles = {}; - const sp<Fence>& releaseFence(mPreviousReleaseFence); std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(releaseFence); { Mutex::Autolock lock(mFrameEventHistoryMutex); |