SF: pass DisplayMode to VsyncTracker
This will be used later to get the peak refresh rate from the predictor
for sub-frame jank recover in VRR case.
Bug: 296635687
Test: presubmit
Change-Id: I1e108223b6ae4872bb48a38e4af743da565749cd
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 6d2586a..db247aa 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -21,6 +21,7 @@
"libui",
"libutils",
],
+ static_libs: ["libsurfaceflinger_common"],
}
cc_library_headers {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b54f334..29b1d62 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -118,7 +118,7 @@
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
auto schedulePtr = std::make_shared<VsyncSchedule>(
- displayId, mFeatures,
+ selectorPtr->getActiveMode().modePtr, mFeatures,
[this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); },
mVsyncTrackerCallback);
@@ -503,7 +503,7 @@
}
void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
- std::optional<Fps> refreshRate) {
+ DisplayModePtr modePtr) {
const auto displayOpt = mDisplays.get(id);
if (!displayOpt) {
ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
@@ -512,12 +512,12 @@
const Display& display = *displayOpt;
if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) {
- if (!refreshRate) {
- refreshRate = display.selectorPtr->getActiveMode().modePtr->getVsyncRate();
+ if (!modePtr) {
+ modePtr = display.selectorPtr->getActiveMode().modePtr.get();
}
- if (refreshRate->isValid()) {
+ if (modePtr->getVsyncRate().isValid()) {
constexpr bool kForce = false;
- display.schedulePtr->startPeriodTransition(refreshRate->getPeriod(), kForce);
+ display.schedulePtr->onDisplayModeChanged(ftl::as_non_null(modePtr), kForce);
}
}
}
@@ -563,19 +563,7 @@
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
to_string(mode.modePtr->getVsyncRate()).c_str());
- display.schedulePtr->getTracker().setDisplayModeData(
- {.renderRate = renderFrameRate,
- .notifyExpectedPresentTimeoutOpt = getNotifyExpectedPresentTimeout(mode)});
-}
-
-std::optional<Period> Scheduler::getNotifyExpectedPresentTimeout(const FrameRateMode& mode) {
- if (mode.modePtr->getVrrConfig() && mode.modePtr->getVrrConfig()->notifyExpectedPresentConfig) {
- return Period::fromNs(
- mode.modePtr->getVrrConfig()
- ->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs);
- } else {
- return std::nullopt;
- }
+ display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
}
void Scheduler::resync() {
@@ -913,9 +901,9 @@
newVsyncSchedulePtr = pacesetter.schedulePtr;
- const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getVsyncRate();
constexpr bool kForce = true;
- newVsyncSchedulePtr->startPeriodTransition(refreshRate.getPeriod(), kForce);
+ newVsyncSchedulePtr->onDisplayModeChanged(pacesetter.selectorPtr->getActiveMode().modePtr,
+ kForce);
}
return newVsyncSchedulePtr;
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index c78051a..0615b31 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -210,13 +210,12 @@
// If allowToEnable is true, then hardware vsync will be turned on.
// Otherwise, if hardware vsync is not already enabled then this method will
// no-op.
- // If refreshRate is nullopt, use the existing refresh rate of the display.
+ // If modePtr is nullopt, use the active display mode.
void resyncToHardwareVsync(PhysicalDisplayId id, bool allowToEnable,
- std::optional<Fps> refreshRate = std::nullopt)
- EXCLUDES(mDisplayLock) {
+ DisplayModePtr modePtr = nullptr) EXCLUDES(mDisplayLock) {
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
- resyncToHardwareVsyncLocked(id, allowToEnable, refreshRate);
+ resyncToHardwareVsyncLocked(id, allowToEnable, modePtr);
}
void forceNextResync() { mLastResyncTime = 0; }
@@ -354,7 +353,7 @@
void onHardwareVsyncRequest(PhysicalDisplayId, bool enable);
void resyncToHardwareVsyncLocked(PhysicalDisplayId, bool allowToEnable,
- std::optional<Fps> refreshRate = std::nullopt)
+ DisplayModePtr modePtr = nullptr)
REQUIRES(kMainThreadContext, mDisplayLock);
void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock);
void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
@@ -431,9 +430,6 @@
Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
void resync() override EXCLUDES(mDisplayLock);
- std::optional<Period> getNotifyExpectedPresentTimeout(const FrameRateMode&)
- REQUIRES(mDisplayLock);
-
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index f5f93ce..acb7265 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -47,16 +47,16 @@
VSyncPredictor::~VSyncPredictor() = default;
-VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
+VSyncPredictor::VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
IVsyncTrackerCallback& callback)
- : mId(id),
+ : mId(modePtr->getPhysicalDisplayId()),
mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
kHistorySize(historySize),
kMinimumSamplesForPrediction(minimumSamplesForPrediction),
kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
mVsyncTrackerCallback(callback),
- mIdealPeriod(idealPeriod) {
+ mDisplayModePtr(modePtr) {
resetModel();
}
@@ -74,13 +74,18 @@
return (i + 1) % mTimestamps.size();
}
+nsecs_t VSyncPredictor::idealPeriod() const {
+ return mDisplayModePtr->getVsyncRate().getPeriodNsecs();
+}
+
bool VSyncPredictor::validate(nsecs_t timestamp) const {
if (mLastTimestampIndex < 0 || mTimestamps.empty()) {
return true;
}
- auto const aValidTimestamp = mTimestamps[mLastTimestampIndex];
- auto const percent = (timestamp - aValidTimestamp) % mIdealPeriod * kMaxPercent / mIdealPeriod;
+ const auto aValidTimestamp = mTimestamps[mLastTimestampIndex];
+ const auto percent =
+ (timestamp - aValidTimestamp) % idealPeriod() * kMaxPercent / idealPeriod();
if (percent >= kOutlierTolerancePercent &&
percent <= (kMaxPercent - kOutlierTolerancePercent)) {
return false;
@@ -90,7 +95,7 @@
[timestamp](nsecs_t a, nsecs_t b) {
return std::abs(timestamp - a) < std::abs(timestamp - b);
});
- const auto distancePercent = std::abs(*iter - timestamp) * kMaxPercent / mIdealPeriod;
+ const auto distancePercent = std::abs(*iter - timestamp) * kMaxPercent / idealPeriod();
if (distancePercent < kOutlierTolerancePercent) {
// duplicate timestamp
return false;
@@ -100,7 +105,7 @@
nsecs_t VSyncPredictor::currentPeriod() const {
std::lock_guard lock(mMutex);
- return mRateMap.find(mIdealPeriod)->second.slope;
+ return mRateMap.find(idealPeriod())->second.slope;
}
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
@@ -137,7 +142,7 @@
const size_t numSamples = mTimestamps.size();
if (numSamples < kMinimumSamplesForPrediction) {
- mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
+ mRateMap[idealPeriod()] = {idealPeriod(), 0};
return true;
}
@@ -161,7 +166,7 @@
// Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
- auto it = mRateMap.find(mIdealPeriod);
+ auto it = mRateMap.find(idealPeriod());
auto const currentPeriod = it->second.slope;
// The mean of the ordinals must be precise for the intercept calculation, so scale them up for
@@ -199,7 +204,7 @@
}
if (CC_UNLIKELY(bottom == 0)) {
- it->second = {mIdealPeriod, 0};
+ it->second = {idealPeriod(), 0};
clearTimestamps();
return false;
}
@@ -207,9 +212,9 @@
nsecs_t const anticipatedPeriod = top * kScalingFactor / bottom;
nsecs_t const intercept = meanTS - (anticipatedPeriod * meanOrdinal / kScalingFactor);
- auto const percent = std::abs(anticipatedPeriod - mIdealPeriod) * kMaxPercent / mIdealPeriod;
+ auto const percent = std::abs(anticipatedPeriod - idealPeriod()) * kMaxPercent / idealPeriod();
if (percent >= kOutlierTolerancePercent) {
- it->second = {mIdealPeriod, 0};
+ it->second = {idealPeriod(), 0};
clearTimestamps();
return false;
}
@@ -241,8 +246,8 @@
if (mTimestamps.empty()) {
traceInt64("VSP-mode", 1);
auto const knownTimestamp = mKnownTimestamp ? *mKnownTimestamp : timePoint;
- auto const numPeriodsOut = ((timePoint - knownTimestamp) / mIdealPeriod) + 1;
- return knownTimestamp + numPeriodsOut * mIdealPeriod;
+ auto const numPeriodsOut = ((timePoint - knownTimestamp) / idealPeriod()) + 1;
+ return knownTimestamp + numPeriodsOut * idealPeriod();
}
auto const oldest = *std::min_element(mTimestamps.begin(), mTimestamps.end());
@@ -278,11 +283,11 @@
mLastVsyncSequence = getVsyncSequenceLocked(timePoint);
const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
- if (!mDisplayModeDataOpt) return 0;
+ if (!mRenderRateOpt) return 0;
const auto divisor =
- RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod),
- mDisplayModeDataOpt->renderRate);
+ RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(idealPeriod()),
+ *mRenderRateOpt);
if (divisor <= 1) return 0;
const int mod = mLastVsyncSequence->seq % divisor;
@@ -293,12 +298,12 @@
if (renderRatePhase == 0) {
const auto vsyncTime = mLastVsyncSequence->vsyncTime;
- if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+ if (FlagManager::getInstance().vrr_config()) {
const auto vsyncTimePoint = TimePoint::fromNs(vsyncTime);
ATRACE_FORMAT("%s InPhase vsyncIn %.2fms", __func__,
ticks<std::milli, float>(vsyncTimePoint - TimePoint::now()));
- mVsyncTrackerCallback.onVsyncGenerated(mId, vsyncTimePoint, *mDisplayModeDataOpt,
- Period::fromNs(mIdealPeriod));
+ const Fps renderRate = mRenderRateOpt ? *mRenderRateOpt : mDisplayModePtr->getPeakFps();
+ mVsyncTrackerCallback.onVsyncGenerated(vsyncTimePoint, mDisplayModePtr, renderRate);
}
return vsyncTime;
}
@@ -307,12 +312,13 @@
const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
const auto nextAnticipatedVsyncTime =
nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
- if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+ if (FlagManager::getInstance().vrr_config()) {
const auto nextAnticipatedVsyncTimePoint = TimePoint::fromNs(nextAnticipatedVsyncTime);
ATRACE_FORMAT("%s outOfPhase vsyncIn %.2fms", __func__,
ticks<std::milli, float>(nextAnticipatedVsyncTimePoint - TimePoint::now()));
- mVsyncTrackerCallback.onVsyncGenerated(mId, nextAnticipatedVsyncTimePoint,
- *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod));
+ const Fps renderRate = mRenderRateOpt ? *mRenderRateOpt : mDisplayModePtr->getPeakFps();
+ mVsyncTrackerCallback.onVsyncGenerated(nextAnticipatedVsyncTimePoint, mDisplayModePtr,
+ renderRate);
}
return nextAnticipatedVsyncTime;
}
@@ -328,7 +334,8 @@
bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const {
std::lock_guard lock(mMutex);
const auto divisor =
- RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod), frameRate);
+ RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(idealPeriod()),
+ frameRate);
return isVSyncInPhaseLocked(timePoint, static_cast<unsigned>(divisor));
}
@@ -344,7 +351,7 @@
return true;
}
- const nsecs_t period = mRateMap[mIdealPeriod].slope;
+ const nsecs_t period = mRateMap[idealPeriod()].slope;
const nsecs_t justBeforeTimePoint = timePoint - period / 2;
const auto vsyncSequence = getVsyncSequenceLocked(justBeforeTimePoint);
ATRACE_FORMAT_INSTANT("vsync in: %.2f sequence: %" PRId64,
@@ -352,14 +359,38 @@
return vsyncSequence.seq % divisor == 0;
}
-void VSyncPredictor::setDisplayModeData(const DisplayModeData& displayModeData) {
- ALOGV("%s %s: RenderRate %s notifyExpectedPresentTimeout %s", __func__, to_string(mId).c_str(),
- to_string(displayModeData.renderRate).c_str(),
- displayModeData.notifyExpectedPresentTimeoutOpt
- ? std::to_string(displayModeData.notifyExpectedPresentTimeoutOpt->ns()).c_str()
- : "N/A");
+void VSyncPredictor::setRenderRate(Fps renderRate) {
+ ATRACE_FORMAT("%s %s", __func__, to_string(renderRate).c_str());
+ ALOGV("%s %s: RenderRate %s ", __func__, to_string(mId).c_str(), to_string(renderRate).c_str());
std::lock_guard lock(mMutex);
- mDisplayModeDataOpt = displayModeData;
+ mRenderRateOpt = renderRate;
+}
+
+void VSyncPredictor::setDisplayModePtr(ftl::NonNull<DisplayModePtr> modePtr) {
+ LOG_ALWAYS_FATAL_IF(mId != modePtr->getPhysicalDisplayId(),
+ "mode does not belong to the display");
+ ATRACE_FORMAT("%s %s", __func__, to_string(*modePtr).c_str());
+ const auto timeout = modePtr->getVrrConfig()
+ ? modePtr->getVrrConfig()->notifyExpectedPresentConfig
+ : std::nullopt;
+ ALOGV("%s %s: DisplayMode %s notifyExpectedPresentTimeout %s", __func__, to_string(mId).c_str(),
+ to_string(*modePtr).c_str(),
+ timeout ? std::to_string(timeout->notifyExpectedPresentTimeoutNs).c_str() : "N/A");
+ std::lock_guard lock(mMutex);
+
+ mDisplayModePtr = modePtr;
+ traceInt64("VSP-setPeriod", modePtr->getVsyncRate().getPeriodNsecs());
+
+ static constexpr size_t kSizeLimit = 30;
+ if (CC_UNLIKELY(mRateMap.size() == kSizeLimit)) {
+ mRateMap.erase(mRateMap.begin());
+ }
+
+ if (mRateMap.find(idealPeriod()) == mRateMap.end()) {
+ mRateMap[idealPeriod()] = {idealPeriod(), 0};
+ }
+
+ clearTimestamps();
}
VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const {
@@ -369,26 +400,7 @@
}
VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModelLocked() const {
- return mRateMap.find(mIdealPeriod)->second;
-}
-
-void VSyncPredictor::setPeriod(nsecs_t period) {
- ATRACE_FORMAT("%s %s", __func__, to_string(mId).c_str());
- traceInt64("VSP-setPeriod", period);
-
- std::lock_guard lock(mMutex);
- static constexpr size_t kSizeLimit = 30;
- if (CC_UNLIKELY(mRateMap.size() == kSizeLimit)) {
- mRateMap.erase(mRateMap.begin());
- }
-
- // TODO(b/308610306) mIdealPeriod to be updated with setDisplayModeData
- mIdealPeriod = period;
- if (mRateMap.find(period) == mRateMap.end()) {
- mRateMap[mIdealPeriod] = {period, 0};
- }
-
- clearTimestamps();
+ return mRateMap.find(idealPeriod())->second;
}
void VSyncPredictor::clearTimestamps() {
@@ -412,18 +424,18 @@
void VSyncPredictor::resetModel() {
std::lock_guard lock(mMutex);
- mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
+ mRateMap[idealPeriod()] = {idealPeriod(), 0};
clearTimestamps();
}
void VSyncPredictor::dump(std::string& result) const {
std::lock_guard lock(mMutex);
- StringAppendF(&result, "\tmIdealPeriod=%.2f\n", mIdealPeriod / 1e6f);
+ StringAppendF(&result, "\tmDisplayModePtr=%s\n", to_string(*mDisplayModePtr).c_str());
StringAppendF(&result, "\tRefresh Rate Map:\n");
- for (const auto& [idealPeriod, periodInterceptTuple] : mRateMap) {
+ for (const auto& [period, periodInterceptTuple] : mRateMap) {
StringAppendF(&result,
"\t\tFor ideal period %.2fms: period = %.2fms, intercept = %" PRId64 "\n",
- idealPeriod / 1e6f, periodInterceptTuple.slope / 1e6f,
+ period / 1e6f, periodInterceptTuple.slope / 1e6f,
periodInterceptTuple.intercept);
}
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index c271eb7..fbc1e16 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -31,14 +31,14 @@
public:
/*
* \param [in] PhysicalDisplayid The display this corresponds to.
- * \param [in] idealPeriod The initial ideal period to use.
+ * \param [in] modePtr The initial display mode
* \param [in] historySize The internal amount of entries to store in the model.
* \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
* predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
* samples that fall outlierTolerancePercent from an anticipated vsync event.
* \param [in] IVsyncTrackerCallback The callback for the VSyncTracker.
*/
- VSyncPredictor(PhysicalDisplayId, nsecs_t idealPeriod, size_t historySize,
+ VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
IVsyncTrackerCallback&);
~VSyncPredictor();
@@ -48,15 +48,6 @@
nsecs_t currentPeriod() const final EXCLUDES(mMutex);
void resetModel() final EXCLUDES(mMutex);
- /*
- * Inform the model that the period is anticipated to change to a new value.
- * model will use the period parameter to predict vsync events until enough
- * timestamps with the new period have been collected.
- *
- * \param [in] period The new period that should be used.
- */
- void setPeriod(nsecs_t period) final EXCLUDES(mMutex);
-
/* Query if the model is in need of more samples to make a prediction.
* \return True, if model would benefit from more samples, False if not.
*/
@@ -71,7 +62,9 @@
bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);
- void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex);
+ void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final EXCLUDES(mMutex);
+
+ void setRenderRate(Fps) final EXCLUDES(mMutex);
void dump(std::string& result) const final EXCLUDES(mMutex);
@@ -96,6 +89,7 @@
int64_t seq;
};
VsyncSequence getVsyncSequenceLocked(nsecs_t timestamp) const REQUIRES(mMutex);
+ nsecs_t idealPeriod() const REQUIRES(mMutex);
bool const mTraceOn;
size_t const kHistorySize;
@@ -104,7 +98,6 @@
IVsyncTrackerCallback& mVsyncTrackerCallback;
std::mutex mutable mMutex;
- nsecs_t mIdealPeriod GUARDED_BY(mMutex);
std::optional<nsecs_t> mKnownTimestamp GUARDED_BY(mMutex);
// Map between ideal vsync period and the calculated model
@@ -113,7 +106,8 @@
size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
- std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex);
+ ftl::NonNull<DisplayModePtr> mDisplayModePtr GUARDED_BY(mMutex);
+ std::optional<Fps> mRenderRateOpt GUARDED_BY(mMutex);
mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex);
};
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 2938aa3..24737e4 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -116,32 +116,34 @@
}
}
-void VSyncReactor::startPeriodTransitionInternal(nsecs_t newPeriod) {
+void VSyncReactor::startPeriodTransitionInternal(ftl::NonNull<DisplayModePtr> modePtr) {
ATRACE_FORMAT("%s %" PRIu64, __func__, mId.value);
mPeriodConfirmationInProgress = true;
- mPeriodTransitioningTo = newPeriod;
+ mModePtrTransitioningTo = modePtr.get();
mMoreSamplesNeeded = true;
setIgnorePresentFencesInternal(true);
}
void VSyncReactor::endPeriodTransition() {
ATRACE_FORMAT("%s %" PRIu64, __func__, mId.value);
- mPeriodTransitioningTo.reset();
+ mModePtrTransitioningTo.reset();
mPeriodConfirmationInProgress = false;
mLastHwVsync.reset();
}
-void VSyncReactor::startPeriodTransition(nsecs_t period, bool force) {
- ATRACE_INT64(ftl::Concat("VSR-", __func__, " ", mId.value).c_str(), period);
+void VSyncReactor::onDisplayModeChanged(ftl::NonNull<DisplayModePtr> modePtr, bool force) {
+ ATRACE_INT64(ftl::Concat("VSR-", __func__, " ", mId.value).c_str(),
+ modePtr->getVsyncRate().getPeriodNsecs());
std::lock_guard lock(mMutex);
mLastHwVsync.reset();
- if (!mSupportKernelIdleTimer && period == mTracker.currentPeriod() && !force) {
+ if (!mSupportKernelIdleTimer &&
+ modePtr->getVsyncRate().getPeriodNsecs() == mTracker.currentPeriod() && !force) {
endPeriodTransition();
setIgnorePresentFencesInternal(false);
mMoreSamplesNeeded = false;
} else {
- startPeriodTransitionInternal(period);
+ startPeriodTransitionInternal(modePtr);
}
}
@@ -159,14 +161,16 @@
return false;
}
- const bool periodIsChanging =
- mPeriodTransitioningTo && (*mPeriodTransitioningTo != mTracker.currentPeriod());
+ const std::optional<Period> newPeriod = mModePtrTransitioningTo
+ ? mModePtrTransitioningTo->getVsyncRate().getPeriod()
+ : std::optional<Period>{};
+ const bool periodIsChanging = newPeriod && (newPeriod->ns() != mTracker.currentPeriod());
if (mSupportKernelIdleTimer && !periodIsChanging) {
// Clear out the Composer-provided period and use the allowance logic below
HwcVsyncPeriod = {};
}
- auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : mTracker.currentPeriod();
+ auto const period = newPeriod ? newPeriod->ns() : mTracker.currentPeriod();
static constexpr int allowancePercent = 10;
static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio;
auto const allowance = period * allowancePercentRatio.num / allowancePercentRatio.den;
@@ -185,8 +189,8 @@
std::lock_guard lock(mMutex);
if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
ATRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value);
- if (mPeriodTransitioningTo) {
- mTracker.setPeriod(*mPeriodTransitioningTo);
+ if (mModePtrTransitioningTo) {
+ mTracker.setDisplayModePtr(ftl::as_non_null(mModePtrTransitioningTo));
*periodFlushed = true;
}
@@ -228,10 +232,11 @@
mInternalIgnoreFences, mExternalIgnoreFences);
StringAppendF(&result, "mMoreSamplesNeeded=%d mPeriodConfirmationInProgress=%d\n",
mMoreSamplesNeeded, mPeriodConfirmationInProgress);
- if (mPeriodTransitioningTo) {
- StringAppendF(&result, "mPeriodTransitioningTo=%" PRId64 "\n", *mPeriodTransitioningTo);
+ if (mModePtrTransitioningTo) {
+ StringAppendF(&result, "mModePtrTransitioningTo=%s\n",
+ to_string(*mModePtrTransitioningTo).c_str());
} else {
- StringAppendF(&result, "mPeriodTransitioningTo=nullptr\n");
+ StringAppendF(&result, "mModePtrTransitioningTo=nullptr\n");
}
if (mLastHwVsync) {
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h
index f230242..2415a66 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.h
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.h
@@ -27,6 +27,7 @@
#include <scheduler/TimeKeeper.h>
+#include "VSyncTracker.h"
#include "VsyncController.h"
namespace android::scheduler {
@@ -45,7 +46,7 @@
bool addPresentFence(std::shared_ptr<FenceTime>) final;
void setIgnorePresentFences(bool ignore) final;
- void startPeriodTransition(nsecs_t period, bool force) final;
+ void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force) final;
bool addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
bool* periodFlushed) final;
@@ -57,7 +58,7 @@
private:
void setIgnorePresentFencesInternal(bool ignore) REQUIRES(mMutex);
void updateIgnorePresentFencesInternal() REQUIRES(mMutex);
- void startPeriodTransitionInternal(nsecs_t newPeriod) REQUIRES(mMutex);
+ void startPeriodTransitionInternal(ftl::NonNull<DisplayModePtr>) REQUIRES(mMutex);
void endPeriodTransition() REQUIRES(mMutex);
bool periodConfirmed(nsecs_t vsync_timestamp, std::optional<nsecs_t> hwcVsyncPeriod)
REQUIRES(mMutex);
@@ -74,7 +75,7 @@
bool mMoreSamplesNeeded GUARDED_BY(mMutex) = false;
bool mPeriodConfirmationInProgress GUARDED_BY(mMutex) = false;
- std::optional<nsecs_t> mPeriodTransitioningTo GUARDED_BY(mMutex);
+ DisplayModePtr mModePtrTransitioningTo GUARDED_BY(mMutex);
std::optional<nsecs_t> mLastHwVsync GUARDED_BY(mMutex);
hal::PowerMode mDisplayPowerMode GUARDED_BY(mMutex) = hal::PowerMode::ON;
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 7eedc31..2ae5c0b 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -20,25 +20,16 @@
#include <utils/Timers.h>
#include <scheduler/Fps.h>
+#include <scheduler/FrameRateMode.h>
#include "VSyncDispatch.h"
namespace android::scheduler {
-struct DisplayModeData {
- Fps renderRate;
- std::optional<Period> notifyExpectedPresentTimeoutOpt;
-
- bool operator==(const DisplayModeData& other) const {
- return isApproxEqual(renderRate, other.renderRate) &&
- notifyExpectedPresentTimeoutOpt == other.notifyExpectedPresentTimeoutOpt;
- }
-};
-
struct IVsyncTrackerCallback {
virtual ~IVsyncTrackerCallback() = default;
- virtual void onVsyncGenerated(PhysicalDisplayId, TimePoint expectedPresentTime,
- const DisplayModeData&, Period vsyncPeriod) = 0;
+ virtual void onVsyncGenerated(TimePoint expectedPresentTime, ftl::NonNull<DisplayModePtr>,
+ Fps renderRate) = 0;
};
/*
@@ -77,13 +68,6 @@
*/
virtual nsecs_t currentPeriod() const = 0;
- /*
- * Inform the tracker that the period is changing and the tracker needs to recalibrate itself.
- *
- * \param [in] period The period that the system is changing into.
- */
- virtual void setPeriod(nsecs_t period) = 0;
-
/* Inform the tracker that the samples it has are not accurate for prediction. */
virtual void resetModel() = 0;
@@ -98,20 +82,25 @@
virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 0;
/*
- * Sets the metadata about the currently active display mode such as VRR
- * timeout period, vsyncPeriod and framework property such as render rate.
- * If the render rate is not a divisor of the period, the render rate is
- * ignored until the period changes.
+ * Sets the active mode of the display which includes the vsync period and other VRR attributes.
+ * This will inform the tracker that the period is changing and the tracker needs to recalibrate
+ * itself.
+ *
+ * \param [in] DisplayModePtr The display mode the tracker will use.
+ */
+ virtual void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) = 0;
+
+ /*
+ * Sets a render rate on the tracker. If the render rate is not a divisor
+ * of the period, the render rate is ignored until the period changes.
* The tracker will continue to track the vsync timeline and expect it
* to match the current period, however, nextAnticipatedVSyncTimeFrom will
* return vsyncs according to the render rate set. Setting a render rate is useful
* when a display is running at 120Hz but the render frame rate is 60Hz.
- * When IVsyncTrackerCallback::onVsyncGenerated callback is made we will pass along
- * the vsyncPeriod, render rate and timeoutNs.
*
- * \param [in] DisplayModeData The DisplayModeData the tracker will use.
+ * \param [in] Fps The render rate the tracker should operate at.
*/
- virtual void setDisplayModeData(const DisplayModeData&) = 0;
+ virtual void setRenderRate(Fps) = 0;
virtual void dump(std::string& result) const = 0;
diff --git a/services/surfaceflinger/Scheduler/VsyncController.h b/services/surfaceflinger/Scheduler/VsyncController.h
index 9177899..807a7fb 100644
--- a/services/surfaceflinger/Scheduler/VsyncController.h
+++ b/services/surfaceflinger/Scheduler/VsyncController.h
@@ -22,6 +22,7 @@
#include <DisplayHardware/HWComposer.h>
#include <DisplayHardware/Hal.h>
+#include <scheduler/FrameRateMode.h>
#include <ui/FenceTime.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
@@ -59,13 +60,14 @@
bool* periodFlushed) = 0;
/*
- * Inform the controller that the period is changing and the controller needs to recalibrate
- * itself. The controller will end the period transition internally.
+ * Inform the controller that the display mode is changing and the controller needs to
+ * recalibrate itself to the new vsync period. The controller will end the period transition
+ * internally.
*
- * \param [in] period The period that the system is changing into.
+ * \param [in] DisplayModePtr The new mode the display is changing to.
* \param [in] force True to recalibrate even if period matches the existing period.
*/
- virtual void startPeriodTransition(nsecs_t period, bool force) = 0;
+ virtual void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force) = 0;
/*
* Tells the tracker to stop using present fences to get a vsync signal.
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index 5fb53f9..4a8aac6 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -16,6 +16,8 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <common/FlagManager.h>
+
#include <ftl/fake_guard.h>
#include <scheduler/Fps.h>
#include <scheduler/Timer.h>
@@ -53,14 +55,14 @@
VSyncCallbackRegistration mRegistration;
};
-VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
+VsyncSchedule::VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags features,
RequestHardwareVsync requestHardwareVsync,
IVsyncTrackerCallback& callback)
- : mId(id),
+ : mId(modePtr->getPhysicalDisplayId()),
mRequestHardwareVsync(std::move(requestHardwareVsync)),
- mTracker(createTracker(id, callback)),
+ mTracker(createTracker(modePtr, callback)),
mDispatch(createDispatch(mTracker)),
- mController(createController(id, *mTracker, features)),
+ mController(createController(modePtr->getPhysicalDisplayId(), *mTracker, features)),
mTracer(features.test(Feature::kTracePredictedVsync)
? std::make_unique<PredictedVsyncTracer>(mDispatch)
: nullptr) {}
@@ -101,17 +103,15 @@
mDispatch->dump(out);
}
-VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id,
+VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(ftl::NonNull<DisplayModePtr> modePtr,
IVsyncTrackerCallback& callback) {
// TODO(b/144707443): Tune constants.
- constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
constexpr size_t kHistorySize = 20;
constexpr size_t kMinSamplesForPrediction = 6;
constexpr uint32_t kDiscardOutlierPercent = 20;
- return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
- kMinSamplesForPrediction, kDiscardOutlierPercent,
- callback);
+ return std::make_unique<VSyncPredictor>(modePtr, kHistorySize, kMinSamplesForPrediction,
+ kDiscardOutlierPercent, callback);
}
VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
@@ -140,9 +140,9 @@
return reactor;
}
-void VsyncSchedule::startPeriodTransition(Period period, bool force) {
+void VsyncSchedule::onDisplayModeChanged(ftl::NonNull<DisplayModePtr> modePtr, bool force) {
std::lock_guard<std::mutex> lock(mHwVsyncLock);
- mController->startPeriodTransition(period.ns(), force);
+ mController->onDisplayModeChanged(modePtr, force);
enableHardwareVsyncLocked();
}
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index ca61f87..60c4105 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -57,21 +57,22 @@
public:
using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
- VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync, IVsyncTrackerCallback&);
+ VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync,
+ IVsyncTrackerCallback&);
~VsyncSchedule();
// IVsyncSource overrides:
Period period() const override;
TimePoint vsyncDeadlineAfter(TimePoint) const override;
- // Inform the schedule that the period is changing and the schedule needs to recalibrate
- // itself. The schedule will end the period transition internally. This will
- // enable hardware VSYNCs in order to calibrate.
+ // Inform the schedule that the display mode changed the schedule needs to recalibrate
+ // itself to the new vsync period. The schedule will end the period transition internally.
+ // This will enable hardware VSYNCs in order to calibrate.
//
- // \param [in] period The period that the system is changing into.
+ // \param [in] DisplayModePtr The mode that the display is changing to.
// \param [in] force True to force a transition even if it is not a
// change.
- void startPeriodTransition(Period period, bool force);
+ void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force);
// Pass a VSYNC sample to VsyncController. Return true if
// VsyncController detected that the VSYNC period changed. Enable or disable
@@ -125,7 +126,7 @@
friend class android::VsyncScheduleTest;
friend class android::fuzz::SchedulerFuzzer;
- static TrackerPtr createTracker(PhysicalDisplayId, IVsyncTrackerCallback&);
+ static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr, IVsyncTrackerCallback&);
static DispatchPtr createDispatch(TrackerPtr);
static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);