Loading services/surfaceflinger/Scheduler/VSyncPredictor.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -71,12 +71,12 @@ nsecs_t VSyncPredictor::currentPeriod() const { return std::get<0>(mRateMap.find(mIdealPeriod)->second); } void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { std::lock_guard<std::mutex> lk(mMutex); if (!validate(timestamp)) { ALOGV("timestamp was too far off the last known timestamp"); return; return false; } if (timestamps.size() != kHistorySize) { Loading @@ -89,7 +89,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (timestamps.size() < kMinimumSamplesForPrediction) { mRateMap[mIdealPeriod] = {mIdealPeriod, 0}; return; return true; } // This is a 'simple linear regression' calculation of Y over X, with Y being the Loading Loading @@ -143,7 +143,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (CC_UNLIKELY(bottom == 0)) { it->second = {mIdealPeriod, 0}; return; return false; } nsecs_t const anticipatedPeriod = top / bottom * kScalingFactor; Loading @@ -156,6 +156,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { ALOGV("model update ts: %" PRId64 " slope: %" PRId64 " intercept: %" PRId64, timestamp, anticipatedPeriod, intercept); return true; } nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { Loading services/surfaceflinger/Scheduler/VSyncPredictor.h +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ public: uint32_t outlierTolerancePercent); ~VSyncPredictor(); void addVsyncTimestamp(nsecs_t timestamp) final; bool addVsyncTimestamp(nsecs_t timestamp) final; nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final; nsecs_t currentPeriod() const final; void resetModel() final; Loading services/surfaceflinger/Scheduler/VSyncReactor.cpp +43 −16 Original line number Diff line number Diff line Loading @@ -130,10 +130,11 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } std::lock_guard<std::mutex> lk(mMutex); if (mIgnorePresentFences) { if (mExternalIgnoreFences || mInternalIgnoreFences) { return true; } bool timestampAccepted = true; for (auto it = mUnfiredFences.begin(); it != mUnfiredFences.end();) { auto const time = (*it)->getCachedSignalTime(); if (time == Fence::SIGNAL_TIME_PENDING) { Loading @@ -141,7 +142,8 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } else if (time == Fence::SIGNAL_TIME_INVALID) { it = mUnfiredFences.erase(it); } else { mTracker->addVsyncTimestamp(time); timestampAccepted &= mTracker->addVsyncTimestamp(time); it = mUnfiredFences.erase(it); } } Loading @@ -152,7 +154,13 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } mUnfiredFences.push_back(fence); } else { mTracker->addVsyncTimestamp(signalTime); timestampAccepted &= mTracker->addVsyncTimestamp(signalTime); } if (!timestampAccepted) { mMoreSamplesNeeded = true; setIgnorePresentFencesInternal(true); mPeriodConfirmationInProgress = true; } return mMoreSamplesNeeded; Loading @@ -160,8 +168,17 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { void VSyncReactor::setIgnorePresentFences(bool ignoration) { std::lock_guard<std::mutex> lk(mMutex); mIgnorePresentFences = ignoration; if (mIgnorePresentFences == true) { mExternalIgnoreFences = ignoration; updateIgnorePresentFencesInternal(); } void VSyncReactor::setIgnorePresentFencesInternal(bool ignoration) { mInternalIgnoreFences = ignoration; updateIgnorePresentFencesInternal(); } void VSyncReactor::updateIgnorePresentFencesInternal() { if (mExternalIgnoreFences || mInternalIgnoreFences) { mUnfiredFences.clear(); } } Loading @@ -177,14 +194,18 @@ nsecs_t VSyncReactor::expectedPresentTime() { } void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) { mPeriodConfirmationInProgress = true; mPeriodTransitioningTo = newPeriod; mMoreSamplesNeeded = true; setIgnorePresentFencesInternal(true); } void VSyncReactor::endPeriodTransition() { setIgnorePresentFencesInternal(false); mMoreSamplesNeeded = false; mPeriodTransitioningTo.reset(); mPeriodConfirmationInProgress = false; mLastHwVsync.reset(); mMoreSamplesNeeded = false; } void VSyncReactor::setPeriod(nsecs_t period) { Loading @@ -208,27 +229,33 @@ void VSyncReactor::beginResync() { void VSyncReactor::endResync() {} bool VSyncReactor::periodChangeDetected(nsecs_t vsync_timestamp) { if (!mLastHwVsync || !mPeriodTransitioningTo) { bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp) { if (!mLastHwVsync || !mPeriodConfirmationInProgress) { return false; } auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : getPeriod(); static constexpr int allowancePercent = 10; static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio; auto const allowance = period * allowancePercentRatio.num / allowancePercentRatio.den; auto const distance = vsync_timestamp - *mLastHwVsync; return std::abs(distance - *mPeriodTransitioningTo) < std::abs(distance - getPeriod()); return std::abs(distance - period) < allowance; } bool VSyncReactor::addResyncSample(nsecs_t timestamp, bool* periodFlushed) { assert(periodFlushed); std::lock_guard<std::mutex> lk(mMutex); if (periodChangeDetected(timestamp)) { if (periodConfirmed(timestamp)) { if (mPeriodTransitioningTo) { mTracker->setPeriod(*mPeriodTransitioningTo); for (auto& entry : mCallbacks) { entry.second->setPeriod(*mPeriodTransitioningTo); } endPeriodTransition(); *periodFlushed = true; } else if (mPeriodTransitioningTo) { } endPeriodTransition(); } else if (mPeriodConfirmationInProgress) { mLastHwVsync = timestamp; mMoreSamplesNeeded = true; *periodFlushed = false; Loading services/surfaceflinger/Scheduler/VSyncReactor.h +6 −2 Original line number Diff line number Diff line Loading @@ -61,9 +61,11 @@ public: void reset() final; private: void setIgnorePresentFencesInternal(bool ignoration) REQUIRES(mMutex); void updateIgnorePresentFencesInternal() REQUIRES(mMutex); void startPeriodTransition(nsecs_t newPeriod) REQUIRES(mMutex); void endPeriodTransition() REQUIRES(mMutex); bool periodChangeDetected(nsecs_t vsync_timestamp) REQUIRES(mMutex); bool periodConfirmed(nsecs_t vsync_timestamp) REQUIRES(mMutex); std::unique_ptr<Clock> const mClock; std::unique_ptr<VSyncTracker> const mTracker; Loading @@ -71,10 +73,12 @@ private: size_t const mPendingLimit; std::mutex mMutex; bool mIgnorePresentFences GUARDED_BY(mMutex) = false; bool mInternalIgnoreFences GUARDED_BY(mMutex) = false; bool mExternalIgnoreFences GUARDED_BY(mMutex) = false; std::vector<std::shared_ptr<FenceTime>> mUnfiredFences GUARDED_BY(mMutex); bool mMoreSamplesNeeded GUARDED_BY(mMutex) = false; bool mPeriodConfirmationInProgress GUARDED_BY(mMutex) = false; std::optional<nsecs_t> mPeriodTransitioningTo GUARDED_BY(mMutex); std::optional<nsecs_t> mLastHwVsync GUARDED_BY(mMutex); Loading services/surfaceflinger/Scheduler/VSyncTracker.h +3 −1 Original line number Diff line number Diff line Loading @@ -33,8 +33,10 @@ public: * to the model. * * \param [in] timestamp The timestamp when the vsync signal was. * \return True if the timestamp was consistent with the internal model, * False otherwise */ virtual void addVsyncTimestamp(nsecs_t timestamp) = 0; virtual bool addVsyncTimestamp(nsecs_t timestamp) = 0; /* * Access the next anticipated vsync time such that the anticipated time >= timePoint. Loading Loading
services/surfaceflinger/Scheduler/VSyncPredictor.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -71,12 +71,12 @@ nsecs_t VSyncPredictor::currentPeriod() const { return std::get<0>(mRateMap.find(mIdealPeriod)->second); } void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { std::lock_guard<std::mutex> lk(mMutex); if (!validate(timestamp)) { ALOGV("timestamp was too far off the last known timestamp"); return; return false; } if (timestamps.size() != kHistorySize) { Loading @@ -89,7 +89,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (timestamps.size() < kMinimumSamplesForPrediction) { mRateMap[mIdealPeriod] = {mIdealPeriod, 0}; return; return true; } // This is a 'simple linear regression' calculation of Y over X, with Y being the Loading Loading @@ -143,7 +143,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (CC_UNLIKELY(bottom == 0)) { it->second = {mIdealPeriod, 0}; return; return false; } nsecs_t const anticipatedPeriod = top / bottom * kScalingFactor; Loading @@ -156,6 +156,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { ALOGV("model update ts: %" PRId64 " slope: %" PRId64 " intercept: %" PRId64, timestamp, anticipatedPeriod, intercept); return true; } nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { Loading
services/surfaceflinger/Scheduler/VSyncPredictor.h +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ public: uint32_t outlierTolerancePercent); ~VSyncPredictor(); void addVsyncTimestamp(nsecs_t timestamp) final; bool addVsyncTimestamp(nsecs_t timestamp) final; nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final; nsecs_t currentPeriod() const final; void resetModel() final; Loading
services/surfaceflinger/Scheduler/VSyncReactor.cpp +43 −16 Original line number Diff line number Diff line Loading @@ -130,10 +130,11 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } std::lock_guard<std::mutex> lk(mMutex); if (mIgnorePresentFences) { if (mExternalIgnoreFences || mInternalIgnoreFences) { return true; } bool timestampAccepted = true; for (auto it = mUnfiredFences.begin(); it != mUnfiredFences.end();) { auto const time = (*it)->getCachedSignalTime(); if (time == Fence::SIGNAL_TIME_PENDING) { Loading @@ -141,7 +142,8 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } else if (time == Fence::SIGNAL_TIME_INVALID) { it = mUnfiredFences.erase(it); } else { mTracker->addVsyncTimestamp(time); timestampAccepted &= mTracker->addVsyncTimestamp(time); it = mUnfiredFences.erase(it); } } Loading @@ -152,7 +154,13 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { } mUnfiredFences.push_back(fence); } else { mTracker->addVsyncTimestamp(signalTime); timestampAccepted &= mTracker->addVsyncTimestamp(signalTime); } if (!timestampAccepted) { mMoreSamplesNeeded = true; setIgnorePresentFencesInternal(true); mPeriodConfirmationInProgress = true; } return mMoreSamplesNeeded; Loading @@ -160,8 +168,17 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) { void VSyncReactor::setIgnorePresentFences(bool ignoration) { std::lock_guard<std::mutex> lk(mMutex); mIgnorePresentFences = ignoration; if (mIgnorePresentFences == true) { mExternalIgnoreFences = ignoration; updateIgnorePresentFencesInternal(); } void VSyncReactor::setIgnorePresentFencesInternal(bool ignoration) { mInternalIgnoreFences = ignoration; updateIgnorePresentFencesInternal(); } void VSyncReactor::updateIgnorePresentFencesInternal() { if (mExternalIgnoreFences || mInternalIgnoreFences) { mUnfiredFences.clear(); } } Loading @@ -177,14 +194,18 @@ nsecs_t VSyncReactor::expectedPresentTime() { } void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) { mPeriodConfirmationInProgress = true; mPeriodTransitioningTo = newPeriod; mMoreSamplesNeeded = true; setIgnorePresentFencesInternal(true); } void VSyncReactor::endPeriodTransition() { setIgnorePresentFencesInternal(false); mMoreSamplesNeeded = false; mPeriodTransitioningTo.reset(); mPeriodConfirmationInProgress = false; mLastHwVsync.reset(); mMoreSamplesNeeded = false; } void VSyncReactor::setPeriod(nsecs_t period) { Loading @@ -208,27 +229,33 @@ void VSyncReactor::beginResync() { void VSyncReactor::endResync() {} bool VSyncReactor::periodChangeDetected(nsecs_t vsync_timestamp) { if (!mLastHwVsync || !mPeriodTransitioningTo) { bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp) { if (!mLastHwVsync || !mPeriodConfirmationInProgress) { return false; } auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : getPeriod(); static constexpr int allowancePercent = 10; static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio; auto const allowance = period * allowancePercentRatio.num / allowancePercentRatio.den; auto const distance = vsync_timestamp - *mLastHwVsync; return std::abs(distance - *mPeriodTransitioningTo) < std::abs(distance - getPeriod()); return std::abs(distance - period) < allowance; } bool VSyncReactor::addResyncSample(nsecs_t timestamp, bool* periodFlushed) { assert(periodFlushed); std::lock_guard<std::mutex> lk(mMutex); if (periodChangeDetected(timestamp)) { if (periodConfirmed(timestamp)) { if (mPeriodTransitioningTo) { mTracker->setPeriod(*mPeriodTransitioningTo); for (auto& entry : mCallbacks) { entry.second->setPeriod(*mPeriodTransitioningTo); } endPeriodTransition(); *periodFlushed = true; } else if (mPeriodTransitioningTo) { } endPeriodTransition(); } else if (mPeriodConfirmationInProgress) { mLastHwVsync = timestamp; mMoreSamplesNeeded = true; *periodFlushed = false; Loading
services/surfaceflinger/Scheduler/VSyncReactor.h +6 −2 Original line number Diff line number Diff line Loading @@ -61,9 +61,11 @@ public: void reset() final; private: void setIgnorePresentFencesInternal(bool ignoration) REQUIRES(mMutex); void updateIgnorePresentFencesInternal() REQUIRES(mMutex); void startPeriodTransition(nsecs_t newPeriod) REQUIRES(mMutex); void endPeriodTransition() REQUIRES(mMutex); bool periodChangeDetected(nsecs_t vsync_timestamp) REQUIRES(mMutex); bool periodConfirmed(nsecs_t vsync_timestamp) REQUIRES(mMutex); std::unique_ptr<Clock> const mClock; std::unique_ptr<VSyncTracker> const mTracker; Loading @@ -71,10 +73,12 @@ private: size_t const mPendingLimit; std::mutex mMutex; bool mIgnorePresentFences GUARDED_BY(mMutex) = false; bool mInternalIgnoreFences GUARDED_BY(mMutex) = false; bool mExternalIgnoreFences GUARDED_BY(mMutex) = false; std::vector<std::shared_ptr<FenceTime>> mUnfiredFences GUARDED_BY(mMutex); bool mMoreSamplesNeeded GUARDED_BY(mMutex) = false; bool mPeriodConfirmationInProgress GUARDED_BY(mMutex) = false; std::optional<nsecs_t> mPeriodTransitioningTo GUARDED_BY(mMutex); std::optional<nsecs_t> mLastHwVsync GUARDED_BY(mMutex); Loading
services/surfaceflinger/Scheduler/VSyncTracker.h +3 −1 Original line number Diff line number Diff line Loading @@ -33,8 +33,10 @@ public: * to the model. * * \param [in] timestamp The timestamp when the vsync signal was. * \return True if the timestamp was consistent with the internal model, * False otherwise */ virtual void addVsyncTimestamp(nsecs_t timestamp) = 0; virtual bool addVsyncTimestamp(nsecs_t timestamp) = 0; /* * Access the next anticipated vsync time such that the anticipated time >= timePoint. Loading