Loading services/surfaceflinger/Layer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1123,7 +1123,7 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for // the same reason we are allowing touch boost for those layers. See // RefreshRateSelector::rankRefreshRates for details. // RefreshRateSelector::rankFrameRates for details. const auto layerVotedWithDefaultCompatibility = frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote; Loading services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +268 −148 File changed.Preview size limit exceeded, changes collapsed. Show changes services/surfaceflinger/Scheduler/RefreshRateSelector.h +64 −27 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ #include <ftl/concat.h> #include <ftl/optional.h> #include <ftl/unit.h> #include <gui/DisplayEventReceiver.h> #include <scheduler/Fps.h> #include <scheduler/FrameRateMode.h> #include <scheduler/Seamlessness.h> #include "DisplayHardware/DisplayMode.h" Loading Loading @@ -58,6 +60,9 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); // The lowest Render Frame Rate that will ever be selected static constexpr Fps kMinSupportedFrameRate = 20_Hz; class Policy { static constexpr int kAllowGroupSwitchingDefault = false; Loading Loading @@ -196,12 +201,12 @@ public: } }; struct ScoredRefreshRate { DisplayModePtr modePtr; struct ScoredFrameRate { FrameRateMode frameRateMode; float score = 0.0f; bool operator==(const ScoredRefreshRate& other) const { return modePtr == other.modePtr && score == other.score; bool operator==(const ScoredFrameRate& other) const { return frameRateMode == other.frameRateMode && score == other.score; } static bool scoresEqual(float lhs, float rhs) { Loading @@ -210,25 +215,25 @@ public: } struct DescendingScore { bool operator()(const ScoredRefreshRate& lhs, const ScoredRefreshRate& rhs) const { bool operator()(const ScoredFrameRate& lhs, const ScoredFrameRate& rhs) const { return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score); } }; }; using RefreshRateRanking = std::vector<ScoredRefreshRate>; using FrameRateRanking = std::vector<ScoredFrameRate>; struct RankedRefreshRates { RefreshRateRanking ranking; // Ordered by descending score. struct RankedFrameRates { FrameRateRanking ranking; // Ordered by descending score. GlobalSignals consideredSignals; bool operator==(const RankedRefreshRates& other) const { bool operator==(const RankedFrameRates& other) const { return ranking == other.ranking && consideredSignals == other.consideredSignals; } }; RankedRefreshRates getRankedRefreshRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); Loading Loading @@ -257,9 +262,12 @@ public: // Override the frame rate for an app to a value which is also // a display refresh rate EnabledForNativeRefreshRates, AppOverrideNativeRefreshRates, // Override the frame rate for an app to any value AppOverride, // Override the frame rate for all apps and all values. Enabled, ftl_last = Enabled Loading Loading @@ -291,10 +299,13 @@ public: // Returns whether switching modes (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only // differ in resolution. // differ in resolution. Once Config::FrameRateOverride::Enabled becomes the default, // we can probably remove canSwitch altogether since all devices will be able // to switch to a frame rate divisor. bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return mDisplayModes.size() > 1; return mDisplayModes.size() > 1 || mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; } // Class to enumerate options around toggling the kernel timer on and off. Loading @@ -307,10 +318,14 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; bool supportsFrameRateOverrideByContent() const { bool supportsAppFrameRateOverrideByContent() const { return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled; } bool supportsFrameRateOverride() const { return mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; } // Return the display refresh rate divisor to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the // layer refresh rate. Loading Loading @@ -387,8 +402,8 @@ private: // See mActiveModeIt for thread safety. DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock); RankedRefreshRates getRankedRefreshRatesLocked(const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock); RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const REQUIRES(mLock); // Returns number of display frames and remainder when dividing the layer refresh period by // display refresh period. Loading @@ -404,18 +419,24 @@ private: struct RefreshRateScoreComparator; enum class RefreshRateOrder { Ascending, Descending }; enum class RefreshRateOrder { Ascending, Descending, ftl_last = Descending }; // Only uses the primary range, not the app request range. RefreshRateRanking rankRefreshRates(std::optional<int> anchorGroupOpt, RefreshRateOrder, std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const REQUIRES(mLock); FrameRateRanking rankFrameRates( std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder, std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1. float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock); float calculateDistanceScoreFromMax(Fps refreshRate) const REQUIRES(mLock); // calculates a score for a layer. Used to determine the display refresh rate // and the frame rate override for certains applications. float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate, Loading @@ -436,11 +457,27 @@ private: : mIdleTimerCallbacks->platform; } bool isNativeRefreshRate(Fps fps) const REQUIRES(mLock) { LOG_ALWAYS_FATAL_IF(mConfig.enableFrameRateOverride != Config::FrameRateOverride::AppOverrideNativeRefreshRates, "should only be called when " "Config::FrameRateOverride::AppOverrideNativeRefreshRates is used"); return mAppOverrideNativeRefreshRates.contains(fps); } std::vector<FrameRateMode> createFrameRateModes( std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange&) const REQUIRES(mLock); // The display modes of the active display. The DisplayModeIterators below are pointers into // this container, so must be invalidated whenever the DisplayModes change. The Policy below // is also dependent, so must be reset as well. DisplayModes mDisplayModes GUARDED_BY(mLock); // Set of supported display refresh rates for easy lookup // when FrameRateOverride::AppOverrideNativeRefreshRates is in use. ftl::SmallMap<Fps, ftl::Unit, 8, FpsApproxEqual> mAppOverrideNativeRefreshRates; // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext // need not be under mLock. DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext); Loading @@ -449,8 +486,8 @@ private: DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock); // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate. std::vector<DisplayModeIterator> mPrimaryRefreshRates GUARDED_BY(mLock); std::vector<DisplayModeIterator> mAppRequestRefreshRates GUARDED_BY(mLock); std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock); std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock); Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); Loading @@ -466,11 +503,11 @@ private: const Config mConfig; Config::FrameRateOverride mFrameRateOverrideConfig; struct GetRankedRefreshRatesCache { struct GetRankedFrameRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; RankedRefreshRates result; RankedFrameRates result; }; mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock); mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock); // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed. std::mutex mIdleTimerCallbacksMutex; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +14 −11 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource( std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsFrameRateOverrideByContent(); leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); return mFrameRateOverrideMappings .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent); } Loading Loading @@ -268,7 +268,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsFrameRateOverrideByContent(); leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); Loading Loading @@ -707,7 +707,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { ATRACE_CALL(); using RankedRefreshRates = RefreshRateSelector::RankedRefreshRates; using RankedRefreshRates = RefreshRateSelector::RankedFrameRates; display::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking; // Tallies the score of a refresh rate across `displayCount` displays. Loading @@ -726,9 +726,10 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (const auto& [id, selectorPtr] : mRefreshRateSelectors) { auto rankedRefreshRates = selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals); for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { for (const auto& [frameRateMode, score] : rankedRefreshRates.ranking) { const auto& modePtr = frameRateMode.modePtr; const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); if (!inserted) { Loading Loading @@ -771,16 +772,18 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (auto& [ranking, signals] : perDisplayRanking) { if (!chosenFps) { auto& [modePtr, _] = ranking.front(); const auto& [frameRateMode, _] = ranking.front(); const auto& modePtr = frameRateMode.modePtr; modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), DisplayModeChoice{std::move(modePtr), signals}); DisplayModeChoice{modePtr, signals}); continue; } for (auto& [modePtr, _] : ranking) { for (auto& [frameRateMode, _] : ranking) { const auto& modePtr = frameRateMode.modePtr; if (modePtr->getFps() == *chosenFps) { modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), DisplayModeChoice{std::move(modePtr), signals}); DisplayModeChoice{modePtr, signals}); break; } } Loading @@ -804,10 +807,10 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() { if (mPolicy.mode) { const auto ranking = leaderSelectorPtr() ->getRankedRefreshRates(mPolicy.contentRequirements, makeGlobalSignals()) ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals()) .ranking; mPolicy.mode = ranking.front().modePtr; mPolicy.mode = ranking.front().frameRateMode.modePtr; } return mPolicy.mode; } Loading services/surfaceflinger/Scheduler/include/scheduler/Fps.h +13 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ struct FpsRange { Fps max = Fps::fromValue(std::numeric_limits<float>::max()); bool includes(Fps) const; bool includes(FpsRange) const; }; struct FpsRanges { Loading @@ -75,6 +76,8 @@ struct FpsRanges { // the range of frame rates that refers to the render rate, which is // the rate that frames are swapped. FpsRange render; bool valid() const; }; static_assert(std::is_trivially_copyable_v<Fps>); Loading Loading @@ -159,6 +162,16 @@ inline bool FpsRange::includes(Fps fps) const { return min <= fps && fps <= max; } inline bool FpsRange::includes(FpsRange range) const { using namespace fps_approx_ops; return min <= range.min && max >= range.max; } inline bool FpsRanges::valid() const { using fps_approx_ops::operator>=; return physical.max >= render.max; } struct FpsApproxEqual { bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); } }; Loading Loading
services/surfaceflinger/Layer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1123,7 +1123,7 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for // the same reason we are allowing touch boost for those layers. See // RefreshRateSelector::rankRefreshRates for details. // RefreshRateSelector::rankFrameRates for details. const auto layerVotedWithDefaultCompatibility = frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote; Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +268 −148 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/surfaceflinger/Scheduler/RefreshRateSelector.h +64 −27 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ #include <ftl/concat.h> #include <ftl/optional.h> #include <ftl/unit.h> #include <gui/DisplayEventReceiver.h> #include <scheduler/Fps.h> #include <scheduler/FrameRateMode.h> #include <scheduler/Seamlessness.h> #include "DisplayHardware/DisplayMode.h" Loading Loading @@ -58,6 +60,9 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); // The lowest Render Frame Rate that will ever be selected static constexpr Fps kMinSupportedFrameRate = 20_Hz; class Policy { static constexpr int kAllowGroupSwitchingDefault = false; Loading Loading @@ -196,12 +201,12 @@ public: } }; struct ScoredRefreshRate { DisplayModePtr modePtr; struct ScoredFrameRate { FrameRateMode frameRateMode; float score = 0.0f; bool operator==(const ScoredRefreshRate& other) const { return modePtr == other.modePtr && score == other.score; bool operator==(const ScoredFrameRate& other) const { return frameRateMode == other.frameRateMode && score == other.score; } static bool scoresEqual(float lhs, float rhs) { Loading @@ -210,25 +215,25 @@ public: } struct DescendingScore { bool operator()(const ScoredRefreshRate& lhs, const ScoredRefreshRate& rhs) const { bool operator()(const ScoredFrameRate& lhs, const ScoredFrameRate& rhs) const { return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score); } }; }; using RefreshRateRanking = std::vector<ScoredRefreshRate>; using FrameRateRanking = std::vector<ScoredFrameRate>; struct RankedRefreshRates { RefreshRateRanking ranking; // Ordered by descending score. struct RankedFrameRates { FrameRateRanking ranking; // Ordered by descending score. GlobalSignals consideredSignals; bool operator==(const RankedRefreshRates& other) const { bool operator==(const RankedFrameRates& other) const { return ranking == other.ranking && consideredSignals == other.consideredSignals; } }; RankedRefreshRates getRankedRefreshRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); Loading Loading @@ -257,9 +262,12 @@ public: // Override the frame rate for an app to a value which is also // a display refresh rate EnabledForNativeRefreshRates, AppOverrideNativeRefreshRates, // Override the frame rate for an app to any value AppOverride, // Override the frame rate for all apps and all values. Enabled, ftl_last = Enabled Loading Loading @@ -291,10 +299,13 @@ public: // Returns whether switching modes (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only // differ in resolution. // differ in resolution. Once Config::FrameRateOverride::Enabled becomes the default, // we can probably remove canSwitch altogether since all devices will be able // to switch to a frame rate divisor. bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return mDisplayModes.size() > 1; return mDisplayModes.size() > 1 || mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; } // Class to enumerate options around toggling the kernel timer on and off. Loading @@ -307,10 +318,14 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; bool supportsFrameRateOverrideByContent() const { bool supportsAppFrameRateOverrideByContent() const { return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled; } bool supportsFrameRateOverride() const { return mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; } // Return the display refresh rate divisor to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the // layer refresh rate. Loading Loading @@ -387,8 +402,8 @@ private: // See mActiveModeIt for thread safety. DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock); RankedRefreshRates getRankedRefreshRatesLocked(const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock); RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const REQUIRES(mLock); // Returns number of display frames and remainder when dividing the layer refresh period by // display refresh period. Loading @@ -404,18 +419,24 @@ private: struct RefreshRateScoreComparator; enum class RefreshRateOrder { Ascending, Descending }; enum class RefreshRateOrder { Ascending, Descending, ftl_last = Descending }; // Only uses the primary range, not the app request range. RefreshRateRanking rankRefreshRates(std::optional<int> anchorGroupOpt, RefreshRateOrder, std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const REQUIRES(mLock); FrameRateRanking rankFrameRates( std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder, std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1. float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock); float calculateDistanceScoreFromMax(Fps refreshRate) const REQUIRES(mLock); // calculates a score for a layer. Used to determine the display refresh rate // and the frame rate override for certains applications. float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate, Loading @@ -436,11 +457,27 @@ private: : mIdleTimerCallbacks->platform; } bool isNativeRefreshRate(Fps fps) const REQUIRES(mLock) { LOG_ALWAYS_FATAL_IF(mConfig.enableFrameRateOverride != Config::FrameRateOverride::AppOverrideNativeRefreshRates, "should only be called when " "Config::FrameRateOverride::AppOverrideNativeRefreshRates is used"); return mAppOverrideNativeRefreshRates.contains(fps); } std::vector<FrameRateMode> createFrameRateModes( std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange&) const REQUIRES(mLock); // The display modes of the active display. The DisplayModeIterators below are pointers into // this container, so must be invalidated whenever the DisplayModes change. The Policy below // is also dependent, so must be reset as well. DisplayModes mDisplayModes GUARDED_BY(mLock); // Set of supported display refresh rates for easy lookup // when FrameRateOverride::AppOverrideNativeRefreshRates is in use. ftl::SmallMap<Fps, ftl::Unit, 8, FpsApproxEqual> mAppOverrideNativeRefreshRates; // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext // need not be under mLock. DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext); Loading @@ -449,8 +486,8 @@ private: DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock); // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate. std::vector<DisplayModeIterator> mPrimaryRefreshRates GUARDED_BY(mLock); std::vector<DisplayModeIterator> mAppRequestRefreshRates GUARDED_BY(mLock); std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock); std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock); Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); Loading @@ -466,11 +503,11 @@ private: const Config mConfig; Config::FrameRateOverride mFrameRateOverrideConfig; struct GetRankedRefreshRatesCache { struct GetRankedFrameRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; RankedRefreshRates result; RankedFrameRates result; }; mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock); mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock); // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed. std::mutex mIdleTimerCallbacksMutex; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +14 −11 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource( std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsFrameRateOverrideByContent(); leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); return mFrameRateOverrideMappings .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent); } Loading Loading @@ -268,7 +268,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = leaderSelectorPtr()->supportsFrameRateOverrideByContent(); leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); Loading Loading @@ -707,7 +707,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { ATRACE_CALL(); using RankedRefreshRates = RefreshRateSelector::RankedRefreshRates; using RankedRefreshRates = RefreshRateSelector::RankedFrameRates; display::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking; // Tallies the score of a refresh rate across `displayCount` displays. Loading @@ -726,9 +726,10 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (const auto& [id, selectorPtr] : mRefreshRateSelectors) { auto rankedRefreshRates = selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals); for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { for (const auto& [frameRateMode, score] : rankedRefreshRates.ranking) { const auto& modePtr = frameRateMode.modePtr; const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); if (!inserted) { Loading Loading @@ -771,16 +772,18 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (auto& [ranking, signals] : perDisplayRanking) { if (!chosenFps) { auto& [modePtr, _] = ranking.front(); const auto& [frameRateMode, _] = ranking.front(); const auto& modePtr = frameRateMode.modePtr; modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), DisplayModeChoice{std::move(modePtr), signals}); DisplayModeChoice{modePtr, signals}); continue; } for (auto& [modePtr, _] : ranking) { for (auto& [frameRateMode, _] : ranking) { const auto& modePtr = frameRateMode.modePtr; if (modePtr->getFps() == *chosenFps) { modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), DisplayModeChoice{std::move(modePtr), signals}); DisplayModeChoice{modePtr, signals}); break; } } Loading @@ -804,10 +807,10 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() { if (mPolicy.mode) { const auto ranking = leaderSelectorPtr() ->getRankedRefreshRates(mPolicy.contentRequirements, makeGlobalSignals()) ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals()) .ranking; mPolicy.mode = ranking.front().modePtr; mPolicy.mode = ranking.front().frameRateMode.modePtr; } return mPolicy.mode; } Loading
services/surfaceflinger/Scheduler/include/scheduler/Fps.h +13 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ struct FpsRange { Fps max = Fps::fromValue(std::numeric_limits<float>::max()); bool includes(Fps) const; bool includes(FpsRange) const; }; struct FpsRanges { Loading @@ -75,6 +76,8 @@ struct FpsRanges { // the range of frame rates that refers to the render rate, which is // the rate that frames are swapped. FpsRange render; bool valid() const; }; static_assert(std::is_trivially_copyable_v<Fps>); Loading Loading @@ -159,6 +162,16 @@ inline bool FpsRange::includes(Fps fps) const { return min <= fps && fps <= max; } inline bool FpsRange::includes(FpsRange range) const { using namespace fps_approx_ops; return min <= range.min && max >= range.max; } inline bool FpsRanges::valid() const { using fps_approx_ops::operator>=; return physical.max >= render.max; } struct FpsApproxEqual { bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); } }; Loading