diff options
-rw-r--r-- | services/surfaceflinger/BufferLayer.cpp | 20 | ||||
-rw-r--r-- | services/surfaceflinger/BufferLayer.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/BufferQueueLayer.cpp | 15 | ||||
-rw-r--r-- | services/surfaceflinger/BufferQueueLayer.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.h | 2 |
6 files changed, 59 insertions, 0 deletions
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fa75ffa403..6561707bcc 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -389,6 +389,20 @@ void BufferLayer::gatherBufferInfo() { mBufferInfo.mFrameLatencyNeeded = true; } +bool BufferLayer::frameIsEarly(nsecs_t expectedPresentTime) const { + // TODO(b/169901895): kEarlyLatchVsyncThreshold should be based on the + // vsync period. We can do this change as soon as ag/13100772 is merged. + constexpr static std::chrono::nanoseconds kEarlyLatchVsyncThreshold = 5ms; + + const auto presentTime = nextPredictedPresentTime(); + if (std::abs(presentTime - expectedPresentTime) >= kEarlyLatchMaxThreshold.count()) { + return false; + } + + return presentTime >= expectedPresentTime && + presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count(); +} + bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) { ATRACE_CALL(); @@ -421,6 +435,12 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } + if (frameIsEarly(expectedPresentTime)) { + ATRACE_NAME("frameIsEarly()"); + mFlinger->signalLayerUpdate(); + return false; + } + // If the head buffer's acquire fence hasn't signaled yet, return and // try again later if (!fenceHasSignaled()) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 63dfe5f5d9..5cd9a7cde1 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -224,6 +224,18 @@ private: std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; + + // Returns true if the next frame is considered too early to present + // at the given expectedPresentTime + bool frameIsEarly(nsecs_t expectedPresentTime) const; + + // Returns the predicted present time of the next frame if available or + // 0 otherwise. + virtual nsecs_t nextPredictedPresentTime() const = 0; + + // The amount of time SF can delay a frame if it is considered early based + // on the VsyncModulator::VsyncConfig::appWorkDuration + static constexpr std::chrono::nanoseconds kEarlyLatchMaxThreshold = 100ms; }; } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 56d874258e..e8e31db236 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -222,6 +222,21 @@ bool BufferQueueLayer::hasFrameUpdate() const { return mQueuedFrames > 0; } +nsecs_t BufferQueueLayer::nextPredictedPresentTime() const { + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems.empty()) { + return 0; + } + + const auto& bufferData = mQueueItems[0]; + + if (!bufferData.item.mIsAutoTimestamp || !bufferData.surfaceFrame) { + return 0; + } + + return bufferData.surfaceFrame->getPredictions().presentTime; +} + status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) { // This boolean is used to make sure that SurfaceFlinger's shadow copy diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 3551026f17..2347d8cec7 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -116,6 +116,8 @@ private: // Temporary - Used only for LEGACY camera mode. uint32_t getProducerStickyTransform() const; + nsecs_t nextPredictedPresentTime() const override; + sp<BufferLayerConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index df1472d0d4..7ec7f36548 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -601,6 +601,14 @@ bool BufferStateLayer::hasFrameUpdate() const { return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } +nsecs_t BufferStateLayer::nextPredictedPresentTime() const { + if (!getDrawingState().isAutoTimestamp || !mSurfaceFrame) { + return 0; + } + + return mSurfaceFrame->getPredictions().presentTime; +} + status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, nsecs_t /*expectedPresentTime*/) { const State& s(getDrawingState()); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 734f647b01..6414e6be60 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -152,6 +152,8 @@ private: bool bufferNeedsFiltering() const override; + nsecs_t nextPredictedPresentTime() const override; + static const std::array<float, 16> IDENTITY_MATRIX; std::unique_ptr<renderengine::Image> mTextureImage; |