Loading services/surfaceflinger/Scheduler/Scheduler.cpp +20 −7 Original line number Diff line number Diff line Loading @@ -67,11 +67,12 @@ namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features, sp<VsyncModulator> modulatorPtr) sp<VsyncModulator> modulatorPtr, IVsyncTrackerCallback& vsyncTrackerCallback) : impl::MessageQueue(compositor), mFeatures(features), mVsyncModulator(std::move(modulatorPtr)), mSchedulerCallback(callback) {} mSchedulerCallback(callback), mVsyncTrackerCallback(vsyncTrackerCallback) {} Scheduler::~Scheduler() { // MessageQueue depends on VsyncSchedule, so first destroy it. Loading Loading @@ -116,10 +117,10 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); auto schedulePtr = std::make_shared<VsyncSchedule>( displayId, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }, mVsyncTrackerCallback); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); } Loading Loading @@ -562,7 +563,19 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) { ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(), to_string(mode.modePtr->getVsyncRate()).c_str()); display.schedulePtr->getTracker().setRenderRate(renderFrameRate); 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; } } void Scheduler::resync() { Loading services/surfaceflinger/Scheduler/Scheduler.h +7 −1 Original line number Diff line number Diff line Loading @@ -102,7 +102,8 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; public: Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>); Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>, IVsyncTrackerCallback&); virtual ~Scheduler(); void startTimers(); Loading Loading @@ -429,6 +430,9 @@ private: 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; Loading Loading @@ -462,6 +466,8 @@ private: ISchedulerCallback& mSchedulerCallback; IVsyncTrackerCallback& mVsyncTrackerCallback; // mDisplayLock may be locked while under mPolicyLock. mutable std::mutex mPolicyLock; Loading services/surfaceflinger/Scheduler/VSyncPredictor.cpp +28 −8 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <gui/TraceUtils.h> #include <utils/Log.h> #include "FlagManager.h" #include "RefreshRateSelector.h" #include "VSyncPredictor.h" Loading @@ -47,12 +48,14 @@ static auto constexpr kMaxPercent = 100u; VSyncPredictor::~VSyncPredictor() = default; VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize, size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent) size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent, IVsyncTrackerCallback& callback) : mId(id), mTraceOn(property_get_bool("debug.sf.vsp_trace", false)), kHistorySize(historySize), kMinimumSamplesForPrediction(minimumSamplesForPrediction), kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)), mVsyncTrackerCallback(callback), mIdealPeriod(idealPeriod) { resetModel(); } Loading Loading @@ -275,11 +278,11 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { mLastVsyncSequence = getVsyncSequenceLocked(timePoint); const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int { if (!mRenderRate) return 0; if (!mDisplayModeDataOpt) return 0; const auto divisor = RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod), *mRenderRate); mDisplayModeDataOpt->renderRate); if (divisor <= 1) return 0; const int mod = mLastVsyncSequence->seq % divisor; Loading @@ -289,12 +292,24 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { }(); if (renderRatePhase == 0) { return mLastVsyncSequence->vsyncTime; const auto vsyncTime = mLastVsyncSequence->vsyncTime; if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) { mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(vsyncTime), *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod)); } return vsyncTime; } auto const [slope, intercept] = getVSyncPredictionModelLocked(); const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase; return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2); const auto nextAnticipatedVsyncTime = nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2); if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) { mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(nextAnticipatedVsyncTime), *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod)); } return nextAnticipatedVsyncTime; } /* Loading Loading @@ -332,10 +347,14 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c return vsyncSequence.seq % divisor == 0; } void VSyncPredictor::setRenderRate(Fps fps) { ALOGV("%s %s: %s", __func__, to_string(mId).c_str(), to_string(fps).c_str()); 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"); std::lock_guard lock(mMutex); mRenderRate = fps; mDisplayModeDataOpt = displayModeData; } VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const { Loading @@ -358,6 +377,7 @@ void VSyncPredictor::setPeriod(nsecs_t period) { 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}; Loading services/surfaceflinger/Scheduler/VSyncPredictor.h +6 −3 Original line number Diff line number Diff line Loading @@ -36,9 +36,11 @@ public: * \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, size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent); size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent, IVsyncTrackerCallback&); ~VSyncPredictor(); bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex); Loading Loading @@ -69,7 +71,7 @@ public: bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex); void setRenderRate(Fps) final EXCLUDES(mMutex); void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex); void dump(std::string& result) const final EXCLUDES(mMutex); Loading Loading @@ -99,6 +101,7 @@ private: size_t const kHistorySize; size_t const kMinimumSamplesForPrediction; size_t const kOutlierTolerancePercent; IVsyncTrackerCallback& mVsyncTrackerCallback; std::mutex mutable mMutex; nsecs_t mIdealPeriod GUARDED_BY(mMutex); Loading @@ -110,7 +113,7 @@ private: size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0; std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex); std::optional<Fps> mRenderRate GUARDED_BY(mMutex); std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex); mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex); }; Loading services/surfaceflinger/Scheduler/VSyncTracker.h +26 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <ui/DisplayId.h> #include <utils/Timers.h> #include <scheduler/Fps.h> Loading @@ -23,6 +24,23 @@ #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; }; /* * VSyncTracker is an interface for providing estimates on future Vsync signal times based on * historical vsync timing data. Loading Loading @@ -80,16 +98,20 @@ public: virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 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. * 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. * 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] Fps The render rate the tracker should operate at. * \param [in] DisplayModeData The DisplayModeData the tracker will use. */ virtual void setRenderRate(Fps) = 0; virtual void setDisplayModeData(const DisplayModeData&) = 0; virtual void dump(std::string& result) const = 0; Loading Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +20 −7 Original line number Diff line number Diff line Loading @@ -67,11 +67,12 @@ namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features, sp<VsyncModulator> modulatorPtr) sp<VsyncModulator> modulatorPtr, IVsyncTrackerCallback& vsyncTrackerCallback) : impl::MessageQueue(compositor), mFeatures(features), mVsyncModulator(std::move(modulatorPtr)), mSchedulerCallback(callback) {} mSchedulerCallback(callback), mVsyncTrackerCallback(vsyncTrackerCallback) {} Scheduler::~Scheduler() { // MessageQueue depends on VsyncSchedule, so first destroy it. Loading Loading @@ -116,10 +117,10 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter } void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); auto schedulePtr = std::make_shared<VsyncSchedule>( displayId, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }, mVsyncTrackerCallback); registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); } Loading Loading @@ -562,7 +563,19 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) { ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(), to_string(mode.modePtr->getVsyncRate()).c_str()); display.schedulePtr->getTracker().setRenderRate(renderFrameRate); 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; } } void Scheduler::resync() { Loading
services/surfaceflinger/Scheduler/Scheduler.h +7 −1 Original line number Diff line number Diff line Loading @@ -102,7 +102,8 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; public: Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>); Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>, IVsyncTrackerCallback&); virtual ~Scheduler(); void startTimers(); Loading Loading @@ -429,6 +430,9 @@ private: 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; Loading Loading @@ -462,6 +466,8 @@ private: ISchedulerCallback& mSchedulerCallback; IVsyncTrackerCallback& mVsyncTrackerCallback; // mDisplayLock may be locked while under mPolicyLock. mutable std::mutex mPolicyLock; Loading
services/surfaceflinger/Scheduler/VSyncPredictor.cpp +28 −8 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <gui/TraceUtils.h> #include <utils/Log.h> #include "FlagManager.h" #include "RefreshRateSelector.h" #include "VSyncPredictor.h" Loading @@ -47,12 +48,14 @@ static auto constexpr kMaxPercent = 100u; VSyncPredictor::~VSyncPredictor() = default; VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize, size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent) size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent, IVsyncTrackerCallback& callback) : mId(id), mTraceOn(property_get_bool("debug.sf.vsp_trace", false)), kHistorySize(historySize), kMinimumSamplesForPrediction(minimumSamplesForPrediction), kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)), mVsyncTrackerCallback(callback), mIdealPeriod(idealPeriod) { resetModel(); } Loading Loading @@ -275,11 +278,11 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { mLastVsyncSequence = getVsyncSequenceLocked(timePoint); const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int { if (!mRenderRate) return 0; if (!mDisplayModeDataOpt) return 0; const auto divisor = RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod), *mRenderRate); mDisplayModeDataOpt->renderRate); if (divisor <= 1) return 0; const int mod = mLastVsyncSequence->seq % divisor; Loading @@ -289,12 +292,24 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const { }(); if (renderRatePhase == 0) { return mLastVsyncSequence->vsyncTime; const auto vsyncTime = mLastVsyncSequence->vsyncTime; if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) { mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(vsyncTime), *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod)); } return vsyncTime; } auto const [slope, intercept] = getVSyncPredictionModelLocked(); const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase; return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2); const auto nextAnticipatedVsyncTime = nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2); if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) { mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(nextAnticipatedVsyncTime), *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod)); } return nextAnticipatedVsyncTime; } /* Loading Loading @@ -332,10 +347,14 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c return vsyncSequence.seq % divisor == 0; } void VSyncPredictor::setRenderRate(Fps fps) { ALOGV("%s %s: %s", __func__, to_string(mId).c_str(), to_string(fps).c_str()); 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"); std::lock_guard lock(mMutex); mRenderRate = fps; mDisplayModeDataOpt = displayModeData; } VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const { Loading @@ -358,6 +377,7 @@ void VSyncPredictor::setPeriod(nsecs_t period) { 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}; Loading
services/surfaceflinger/Scheduler/VSyncPredictor.h +6 −3 Original line number Diff line number Diff line Loading @@ -36,9 +36,11 @@ public: * \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, size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent); size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent, IVsyncTrackerCallback&); ~VSyncPredictor(); bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex); Loading Loading @@ -69,7 +71,7 @@ public: bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex); void setRenderRate(Fps) final EXCLUDES(mMutex); void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex); void dump(std::string& result) const final EXCLUDES(mMutex); Loading Loading @@ -99,6 +101,7 @@ private: size_t const kHistorySize; size_t const kMinimumSamplesForPrediction; size_t const kOutlierTolerancePercent; IVsyncTrackerCallback& mVsyncTrackerCallback; std::mutex mutable mMutex; nsecs_t mIdealPeriod GUARDED_BY(mMutex); Loading @@ -110,7 +113,7 @@ private: size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0; std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex); std::optional<Fps> mRenderRate GUARDED_BY(mMutex); std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex); mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex); }; Loading
services/surfaceflinger/Scheduler/VSyncTracker.h +26 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <ui/DisplayId.h> #include <utils/Timers.h> #include <scheduler/Fps.h> Loading @@ -23,6 +24,23 @@ #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; }; /* * VSyncTracker is an interface for providing estimates on future Vsync signal times based on * historical vsync timing data. Loading Loading @@ -80,16 +98,20 @@ public: virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 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. * 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. * 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] Fps The render rate the tracker should operate at. * \param [in] DisplayModeData The DisplayModeData the tracker will use. */ virtual void setRenderRate(Fps) = 0; virtual void setDisplayModeData(const DisplayModeData&) = 0; virtual void dump(std::string& result) const = 0; Loading