Loading services/surfaceflinger/Scheduler/VSyncPredictor.cpp +29 −10 Original line number Diff line number Diff line Loading @@ -89,7 +89,9 @@ nsecs_t VSyncPredictor::idealPeriod() const { } bool VSyncPredictor::validate(nsecs_t timestamp) const { SFTRACE_CALL(); if (mLastTimestampIndex < 0 || mTimestamps.empty()) { SFTRACE_INSTANT("timestamp valid (first)"); return true; } Loading @@ -98,7 +100,11 @@ bool VSyncPredictor::validate(nsecs_t timestamp) const { (timestamp - aValidTimestamp) % idealPeriod() * kMaxPercent / idealPeriod(); if (percent >= kOutlierTolerancePercent && percent <= (kMaxPercent - kOutlierTolerancePercent)) { SFTRACE_FORMAT_INSTANT("timestamp is not aligned with model"); SFTRACE_FORMAT_INSTANT("timestamp not aligned with model. aValidTimestamp %.2fms ago" ", timestamp %.2fms ago, idealPeriod=%.2 percent=%d", (mClock->now() - aValidTimestamp) / 1e6f, (mClock->now() - timestamp) / 1e6f, idealPeriod() / 1e6f, percent); return false; } Loading Loading @@ -148,7 +154,10 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { // Add the timestamp to mTimestamps before clearing it so we could // update mKnownTimestamp based on the new timestamp. mTimestamps.push_back(timestamp); clearTimestamps(); // Do not clear timelines as we don't want to break the phase while // we are still learning. clearTimestamps(/* clearTimelines */ false); } else if (!mTimestamps.empty()) { mKnownTimestamp = std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end())); Loading Loading @@ -235,7 +244,7 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (CC_UNLIKELY(bottom == 0)) { it->second = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); return false; } Loading @@ -245,7 +254,7 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { auto const percent = std::abs(anticipatedPeriod - idealPeriod()) * kMaxPercent / idealPeriod(); if (percent >= kOutlierTolerancePercent) { it->second = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); return false; } Loading Loading @@ -425,6 +434,9 @@ void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) { timeout ? std::to_string(timeout->timeoutNs).c_str() : "N/A"); std::lock_guard lock(mMutex); // do not clear the timelines on VRR displays if we didn't change the mode const bool isVrr = modePtr->getVrrConfig().has_value(); const bool clearTimelines = !isVrr || mDisplayModePtr->getId() != modePtr->getId(); mDisplayModePtr = modePtr; mNumVsyncsForFrame = numVsyncsPerFrame(mDisplayModePtr); traceInt64("VSP-setPeriod", modePtr->getVsyncRate().getPeriodNsecs()); Loading @@ -438,8 +450,10 @@ void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) { mRateMap[idealPeriod()] = {idealPeriod(), 0}; } if (clearTimelines) { mTimelines.clear(); clearTimestamps(); } clearTimestamps(clearTimelines); } Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime, Loading Loading @@ -556,15 +570,19 @@ VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModelLocked() const { return mRateMap.find(idealPeriod())->second; } void VSyncPredictor::clearTimestamps() { SFTRACE_CALL(); void VSyncPredictor::clearTimestamps(bool clearTimelines) { SFTRACE_FORMAT("%s: clearTimelines=%d", __func__, clearTimelines); if (!mTimestamps.empty()) { auto const maxRb = *std::max_element(mTimestamps.begin(), mTimestamps.end()); if (mKnownTimestamp) { mKnownTimestamp = std::max(*mKnownTimestamp, maxRb); SFTRACE_FORMAT_INSTANT("mKnownTimestamp was %.2fms ago", (mClock->now() - *mKnownTimestamp) / 1e6f); } else { mKnownTimestamp = maxRb; SFTRACE_FORMAT_INSTANT("mKnownTimestamp (maxRb) was %.2fms ago", (mClock->now() - *mKnownTimestamp) / 1e6f); } mTimestamps.clear(); Loading @@ -575,7 +593,7 @@ void VSyncPredictor::clearTimestamps() { if (mTimelines.empty()) { mLastCommittedVsync = TimePoint::fromNs(0); mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt); } else { } else if (clearTimelines) { while (mTimelines.size() > 1) { mTimelines.pop_front(); } Loading @@ -596,9 +614,10 @@ bool VSyncPredictor::needsMoreSamples() const { } void VSyncPredictor::resetModel() { SFTRACE_CALL(); std::lock_guard lock(mMutex); mRateMap[idealPeriod()] = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); } void VSyncPredictor::dump(std::string& result) const { Loading services/surfaceflinger/Scheduler/VSyncPredictor.h +1 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ private: VSyncPredictor(VSyncPredictor const&) = delete; VSyncPredictor& operator=(VSyncPredictor const&) = delete; void clearTimestamps() REQUIRES(mMutex); void clearTimestamps(bool clearTimelines) REQUIRES(mMutex); const std::unique_ptr<Clock> mClock; const PhysicalDisplayId mId; Loading services/surfaceflinger/Scheduler/VSyncReactor.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,9 @@ void VSyncReactor::onDisplayModeChanged(ftl::NonNull<DisplayModePtr> modePtr, bo std::lock_guard lock(mMutex); mLastHwVsync.reset(); if (!mSupportKernelIdleTimer && mTracker.isCurrentMode(modePtr) && !force) { // kernel idle timer is not applicable for VRR const bool supportKernelIdleTimer = mSupportKernelIdleTimer && !modePtr->getVrrConfig(); if (!supportKernelIdleTimer && mTracker.isCurrentMode(modePtr) && !force) { endPeriodTransition(); setIgnorePresentFencesInternal(false); mMoreSamplesNeeded = false; Loading Loading
services/surfaceflinger/Scheduler/VSyncPredictor.cpp +29 −10 Original line number Diff line number Diff line Loading @@ -89,7 +89,9 @@ nsecs_t VSyncPredictor::idealPeriod() const { } bool VSyncPredictor::validate(nsecs_t timestamp) const { SFTRACE_CALL(); if (mLastTimestampIndex < 0 || mTimestamps.empty()) { SFTRACE_INSTANT("timestamp valid (first)"); return true; } Loading @@ -98,7 +100,11 @@ bool VSyncPredictor::validate(nsecs_t timestamp) const { (timestamp - aValidTimestamp) % idealPeriod() * kMaxPercent / idealPeriod(); if (percent >= kOutlierTolerancePercent && percent <= (kMaxPercent - kOutlierTolerancePercent)) { SFTRACE_FORMAT_INSTANT("timestamp is not aligned with model"); SFTRACE_FORMAT_INSTANT("timestamp not aligned with model. aValidTimestamp %.2fms ago" ", timestamp %.2fms ago, idealPeriod=%.2 percent=%d", (mClock->now() - aValidTimestamp) / 1e6f, (mClock->now() - timestamp) / 1e6f, idealPeriod() / 1e6f, percent); return false; } Loading Loading @@ -148,7 +154,10 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { // Add the timestamp to mTimestamps before clearing it so we could // update mKnownTimestamp based on the new timestamp. mTimestamps.push_back(timestamp); clearTimestamps(); // Do not clear timelines as we don't want to break the phase while // we are still learning. clearTimestamps(/* clearTimelines */ false); } else if (!mTimestamps.empty()) { mKnownTimestamp = std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end())); Loading Loading @@ -235,7 +244,7 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (CC_UNLIKELY(bottom == 0)) { it->second = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); return false; } Loading @@ -245,7 +254,7 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { auto const percent = std::abs(anticipatedPeriod - idealPeriod()) * kMaxPercent / idealPeriod(); if (percent >= kOutlierTolerancePercent) { it->second = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); return false; } Loading Loading @@ -425,6 +434,9 @@ void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) { timeout ? std::to_string(timeout->timeoutNs).c_str() : "N/A"); std::lock_guard lock(mMutex); // do not clear the timelines on VRR displays if we didn't change the mode const bool isVrr = modePtr->getVrrConfig().has_value(); const bool clearTimelines = !isVrr || mDisplayModePtr->getId() != modePtr->getId(); mDisplayModePtr = modePtr; mNumVsyncsForFrame = numVsyncsPerFrame(mDisplayModePtr); traceInt64("VSP-setPeriod", modePtr->getVsyncRate().getPeriodNsecs()); Loading @@ -438,8 +450,10 @@ void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) { mRateMap[idealPeriod()] = {idealPeriod(), 0}; } if (clearTimelines) { mTimelines.clear(); clearTimestamps(); } clearTimestamps(clearTimelines); } Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime, Loading Loading @@ -556,15 +570,19 @@ VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModelLocked() const { return mRateMap.find(idealPeriod())->second; } void VSyncPredictor::clearTimestamps() { SFTRACE_CALL(); void VSyncPredictor::clearTimestamps(bool clearTimelines) { SFTRACE_FORMAT("%s: clearTimelines=%d", __func__, clearTimelines); if (!mTimestamps.empty()) { auto const maxRb = *std::max_element(mTimestamps.begin(), mTimestamps.end()); if (mKnownTimestamp) { mKnownTimestamp = std::max(*mKnownTimestamp, maxRb); SFTRACE_FORMAT_INSTANT("mKnownTimestamp was %.2fms ago", (mClock->now() - *mKnownTimestamp) / 1e6f); } else { mKnownTimestamp = maxRb; SFTRACE_FORMAT_INSTANT("mKnownTimestamp (maxRb) was %.2fms ago", (mClock->now() - *mKnownTimestamp) / 1e6f); } mTimestamps.clear(); Loading @@ -575,7 +593,7 @@ void VSyncPredictor::clearTimestamps() { if (mTimelines.empty()) { mLastCommittedVsync = TimePoint::fromNs(0); mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt); } else { } else if (clearTimelines) { while (mTimelines.size() > 1) { mTimelines.pop_front(); } Loading @@ -596,9 +614,10 @@ bool VSyncPredictor::needsMoreSamples() const { } void VSyncPredictor::resetModel() { SFTRACE_CALL(); std::lock_guard lock(mMutex); mRateMap[idealPeriod()] = {idealPeriod(), 0}; clearTimestamps(); clearTimestamps(/* clearTimelines */ true); } void VSyncPredictor::dump(std::string& result) const { Loading
services/surfaceflinger/Scheduler/VSyncPredictor.h +1 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ private: VSyncPredictor(VSyncPredictor const&) = delete; VSyncPredictor& operator=(VSyncPredictor const&) = delete; void clearTimestamps() REQUIRES(mMutex); void clearTimestamps(bool clearTimelines) REQUIRES(mMutex); const std::unique_ptr<Clock> mClock; const PhysicalDisplayId mId; Loading
services/surfaceflinger/Scheduler/VSyncReactor.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,9 @@ void VSyncReactor::onDisplayModeChanged(ftl::NonNull<DisplayModePtr> modePtr, bo std::lock_guard lock(mMutex); mLastHwVsync.reset(); if (!mSupportKernelIdleTimer && mTracker.isCurrentMode(modePtr) && !force) { // kernel idle timer is not applicable for VRR const bool supportKernelIdleTimer = mSupportKernelIdleTimer && !modePtr->getVrrConfig(); if (!supportKernelIdleTimer && mTracker.isCurrentMode(modePtr) && !force) { endPeriodTransition(); setIgnorePresentFencesInternal(false); mMoreSamplesNeeded = false; Loading