Moving DispSync into Scheduler.
This change is part of go/surface-flinger-scheduler.
Test: SF tests pass.
Change-Id: I073a54c2111fa3146af3eb68f3294c3c5c95543c
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 23281c2..f0723e8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -584,15 +584,14 @@
// start the EventThread
if (mUseScheduler) {
- mScheduler = std::make_unique<Scheduler>();
+ mScheduler = std::make_unique<Scheduler>(
+ [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
mAppConnectionHandle =
- mScheduler->createConnection("appConnection", mPrimaryDispSync.get(),
- SurfaceFlinger::vsyncPhaseOffsetNs,
+ mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
[this] { resyncWithRateLimit(); },
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
- mScheduler->createConnection("sfConnection", mPrimaryDispSync.get(),
- SurfaceFlinger::sfVsyncPhaseOffsetNs,
+ mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
[this] { resyncWithRateLimit(); },
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
@@ -912,10 +911,13 @@
return BAD_VALUE;
}
- // FIXME for now we always return stats for the primary display
- memset(stats, 0, sizeof(*stats));
- stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
- stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+ // FIXME for now we always return stats for the primary display.
+ if (mUseScheduler) {
+ mScheduler->getDisplayStatInfo(stats);
+ } else {
+ stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+ stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+ }
return NO_ERROR;
}
@@ -1246,13 +1248,17 @@
const auto activeConfig = getHwComposer().getActiveConfig(displayId);
const nsecs_t period = activeConfig->getVsyncPeriod();
- mPrimaryDispSync->reset();
- mPrimaryDispSync->setPeriod(period);
+ if (mUseScheduler) {
+ mScheduler->setVsyncPeriod(period);
+ } else {
+ mPrimaryDispSync->reset();
+ mPrimaryDispSync->setPeriod(period);
- if (!mPrimaryHWVsyncEnabled) {
- mPrimaryDispSync->beginResync();
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
+ if (!mPrimaryHWVsyncEnabled) {
+ mPrimaryDispSync->beginResync();
+ mEventControlThread->setVsyncEnabled(true);
+ mPrimaryHWVsyncEnabled = true;
+ }
}
}
@@ -1300,19 +1306,22 @@
return;
}
- bool needsHwVsync = false;
-
- { // Scope for the lock
- Mutex::Autolock _l(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
- }
- }
-
- if (needsHwVsync) {
- enableHardwareVsync();
+ if (mUseScheduler) {
+ mScheduler->addResyncSample(timestamp);
} else {
- disableHardwareVsync(false);
+ bool needsHwVsync = false;
+ { // Scope for the lock
+ Mutex::Autolock _l(mHWVsyncLock);
+ if (mPrimaryHWVsyncEnabled) {
+ needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+ }
+ }
+
+ if (needsHwVsync) {
+ enableHardwareVsync();
+ } else {
+ disableHardwareVsync(false);
+ }
}
}
@@ -1364,7 +1373,11 @@
// Note: it is assumed the caller holds |mStateLock| when this is called
void SurfaceFlinger::resetDisplayState() {
- disableHardwareVsync(true);
+ if (mUseScheduler) {
+ mScheduler->disableHardwareVsync(true);
+ } else {
+ disableHardwareVsync(true);
+ }
// Clear the drawing state so that the logic inside of
// handleTransactionLocked will fire. It will determine the delta between
// mCurrentState and mDrawingState and re-apply all changes when we make the
@@ -1432,12 +1445,17 @@
// The present fences returned from vr_hwc are not an accurate
// representation of vsync times.
- mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
- !hasSyncFramework);
+ if (mUseScheduler) {
+ mScheduler->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() || !hasSyncFramework);
+ } else {
+ mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
+ !hasSyncFramework);
+ }
// Use phase of 0 since phase is not known.
// Use latency of 0, which will snap to the ideal latency.
- setCompositorTimingSnapped(0, period, 0);
+ DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+ setCompositorTimingSnapped(stats, 0);
resyncToHardwareVsync(false);
@@ -1736,9 +1754,8 @@
}
}
-void SurfaceFlinger::updateCompositorTiming(
- nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
- std::shared_ptr<FenceTime>& presentFenceTime) {
+void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
+ std::shared_ptr<FenceTime>& presentFenceTime) {
// Update queue of past composite+present times and determine the
// most recently known composite to present latency.
getBE().mCompositePresentTimes.push({compositeTime, presentFenceTime});
@@ -1760,21 +1777,20 @@
getBE().mCompositePresentTimes.pop();
}
- setCompositorTimingSnapped(
- vsyncPhase, vsyncInterval, compositeToPresentLatency);
+ setCompositorTimingSnapped(stats, compositeToPresentLatency);
}
-void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
- nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
+void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats,
+ nsecs_t compositeToPresentLatency) {
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
- (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
- ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+ nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0)
+ ? (stats.vsyncPeriod - (sfVsyncPhaseOffsetNs % stats.vsyncPeriod))
+ : ((-sfVsyncPhaseOffsetNs) % stats.vsyncPeriod);
// Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
if (idealLatency <= 0) {
- idealLatency = vsyncInterval;
+ idealLatency = stats.vsyncPeriod;
}
// Snap the latency to a value that removes scheduling jitter from the
@@ -1783,15 +1799,14 @@
// something (such as user input) to an accurate diasplay time.
// Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
// with (presentLatency % interval).
- nsecs_t bias = vsyncInterval / 2;
- int64_t extraVsyncs =
- (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
- nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
- idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
+ nsecs_t bias = stats.vsyncPeriod / 2;
+ int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
+ nsecs_t snappedCompositeToPresentLatency =
+ (extraVsyncs > 0) ? idealLatency + (extraVsyncs * stats.vsyncPeriod) : idealLatency;
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
- getBE().mCompositorTiming.deadline = vsyncPhase - idealLatency;
- getBE().mCompositorTiming.interval = vsyncInterval;
+ getBE().mCompositorTiming.deadline = stats.vsyncTime - idealLatency;
+ getBE().mCompositorTiming.interval = stats.vsyncPeriod;
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
@@ -1825,14 +1840,18 @@
auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
getBE().mDisplayTimeline.push(presentFenceTime);
- nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
- nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();
+ DisplayStatInfo stats;
+ if (mUseScheduler) {
+ mScheduler->getDisplayStatInfo(&stats);
+ } else {
+ stats.vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+ stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
+ }
// We use the mRefreshStartTime which might be sampled a little later than
// when we started doing work for this frame, but that should be okay
// since updateCompositorTiming has snapping logic.
- updateCompositorTiming(
- vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
+ updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
CompositorTiming compositorTiming;
{
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -1849,16 +1868,24 @@
});
if (presentFenceTime->isValid()) {
- if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
- enableHardwareVsync();
+ if (mUseScheduler) {
+ mScheduler->addPresentFence(presentFenceTime);
} else {
- disableHardwareVsync(false);
+ if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
+ enableHardwareVsync();
+ } else {
+ disableHardwareVsync(false);
+ }
}
}
if (!hasSyncFramework) {
if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) {
- enableHardwareVsync();
+ if (mUseScheduler) {
+ mScheduler->enableHardwareVsync();
+ } else {
+ enableHardwareVsync();
+ }
}
}
@@ -1892,7 +1919,7 @@
mHasPoweredOff = false;
} else {
nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
- size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval);
+ size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
getBE().mFrameBuckets[numPeriods] += elapsedTime;
} else {
@@ -3991,7 +4018,8 @@
// Use phase of 0 since phase is not known.
// Use latency of 0, which will snap to the ideal latency.
- setCompositorTimingSnapped(0, period, 0);
+ DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+ setCompositorTimingSnapped(stats, 0);
}
void SurfaceFlinger::initializeDisplays() {
@@ -4057,8 +4085,11 @@
}
if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
- disableHardwareVsync(true); // also cancels any in-progress resync
-
+ if (mUseScheduler) {
+ mScheduler->disableHardwareVsync(true);
+ } else {
+ disableHardwareVsync(true); // also cancels any in-progress resync
+ }
// FIXME: eventthread only knows about the main display right now
if (mUseScheduler) {
mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -4086,7 +4117,11 @@
} else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
// Leave display going to doze
if (display->isPrimary()) {
- disableHardwareVsync(true); // also cancels any in-progress resync
+ if (mUseScheduler) {
+ mScheduler->disableHardwareVsync(true);
+ } else {
+ disableHardwareVsync(true); // also cancels any in-progress resync
+ }
// FIXME: eventthread only knows about the main display right now
if (mUseScheduler) {
mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -5033,6 +5068,7 @@
// Needs to be shifted to proper binder interface when we productize
case 1016: {
n = data.readInt32();
+ // TODO(b/113612090): Evaluate if this can be removed.
mPrimaryDispSync->setRefreshSkipCount(n);
return NO_ERROR;
}
@@ -5161,9 +5197,17 @@
}
if ((frequencyScaler.multiplier == 1) && (frequencyScaler.divisor == 1)) {
- enableHardwareVsync();
+ if (mUseScheduler) {
+ mScheduler->enableHardwareVsync();
+ } else {
+ enableHardwareVsync();
+ }
} else {
- disableHardwareVsync(true);
+ if (mUseScheduler) {
+ mScheduler->disableHardwareVsync(true);
+ } else {
+ disableHardwareVsync(true);
+ }
}
mPrimaryDispSync->scalePeriod(frequencyScaler);
getBE().mHwc->setDisplayFrequencyScaleParameters(frequencyScaler);