Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1af0fb6e authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Rename "leader" display to "pacesetter"

"Leader" became ambiguous once we began to consider that there are two
orthogonal concepts that "leader" seems to imply:
- The display with the highest refresh rate (originally called "leader")
- The display that is refreshed first in a given update (assuming it's
  being updated)

To better distinguish between the two, we've come up with new names:
- pacesetter
- front runner (for the second concept)

Change uses of "leader" to "pacesetter" throughout SF and Scheduler.

Bug: 255635821
Bug: 256196556
Test: m
Change-Id: Ia02c35dd442d310695f1ce873fbaf30910c12419
parent 5b6ca88e
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -510,21 +510,21 @@ void DisplayDevice::clearDesiredActiveModeState() {
    mDesiredActiveModeChanged = false;
}

void DisplayDevice::adjustRefreshRate(Fps leaderDisplayRefreshRate) {
void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
    using fps_approx_ops::operator==;
    if (mRequestedRefreshRate == 0_Hz) {
        return;
    }

    using fps_approx_ops::operator>;
    if (mRequestedRefreshRate > leaderDisplayRefreshRate) {
        mAdjustedRefreshRate = leaderDisplayRefreshRate;
    if (mRequestedRefreshRate > pacesetterDisplayRefreshRate) {
        mAdjustedRefreshRate = pacesetterDisplayRefreshRate;
        return;
    }

    unsigned divisor = static_cast<unsigned>(
            std::round(leaderDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
    mAdjustedRefreshRate = leaderDisplayRefreshRate / divisor;
            std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
    mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor;
}

std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);
+3 −3
Original line number Diff line number Diff line
@@ -247,9 +247,9 @@ public:

    Fps getAdjustedRefreshRate() const { return mAdjustedRefreshRate; }

    // Round the requested refresh rate to match a divisor of the leader
    // Round the requested refresh rate to match a divisor of the pacesetter
    // display's refresh rate. Only supported for virtual displays.
    void adjustRefreshRate(Fps leaderDisplayRefreshRate);
    void adjustRefreshRate(Fps pacesetterDisplayRefreshRate);

    // release HWC resources (if any) for removable displays
    void disconnect();
@@ -290,7 +290,7 @@ private:
    // for virtual displays to match this requested refresh rate.
    const Fps mRequestedRefreshRate;

    // Adjusted refresh rate, rounded to match a divisor of the leader
    // Adjusted refresh rate, rounded to match a divisor of the pacesetter
    // display's refresh rate. Only supported for virtual displays.
    Fps mAdjustedRefreshRate = 0_Hz;

+2 −1
Original line number Diff line number Diff line
@@ -196,7 +196,8 @@ Layer::Layer(const LayerCreationArgs& args)
        mDrawingState.color.b = -1.0_hf;
    }

    mFrameTracker.setDisplayRefreshPeriod(args.flinger->mScheduler->getLeaderVsyncPeriod().ns());
    mFrameTracker.setDisplayRefreshPeriod(
            args.flinger->mScheduler->getPacesetterVsyncPeriod().ns());

    mOwnerUid = args.ownerUid;
    mOwnerPid = args.ownerPid;
+49 −48
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ Scheduler::~Scheduler() {
    mTouchTimer.reset();

    // Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler.
    demoteLeaderDisplay();
    demotePacesetterDisplay();
}

void Scheduler::startTimers() {
@@ -106,11 +106,11 @@ void Scheduler::startTimers() {
    }
}

void Scheduler::setLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) {
    demoteLeaderDisplay();
void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) {
    demotePacesetterDisplay();

    std::scoped_lock lock(mDisplayLock);
    promoteLeaderDisplay(leaderIdOpt);
    promotePacesetterDisplay(pacesetterIdOpt);
}

void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
@@ -121,17 +121,17 @@ void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelector
void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
                                        RefreshRateSelectorPtr selectorPtr,
                                        std::shared_ptr<VsyncSchedule> vsyncSchedule) {
    demoteLeaderDisplay();
    demotePacesetterDisplay();

    std::scoped_lock lock(mDisplayLock);
    mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
    mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule));

    promoteLeaderDisplay();
    promotePacesetterDisplay();
}

void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
    demoteLeaderDisplay();
    demotePacesetterDisplay();

    std::scoped_lock lock(mDisplayLock);
    mRefreshRateSelectors.erase(displayId);
@@ -142,7 +142,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
    // headless virtual display.)
    LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!");

    promoteLeaderDisplay();
    promotePacesetterDisplay();
}

void Scheduler::run() {
@@ -165,7 +165,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,

std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
    const bool supportsFrameRateOverrideByContent =
            leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();
            pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent();
    return mFrameRateOverrideMappings
            .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
}
@@ -192,7 +192,7 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback()

impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
    return [this](uid_t uid) {
        const Fps refreshRate = leaderSelectorPtr()->getActiveMode().fps;
        const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().fps;
        const nsecs_t currentPeriod =
                getVsyncSchedule()->period().ns() ?: refreshRate.getPeriodNsecs();

@@ -285,7 +285,7 @@ void Scheduler::enableSyntheticVsync(bool enable) {

void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
    const bool supportsFrameRateOverrideByContent =
            leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();
            pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent();

    std::vector<FrameRateOverride> overrides =
            mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
@@ -326,7 +326,7 @@ void Scheduler::dispatchCachedReportedMode() {
    // If the mode is not the current mode, this means that a
    // mode change is in progress. In that case we shouldn't dispatch an event
    // as it will be dispatched when the current mode changes.
    if (leaderSelectorPtr()->getActiveMode() != mPolicy.modeOpt) {
    if (pacesetterSelectorPtr()->getActiveMode() != mPolicy.modeOpt) {
        return;
    }

@@ -489,7 +489,7 @@ void Scheduler::deregisterLayer(Layer* layer) {

void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
                                   LayerHistory::LayerUpdateType updateType) {
    if (leaderSelectorPtr()->canSwitch()) {
    if (pacesetterSelectorPtr()->canSwitch()) {
        mLayerHistory.record(layer, presentTime, systemTime(), updateType);
    }
}
@@ -504,7 +504,7 @@ void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) {
}

void Scheduler::chooseRefreshRateForContent() {
    const auto selectorPtr = leaderSelectorPtr();
    const auto selectorPtr = pacesetterSelectorPtr();
    if (!selectorPtr->canSwitch()) return;

    ATRACE_CALL();
@@ -514,22 +514,22 @@ void Scheduler::chooseRefreshRateForContent() {
}

void Scheduler::resetIdleTimer() {
    leaderSelectorPtr()->resetIdleTimer();
    pacesetterSelectorPtr()->resetIdleTimer();
}

void Scheduler::onTouchHint() {
    if (mTouchTimer) {
        mTouchTimer->reset();
        leaderSelectorPtr()->resetKernelIdleTimer();
        pacesetterSelectorPtr()->resetKernelIdleTimer();
    }
}

void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) {
    const bool isLeader = [this, id]() REQUIRES(kMainThreadContext) {
    const bool isPacesetter = [this, id]() REQUIRES(kMainThreadContext) {
        ftl::FakeGuard guard(mDisplayLock);
        return id == mLeaderDisplayId;
        return id == mPacesetterDisplayId;
    }();
    if (isLeader) {
    if (isPacesetter) {
        // TODO (b/255657128): This needs to be handled per display.
        std::lock_guard<std::mutex> lock(mPolicyLock);
        mPolicy.displayPowerMode = powerMode;
@@ -539,7 +539,7 @@ void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMo
        auto vsyncSchedule = getVsyncScheduleLocked(id);
        vsyncSchedule->getController().setDisplayPowerMode(powerMode);
    }
    if (!isLeader) return;
    if (!isPacesetter) return;

    if (mDisplayPowerTimer) {
        mDisplayPowerTimer->reset();
@@ -560,8 +560,8 @@ std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncScheduleLocked(
        std::optional<PhysicalDisplayId> idOpt) const {
    ftl::FakeGuard guard(kMainThreadContext);
    if (!idOpt) {
        LOG_ALWAYS_FATAL_IF(!mLeaderDisplayId, "Missing a leader!");
        idOpt = mLeaderDisplayId;
        LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
        idOpt = mPacesetterDisplayId;
    }
    auto scheduleOpt = mVsyncSchedules.get(*idOpt);
    LOG_ALWAYS_FATAL_IF(!scheduleOpt);
@@ -573,7 +573,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) {

    // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
    // magic number
    const Fps refreshRate = leaderSelectorPtr()->getActiveMode().modePtr->getFps();
    const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getFps();

    constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
    using namespace fps_approx_ops;
@@ -637,7 +637,7 @@ void Scheduler::dump(utils::Dumper& dumper) const {
        {
            std::scoped_lock lock(mDisplayLock);
            ftl::FakeGuard guard(kMainThreadContext);
            dumper.dump("leaderDisplayId"sv, mLeaderDisplayId);
            dumper.dump("pacesetterDisplayId"sv, mPacesetterDisplayId);
        }
        dumper.dump("layerHistory"sv, mLayerHistory.dump());
        dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval));
@@ -651,13 +651,13 @@ void Scheduler::dump(utils::Dumper& dumper) const {
void Scheduler::dumpVsync(std::string& out) const {
    std::scoped_lock lock(mDisplayLock);
    ftl::FakeGuard guard(kMainThreadContext);
    if (mLeaderDisplayId) {
        base::StringAppendF(&out, "VsyncSchedule for leader %s:\n",
                            to_string(*mLeaderDisplayId).c_str());
    if (mPacesetterDisplayId) {
        base::StringAppendF(&out, "VsyncSchedule for pacesetter %s:\n",
                            to_string(*mPacesetterDisplayId).c_str());
        getVsyncScheduleLocked()->dump(out);
    }
    for (auto& [id, vsyncSchedule] : mVsyncSchedules) {
        if (id == mLeaderDisplayId) {
        if (id == mPacesetterDisplayId) {
            continue;
        }
        base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
@@ -669,7 +669,7 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di
    if (consideredSignals.idle) return false;

    const auto frameRateOverrides =
            leaderSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements,
            pacesetterSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements,
                                                           displayRefreshRate, consideredSignals);

    // Note that RefreshRateSelector::supportsFrameRateOverrideByContent is checked when querying
@@ -677,23 +677,23 @@ bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps di
    return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
}

void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) {
    // TODO(b/241286431): Choose the leader display.
    mLeaderDisplayId = leaderIdOpt.value_or(mRefreshRateSelectors.begin()->first);
    ALOGI("Display %s is the leader", to_string(*mLeaderDisplayId).c_str());
void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) {
    // TODO(b/241286431): Choose the pacesetter display.
    mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first);
    ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());

    auto vsyncSchedule = getVsyncScheduleLocked(*mLeaderDisplayId);
    if (const auto leaderPtr = leaderSelectorPtrLocked()) {
        leaderPtr->setIdleTimerCallbacks(
    auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
    if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) {
        pacesetterPtr->setIdleTimerCallbacks(
                {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
                              .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
                 .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
                            .onExpired =
                                    [this] { kernelIdleTimerCallback(TimerState::Expired); }}});

        leaderPtr->startIdleTimer();
        pacesetterPtr->startIdleTimer();

        const Fps refreshRate = leaderPtr->getActiveMode().modePtr->getFps();
        const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps();
        vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
                                             true /* force */);
    }
@@ -707,14 +707,14 @@ void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOp
    }
}

void Scheduler::demoteLeaderDisplay() {
void Scheduler::demotePacesetterDisplay() {
    // No need to lock for reads on kMainThreadContext.
    if (const auto leaderPtr = FTL_FAKE_GUARD(mDisplayLock, leaderSelectorPtrLocked())) {
        leaderPtr->stopIdleTimer();
        leaderPtr->clearIdleTimerCallbacks();
    if (const auto pacesetterPtr = FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) {
        pacesetterPtr->stopIdleTimer();
        pacesetterPtr->clearIdleTimerCallbacks();
    }

    // Clear state that depends on the leader's RefreshRateSelector.
    // Clear state that depends on the pacesetter's RefreshRateSelector.
    std::scoped_lock lock(mPolicyLock);
    mPolicy = {};
}
@@ -743,10 +743,11 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals

            modeChoices = chooseDisplayModes();

            // TODO(b/240743786): The leader display's mode must change for any DisplayModeRequest
            // to go through. Fix this by tracking per-display Scheduler::Policy and timers.
            // TODO(b/240743786): The pacesetter display's mode must change for any
            // DisplayModeRequest to go through. Fix this by tracking per-display Scheduler::Policy
            // and timers.
            std::tie(modeOpt, consideredSignals) =
                    modeChoices.get(*mLeaderDisplayId)
                    modeChoices.get(*mPacesetterDisplayId)
                            .transform([](const DisplayModeChoice& choice) {
                                return std::make_pair(choice.mode, choice.consideredSignals);
                            })
@@ -879,7 +880,7 @@ GlobalSignals Scheduler::makeGlobalSignals() const {
FrameRateMode Scheduler::getPreferredDisplayMode() {
    std::lock_guard<std::mutex> lock(mPolicyLock);
    const auto frameRateMode =
            leaderSelectorPtr()
            pacesetterSelectorPtr()
                    ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals())
                    .ranking.front()
                    .frameRateMode;
+26 −26
Original line number Diff line number Diff line
@@ -102,8 +102,8 @@ public:

    void startTimers();

    // TODO(b/241285191): Remove this API by promoting leader in onScreen{Acquired,Released}.
    void setLeaderDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext)
    // TODO(b/241285191): Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
    void setPacesetterDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext)
            EXCLUDES(mDisplayLock);

    using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
@@ -167,9 +167,9 @@ public:

    const VsyncModulator& vsyncModulator() const { return *mVsyncModulator; }

    // In some cases, we should only modulate for the leader display. In those
    // In some cases, we should only modulate for the pacesetter display. In those
    // cases, the caller should pass in the relevant display, and the method
    // will no-op if it's not the leader. Other cases are not specific to a
    // will no-op if it's not the pacesetter. Other cases are not specific to a
    // display.
    template <typename... Args,
              typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
@@ -177,13 +177,13 @@ public:
        if (id) {
            std::scoped_lock lock(mDisplayLock);
            ftl::FakeGuard guard(kMainThreadContext);
            if (id != mLeaderDisplayId) {
            if (id != mPacesetterDisplayId) {
                return;
            }
        }

        if (const auto config = (*mVsyncModulator.*handler)(args...)) {
            setVsyncConfig(*config, getLeaderVsyncPeriod());
            setVsyncConfig(*config, getPacesetterVsyncPeriod());
        }
    }

@@ -254,7 +254,7 @@ public:
    void dump(ConnectionHandle, std::string&) const;
    void dumpVsync(std::string&) const EXCLUDES(mDisplayLock);

    // Returns the preferred refresh rate and frame rate for the leader display.
    // Returns the preferred refresh rate and frame rate for the pacesetter display.
    FrameRateMode getPreferredDisplayMode();

    // Notifies the scheduler about a refresh rate timeline change.
@@ -277,12 +277,12 @@ public:
    // Retrieves the overridden refresh rate for a given uid.
    std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock);

    Period getLeaderVsyncPeriod() const EXCLUDES(mDisplayLock) {
        return leaderSelectorPtr()->getActiveMode().fps.getPeriod();
    Period getPacesetterVsyncPeriod() const EXCLUDES(mDisplayLock) {
        return pacesetterSelectorPtr()->getActiveMode().fps.getPeriod();
    }

    Fps getLeaderRefreshRate() const EXCLUDES(mDisplayLock) {
        return leaderSelectorPtr()->getActiveMode().fps;
    Fps getPacesetterRefreshRate() const EXCLUDES(mDisplayLock) {
        return pacesetterSelectorPtr()->getActiveMode().fps;
    }

    // Returns the framerate of the layer with the given sequence ID
@@ -318,14 +318,14 @@ private:
    void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock);
    void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);

    // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new
    // `mLeaderDisplayId` is never `std::nullopt`.
    void promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt = std::nullopt)
    // Chooses a pacesetter among the registered displays, unless `pacesetterIdOpt` is specified.
    // The new `mPacesetterDisplayId` is never `std::nullopt`.
    void promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt)
            REQUIRES(kMainThreadContext, mDisplayLock);

    // Blocks until the leader's idle timer thread exits. `mDisplayLock` must not be locked by the
    // caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
    void demoteLeaderDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock);
    // Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by
    // the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
    void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock);

    void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr,
                                 std::shared_ptr<VsyncSchedule>) REQUIRES(kMainThreadContext)
@@ -415,23 +415,23 @@ private:
    display::PhysicalDisplayMap<PhysicalDisplayId, std::shared_ptr<VsyncSchedule>> mVsyncSchedules
            GUARDED_BY(mDisplayLock) GUARDED_BY(kMainThreadContext);

    ftl::Optional<PhysicalDisplayId> mLeaderDisplayId GUARDED_BY(mDisplayLock)
    ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
            GUARDED_BY(kMainThreadContext);

    RefreshRateSelectorPtr leaderSelectorPtr() const EXCLUDES(mDisplayLock) {
    RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) {
        std::scoped_lock lock(mDisplayLock);
        return leaderSelectorPtrLocked();
        return pacesetterSelectorPtrLocked();
    }

    RefreshRateSelectorPtr leaderSelectorPtrLocked() const REQUIRES(mDisplayLock) {
    RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) {
        ftl::FakeGuard guard(kMainThreadContext);
        const RefreshRateSelectorPtr noLeader;
        return mLeaderDisplayId
                .and_then([this](PhysicalDisplayId leaderId)
        const RefreshRateSelectorPtr noPacesetter;
        return mPacesetterDisplayId
                .and_then([this](PhysicalDisplayId pacesetterId)
                                  REQUIRES(mDisplayLock, kMainThreadContext) {
                                      return mRefreshRateSelectors.get(leaderId);
                                      return mRefreshRateSelectors.get(pacesetterId);
                                  })
                .value_or(std::cref(noLeader));
                .value_or(std::cref(noPacesetter));
    }

    std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked(
Loading