diff options
-rw-r--r-- | libs/ui/FenceTime.cpp | 28 | ||||
-rw-r--r-- | libs/ui/include/ui/FenceTime.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 9 | ||||
-rw-r--r-- | services/surfaceflinger/FrameTracker.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/FrameTracker.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 41 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 9 |
9 files changed, 75 insertions, 30 deletions
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index bdfe04b0dd..538c1d2a42 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -97,6 +97,34 @@ bool FenceTime::isValid() const { return mState != State::INVALID; } +status_t FenceTime::wait(int timeout) { + // See if we already have a cached value we can return. + nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed); + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + return NO_ERROR; + } + + // Hold a reference to the fence on the stack in case the class' + // reference is removed by another thread. This prevents the + // fence from being destroyed until the end of this method, where + // we conveniently do not have the lock held. + sp<Fence> fence; + { + // With the lock acquired this time, see if we have the cached + // value or if we need to poll the fence. + std::lock_guard<std::mutex> lock(mMutex); + if (!mFence.get()) { + // Another thread set the signal time just before we added the + // reference to mFence. + return NO_ERROR; + } + fence = mFence; + } + + // Make the system call without the lock held. + return fence->wait(timeout); +} + nsecs_t FenceTime::getSignalTime() { // See if we already have a cached value we can return. nsecs_t signalTime = mSignalTime.load(std::memory_order_relaxed); diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h index ecba7f73e8..ac75f431a0 100644 --- a/libs/ui/include/ui/FenceTime.h +++ b/libs/ui/include/ui/FenceTime.h @@ -112,6 +112,13 @@ public: // Returns a snapshot of the FenceTime in its current state. Snapshot getSnapshot() const; + // wait waits for up to timeout milliseconds for the fence to signal. If + // the fence signals then NO_ERROR is returned. If the timeout expires + // before the fence signals then -ETIME is returned. A timeout of + // TIMEOUT_NEVER may be used to indicate that the call should wait + // indefinitely for the fence to signal. + status_t wait(int timeout); + void signalForTest(nsecs_t signalTime); private: diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index a974dc4488..d6becbf213 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -432,10 +432,12 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence } bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) { + mCurrentState.acquireFence = fence; + mCurrentState.acquireFenceTime = std::make_unique<FenceTime>(fence); + // The acquire fences of BufferStateLayers have already signaled before they are set - mCallbackHandleAcquireTime = fence->getSignalTime(); + mCallbackHandleAcquireTime = mCurrentState.acquireFenceTime->getSignalTime(); - mCurrentState.acquireFence = fence; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -691,7 +693,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we // are processing the next state. addSurfaceFramePresentedForBuffer(bufferSurfaceFrame, - mDrawingState.acquireFence->getSignalTime(), latchTime); + mDrawingState.acquireFenceTime->getSignalTime(), + latchTime); } mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index 8ad805b1d8..178c531a2a 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -62,10 +62,9 @@ void FrameTracker::setActualPresentTime(nsecs_t presentTime) { mFrameRecords[mOffset].actualPresentTime = presentTime; } -void FrameTracker::setActualPresentFence( - std::shared_ptr<FenceTime>&& readyFence) { +void FrameTracker::setActualPresentFence(const std::shared_ptr<FenceTime>& readyFence) { Mutex::Autolock lock(mMutex); - mFrameRecords[mOffset].actualPresentFence = std::move(readyFence); + mFrameRecords[mOffset].actualPresentFence = readyFence; mNumFences++; } diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index 35382be1c0..bc412aee2f 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -66,7 +66,7 @@ public: // setActualPresentFence sets the fence that is used to get the time // at which the current frame became visible to the user. - void setActualPresentFence(std::shared_ptr<FenceTime>&& fence); + void setActualPresentFence(const std::shared_ptr<FenceTime>& fence); // setDisplayRefreshPeriod sets the display refresh period in nanoseconds. // This is used to compute frame presentation duration statistics relative diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b5410fe295..dbd6b32656 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -116,7 +116,8 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.bufferTransform = 0; mCurrentState.transformToDisplayInverse = false; mCurrentState.crop.makeInvalid(); - mCurrentState.acquireFence = new Fence(-1); + mCurrentState.acquireFence = sp<Fence>::make(-1); + mCurrentState.acquireFenceTime = std::make_shared<FenceTime>(mCurrentState.acquireFence); mCurrentState.dataspace = ui::Dataspace::UNKNOWN; mCurrentState.hdrMetadata.validTypes = 0; mCurrentState.surfaceDamageRegion = Region::INVALID_REGION; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 421a10776f..3f7a75f691 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -261,6 +261,7 @@ public: sp<GraphicBuffer> buffer; client_cache_t clientCacheId; sp<Fence> acquireFence; + std::shared_ptr<FenceTime> acquireFenceTime; HdrMetadata hdrMetadata; Region surfaceDamageRegion; int32_t api; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 84b4b236db..a9c82d0333 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1661,7 +1661,7 @@ void SurfaceFlinger::setVsyncEnabled(bool enabled) { })); } -sp<Fence> SurfaceFlinger::previousFrameFence() { +SurfaceFlinger::FenceWithFenceTime SurfaceFlinger::previousFrameFence() { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check // fence N-2 @@ -1671,9 +1671,9 @@ sp<Fence> SurfaceFlinger::previousFrameFence() { bool SurfaceFlinger::previousFramePending(int graceTimeMs) { ATRACE_CALL(); - const sp<Fence>& fence = previousFrameFence(); + const std::shared_ptr<FenceTime>& fence = previousFrameFence().fenceTime; - if (fence == Fence::NO_FENCE) { + if (fence == FenceTime::NO_FENCE) { return false; } @@ -1684,9 +1684,9 @@ bool SurfaceFlinger::previousFramePending(int graceTimeMs) { } nsecs_t SurfaceFlinger::previousFramePresentTime() { - const sp<Fence>& fence = previousFrameFence(); + const std::shared_ptr<FenceTime>& fence = previousFrameFence().fenceTime; - if (fence == Fence::NO_FENCE) { + if (fence == FenceTime::NO_FENCE) { return Fence::SIGNAL_TIME_INVALID; } @@ -2117,16 +2117,17 @@ void SurfaceFlinger::postComposition() { getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFences[1] = mPreviousPresentFences[0]; - mPreviousPresentFences[0] = + mPreviousPresentFences[0].fence = display ? getHwComposer().getPresentFence(display->getPhysicalId()) : Fence::NO_FENCE; - auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]); - getBE().mDisplayTimeline.push(presentFenceTime); + mPreviousPresentFences[0].fenceTime = + std::make_shared<FenceTime>(mPreviousPresentFences[0].fence); + + getBE().mDisplayTimeline.push(mPreviousPresentFences[0].fenceTime); // Set presentation information before calling Layer::releasePendingBuffer, such that jank // information from previous' frame classification is already available when sending jank info // to clients, so they get jank classification as early as possible. - mFrameTimeline->setSfPresent(systemTime(), - std::make_shared<FenceTime>(mPreviousPresentFences[0]), + mFrameTimeline->setSfPresent(systemTime(), mPreviousPresentFences[0].fenceTime, glCompositionDoneFenceTime != FenceTime::NO_FENCE); nsecs_t dequeueReadyTime = systemTime(); @@ -2140,7 +2141,7 @@ void SurfaceFlinger::postComposition() { // be sampled a little later than when we started doing work for this frame, // but that should be okay since updateCompositorTiming has snapping logic. updateCompositorTiming(stats, mCompositionEngine->getLastFrameRefreshTimestamp(), - presentFenceTime); + mPreviousPresentFences[0].fenceTime); CompositorTiming compositorTiming; { std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock); @@ -2148,8 +2149,9 @@ void SurfaceFlinger::postComposition() { } mDrawingState.traverse([&](Layer* layer) { - const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime, - presentFenceTime, compositorTiming); + const bool frameLatched = + layer->onPostComposition(display, glCompositionDoneFenceTime, + mPreviousPresentFences[0].fenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); } @@ -2162,12 +2164,12 @@ void SurfaceFlinger::postComposition() { } } - mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0]); + mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence); mTransactionCallbackInvoker.sendCallbacks(); if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON && - presentFenceTime->isValid()) { - mScheduler->addPresentFence(presentFenceTime); + mPreviousPresentFences[0].fenceTime->isValid()) { + mScheduler->addPresentFence(mPreviousPresentFences[0].fenceTime); } const bool isDisplayConnected = @@ -2182,9 +2184,8 @@ void SurfaceFlinger::postComposition() { if (mAnimCompositionPending) { mAnimCompositionPending = false; - if (presentFenceTime->isValid()) { - mAnimFrameTracker.setActualPresentFence( - std::move(presentFenceTime)); + if (mPreviousPresentFences[0].fenceTime->isValid()) { + mAnimFrameTracker.setActualPresentFence(mPreviousPresentFences[0].fenceTime); } else if (isDisplayConnected) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. @@ -2203,7 +2204,7 @@ void SurfaceFlinger::postComposition() { mTimeStats->incrementClientCompositionReusedFrames(); } - mTimeStats->setPresentFenceGlobal(presentFenceTime); + mTimeStats->setPresentFenceGlobal(mPreviousPresentFences[0].fenceTime); const size_t sfConnections = mScheduler->getEventThreadConnectionCount(mSfConnectionHandle); const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c57b180dd4..c4c9ce3c20 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1013,9 +1013,14 @@ private: bool isDisplayModeAllowed(DisplayModeId) const REQUIRES(mStateLock); + struct FenceWithFenceTime { + sp<Fence> fence = Fence::NO_FENCE; + std::shared_ptr<FenceTime> fenceTime = FenceTime::NO_FENCE; + }; + // Gets the fence for the previous frame. // Must be called on the main thread. - sp<Fence> previousFrameFence(); + FenceWithFenceTime previousFrameFence(); // Whether the previous frame has not yet been presented to the display. // If graceTimeMs is positive, this method waits for at most the provided @@ -1193,7 +1198,7 @@ private: std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> mLayersWithQueuedFrames; // Tracks layers that need to update a display's dirty region. std::vector<sp<Layer>> mLayersPendingRefresh; - std::array<sp<Fence>, 2> mPreviousPresentFences = {Fence::NO_FENCE, Fence::NO_FENCE}; + std::array<FenceWithFenceTime, 2> mPreviousPresentFences; // True if in the previous frame at least one layer was composed via the GPU. bool mHadClientComposition = false; // True if in the previous frame at least one layer was composed via HW Composer. |