Loading services/surfaceflinger/BufferLayer.cpp +37 −18 Original line number Diff line number Diff line Loading @@ -389,33 +389,58 @@ void BufferLayer::gatherBufferInfo() { mBufferInfo.mFrameLatencyNeeded = true; } bool BufferLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); return false; } // AutoRefresh layers and sideband streams should always be presented if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } // If the next planned present time is not current, return and try again later if (frameIsEarly(expectedPresentTime)) { ATRACE_NAME("frameIsEarly()"); return false; } // If this layer doesn't have a frame is shouldn't be presented if (!hasFrameUpdate()) { return false; } // Defer to the derived class to decide whether the next buffer is due for // presentation. return isBufferDue(expectedPresentTime); } 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()) { if (!presentTime.has_value()) { return false; } return presentTime >= expectedPresentTime && presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count(); 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(); // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); mFlinger->setTransactionFlags(eTraversalNeeded); return false; } bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); if (refreshRequired) { Loading @@ -435,12 +460,6 @@ 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()) { Loading services/surfaceflinger/BufferLayer.h +15 −8 Original line number Diff line number Diff line Loading @@ -175,12 +175,24 @@ protected: void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; // Transform hint provided to the producer. This must be accessed holding /// the mStateLock. // the mStateLock. ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0; bool getAutoRefresh() const { return mAutoRefresh; } bool getSidebandStreamChanged() const { return mSidebandStreamChanged; } // Returns true if the next buffer should be presented at the expected present time bool shouldPresentNow(nsecs_t expectedPresentTime) const final; // Returns true if the next buffer should be presented at the expected present time, // overridden by BufferStateLayer and BufferQueueLayer for implementation // specific logic virtual bool isBufferDue(nsecs_t /*expectedPresentTime*/) const = 0; // Returns true if the next frame is considered too early to present // at the given expectedPresentTime bool frameIsEarly(nsecs_t expectedPresentTime) const; std::atomic<bool> mAutoRefresh{false}; std::atomic<bool> mSidebandStreamChanged{false}; Loading Loading @@ -225,13 +237,8 @@ private: 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; // Returns the predicted present time of the next frame if available virtual std::optional<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 Loading services/surfaceflinger/BufferQueueLayer.cpp +4 −12 Original line number Diff line number Diff line Loading @@ -100,15 +100,7 @@ int32_t BufferQueueLayer::getQueuedFrameCount() const { return mQueuedFrames; } bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } if (!hasFrameUpdate()) { return false; } bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); const int64_t addedTime = mQueueItems[0].item.mTimestamp; Loading Loading @@ -223,16 +215,16 @@ bool BufferQueueLayer::hasFrameUpdate() const { return mQueuedFrames > 0; } nsecs_t BufferQueueLayer::nextPredictedPresentTime() const { std::optional<nsecs_t> BufferQueueLayer::nextPredictedPresentTime() const { Mutex::Autolock lock(mQueueItemLock); if (mQueueItems.empty()) { return 0; return std::nullopt; } const auto& bufferData = mQueueItems[0]; if (!bufferData.item.mIsAutoTimestamp || !bufferData.surfaceFrame) { return 0; return std::nullopt; } return bufferData.surfaceFrame->getPredictions().presentTime; Loading services/surfaceflinger/BufferQueueLayer.h +3 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ public: int32_t getQueuedFrameCount() const override; bool shouldPresentNow(nsecs_t expectedPresentTime) const override; // Returns true if the next buffer should be presented at the expected present time bool isBufferDue(nsecs_t expectedPresentTime) const override; // Implements BufferLayer. bool fenceHasSignaled() const override; Loading Loading @@ -116,7 +117,7 @@ private: // Temporary - Used only for LEGACY camera mode. uint32_t getProducerStickyTransform() const; nsecs_t nextPredictedPresentTime() const override; std::optional<nsecs_t> nextPredictedPresentTime() const override; sp<BufferLayerConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; Loading services/surfaceflinger/BufferStateLayer.cpp +2 −10 Original line number Diff line number Diff line Loading @@ -212,14 +212,6 @@ void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime } } bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } return hasFrameUpdate(); } bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. return (getSidebandStreamChanged() || getAutoRefresh() || Loading Loading @@ -602,9 +594,9 @@ bool BufferStateLayer::hasFrameUpdate() const { return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } nsecs_t BufferStateLayer::nextPredictedPresentTime() const { std::optional<nsecs_t> BufferStateLayer::nextPredictedPresentTime() const { if (!getDrawingState().isAutoTimestamp || !mSurfaceFrame) { return 0; return std::nullopt; } return mSurfaceFrame->getPredictions().presentTime; Loading Loading
services/surfaceflinger/BufferLayer.cpp +37 −18 Original line number Diff line number Diff line Loading @@ -389,33 +389,58 @@ void BufferLayer::gatherBufferInfo() { mBufferInfo.mFrameLatencyNeeded = true; } bool BufferLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); return false; } // AutoRefresh layers and sideband streams should always be presented if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } // If the next planned present time is not current, return and try again later if (frameIsEarly(expectedPresentTime)) { ATRACE_NAME("frameIsEarly()"); return false; } // If this layer doesn't have a frame is shouldn't be presented if (!hasFrameUpdate()) { return false; } // Defer to the derived class to decide whether the next buffer is due for // presentation. return isBufferDue(expectedPresentTime); } 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()) { if (!presentTime.has_value()) { return false; } return presentTime >= expectedPresentTime && presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count(); 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(); // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); mFlinger->setTransactionFlags(eTraversalNeeded); return false; } bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); if (refreshRequired) { Loading @@ -435,12 +460,6 @@ 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()) { Loading
services/surfaceflinger/BufferLayer.h +15 −8 Original line number Diff line number Diff line Loading @@ -175,12 +175,24 @@ protected: void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; // Transform hint provided to the producer. This must be accessed holding /// the mStateLock. // the mStateLock. ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0; bool getAutoRefresh() const { return mAutoRefresh; } bool getSidebandStreamChanged() const { return mSidebandStreamChanged; } // Returns true if the next buffer should be presented at the expected present time bool shouldPresentNow(nsecs_t expectedPresentTime) const final; // Returns true if the next buffer should be presented at the expected present time, // overridden by BufferStateLayer and BufferQueueLayer for implementation // specific logic virtual bool isBufferDue(nsecs_t /*expectedPresentTime*/) const = 0; // Returns true if the next frame is considered too early to present // at the given expectedPresentTime bool frameIsEarly(nsecs_t expectedPresentTime) const; std::atomic<bool> mAutoRefresh{false}; std::atomic<bool> mSidebandStreamChanged{false}; Loading Loading @@ -225,13 +237,8 @@ private: 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; // Returns the predicted present time of the next frame if available virtual std::optional<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 Loading
services/surfaceflinger/BufferQueueLayer.cpp +4 −12 Original line number Diff line number Diff line Loading @@ -100,15 +100,7 @@ int32_t BufferQueueLayer::getQueuedFrameCount() const { return mQueuedFrames; } bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } if (!hasFrameUpdate()) { return false; } bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); const int64_t addedTime = mQueueItems[0].item.mTimestamp; Loading Loading @@ -223,16 +215,16 @@ bool BufferQueueLayer::hasFrameUpdate() const { return mQueuedFrames > 0; } nsecs_t BufferQueueLayer::nextPredictedPresentTime() const { std::optional<nsecs_t> BufferQueueLayer::nextPredictedPresentTime() const { Mutex::Autolock lock(mQueueItemLock); if (mQueueItems.empty()) { return 0; return std::nullopt; } const auto& bufferData = mQueueItems[0]; if (!bufferData.item.mIsAutoTimestamp || !bufferData.surfaceFrame) { return 0; return std::nullopt; } return bufferData.surfaceFrame->getPredictions().presentTime; Loading
services/surfaceflinger/BufferQueueLayer.h +3 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ public: int32_t getQueuedFrameCount() const override; bool shouldPresentNow(nsecs_t expectedPresentTime) const override; // Returns true if the next buffer should be presented at the expected present time bool isBufferDue(nsecs_t expectedPresentTime) const override; // Implements BufferLayer. bool fenceHasSignaled() const override; Loading Loading @@ -116,7 +117,7 @@ private: // Temporary - Used only for LEGACY camera mode. uint32_t getProducerStickyTransform() const; nsecs_t nextPredictedPresentTime() const override; std::optional<nsecs_t> nextPredictedPresentTime() const override; sp<BufferLayerConsumer> mConsumer; sp<IGraphicBufferProducer> mProducer; Loading
services/surfaceflinger/BufferStateLayer.cpp +2 −10 Original line number Diff line number Diff line Loading @@ -212,14 +212,6 @@ void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime } } bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { if (getSidebandStreamChanged() || getAutoRefresh()) { return true; } return hasFrameUpdate(); } bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. return (getSidebandStreamChanged() || getAutoRefresh() || Loading Loading @@ -602,9 +594,9 @@ bool BufferStateLayer::hasFrameUpdate() const { return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } nsecs_t BufferStateLayer::nextPredictedPresentTime() const { std::optional<nsecs_t> BufferStateLayer::nextPredictedPresentTime() const { if (!getDrawingState().isAutoTimestamp || !mSurfaceFrame) { return 0; return std::nullopt; } return mSurfaceFrame->getPredictions().presentTime; Loading