Loading services/surfaceflinger/RefreshRateOverlay.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -170,7 +170,7 @@ bool RefreshRateOverlay::createLayer() { void RefreshRateOverlay::primeCache() { auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { auto fps = allRefreshRates.begin()->second->fps; auto fps = allRefreshRates.begin()->second->getFps(); half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); return; Loading @@ -179,7 +179,7 @@ void RefreshRateOverlay::primeCache() { std::vector<uint32_t> supportedFps; supportedFps.reserve(allRefreshRates.size()); for (auto& [ignored, refreshRate] : allRefreshRates) { supportedFps.push_back(refreshRate->fps); supportedFps.push_back(refreshRate->getFps()); } std::sort(supportedFps.begin(), supportedFps.end()); Loading Loading @@ -207,7 +207,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; auto buffer = mBufferCache[refreshRate.fps]; auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); Loading services/surfaceflinger/Scheduler/HwcStrongTypes.h +0 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,5 @@ namespace android { // Strong types for the different indexes as they are referring to a different base. using HwcConfigIndexType = StrongTyping<int, struct HwcConfigIndexTypeTag, Compare, Add, Hash>; using HwcConfigGroupType = StrongTyping<int, struct HwcConfigGroupTypeTag, Compare>; } // namespace android No newline at end of file services/surfaceflinger/Scheduler/PhaseOffsets.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ std::vector<float> getRefreshRatesFromConfigs( refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { refreshRates.emplace_back(refreshRate->fps); refreshRates.emplace_back(refreshRate->getFps()); } return refreshRates; Loading @@ -59,7 +59,7 @@ namespace impl { PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs), refreshRateConfigs.getCurrentRefreshRate().fps, refreshRateConfigs.getCurrentRefreshRate().getFps(), // Below defines the threshold when an offset is considered to be negative, // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For Loading Loading @@ -275,7 +275,7 @@ std::unordered_map<float, PhaseDurations::Offsets> PhaseDurations::initializeOff PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs), refreshRateConfigs.getCurrentRefreshRate().fps, refreshRateConfigs.getCurrentRefreshRate().getFps(), getProperty("debug.sf.late.sf.duration").value_or(-1), getProperty("debug.sf.late.app.duration").value_or(-1), getProperty("debug.sf.early.sf.duration").value_or(mSfDuration), Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +38 −45 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( if (explicitContentFramerate != 0) { contentFramerate = explicitContentFramerate; } else if (contentFramerate == 0) { contentFramerate = round<int>(mMaxSupportedRefreshRate->fps); contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps()); } ATRACE_INT("ContentFPS", contentFramerate); Loading Loading @@ -177,7 +177,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( continue; } const auto displayPeriod = scores[i].first->vsyncPeriod; const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod(); const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate); if (layer.vote == LayerVoteType::ExplicitDefault) { const auto layerScore = [&]() { Loading Loading @@ -309,21 +309,30 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) { init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { std::vector<InputConfig> inputConfigs; for (size_t configId = 0; configId < configs.size(); ++configId) { auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup()); inputConfigs.push_back({HwcConfigIndexType(static_cast<int>(configId)), configGroup, configs[configId]->getVsyncPeriod()}); LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast<size_t>(configId.value())); const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, base::StringPrintf("%2.ffps", fps), fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } } init(inputConfigs, currentConfigId); std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentConfigId; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); constructAvailableRefreshRates(); } bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { Loading Loading @@ -406,10 +415,13 @@ void RefreshRateConfigs::getSortedRefreshRateList( std::sort(outRefreshRates->begin(), outRefreshRates->end(), [](const auto refreshRate1, const auto refreshRate2) { if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) { return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; if (refreshRate1->hwcConfig->getVsyncPeriod() != refreshRate2->hwcConfig->getVsyncPeriod()) { return refreshRate1->hwcConfig->getVsyncPeriod() > refreshRate2->hwcConfig->getVsyncPeriod(); } else { return refreshRate1->configGroup > refreshRate2->configGroup; return refreshRate1->hwcConfig->getConfigGroup() > refreshRate2->hwcConfig->getConfigGroup(); } }); } Loading @@ -417,13 +429,20 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup; const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", policy->defaultConfig.value(), group.value(), policy->minRefreshRate, policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate, policy->maxRefreshRate); getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { return (policy->allowGroupSwitching || refreshRate.configGroup == group) && const auto& hwcConfig = refreshRate.hwcConfig; return hwcConfig->getHeight() == defaultConfig->getHeight() && hwcConfig->getWidth() == defaultConfig->getWidth() && hwcConfig->getDpiX() == defaultConfig->getDpiX() && hwcConfig->getDpiY() == defaultConfig->getDpiY() && (policy->allowGroupSwitching || hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate); }, &mAvailableRefreshRates); Loading @@ -440,30 +459,4 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { policy->maxRefreshRate); } // NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor void RefreshRateConfigs::init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS { LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); for (const auto& config : configs) { const float fps = 1e9f / config.vsyncPeriod; mRefreshRates.emplace(config.configId, std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod, config.configGroup, base::StringPrintf("%2.ffps", fps), fps)); if (config.configId == currentHwcConfig) { mCurrentRefreshRate = mRefreshRates.at(config.configId).get(); } } std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentHwcConfig; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); constructAvailableRefreshRates(); } } // namespace android::scheduler services/surfaceflinger/Scheduler/RefreshRateConfigs.h +38 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include "Scheduler/StrongTyping.h" namespace android::scheduler { class RefreshRateConfigsTest; using namespace std::chrono_literals; enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 }; Loading @@ -49,30 +51,27 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); struct RefreshRate { // The tolerance within which we consider FPS approximately equals. static constexpr float FPS_EPSILON = 0.001f; class RefreshRate { private: // Effectively making the constructor private while allowing // std::make_unique to create the object struct ConstructorTag { explicit ConstructorTag(int) {} }; RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod, HwcConfigGroupType configGroup, std::string name, float fps) : configId(configId), vsyncPeriod(vsyncPeriod), configGroup(configGroup), name(std::move(name)), fps(fps) {} public: RefreshRate(HwcConfigIndexType configId, std::shared_ptr<const HWC2::Display::Config> config, std::string name, float fps, ConstructorTag) : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {} RefreshRate(const RefreshRate&) = delete; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // Vsync period in nanoseconds. const nsecs_t vsyncPeriod; // This configGroup for the config. const HwcConfigGroupType configGroup; // Human readable name of the refresh rate. const std::string name; // Refresh rate in frames per second const float fps = 0; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } const std::string& getName() const { return name; } float getFps() const { return fps; } // Checks whether the fps of this RefreshRate struct is within a given min and max refresh // rate passed in. FPS_EPSILON is applied to the boundaries for approximation. Loading @@ -81,11 +80,27 @@ public: } bool operator!=(const RefreshRate& other) const { return configId != other.configId || vsyncPeriod != other.vsyncPeriod || configGroup != other.configGroup; return configId != other.configId || hwcConfig != other.hwcConfig; } bool operator==(const RefreshRate& other) const { return !(*this != other); } private: friend RefreshRateConfigs; friend RefreshRateConfigsTest; // The tolerance within which we consider FPS approximately equals. static constexpr float FPS_EPSILON = 0.001f; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // The config itself std::shared_ptr<const HWC2::Display::Config> hwcConfig; // Human readable name of the refresh rate. const std::string name; // Refresh rate in frames per second const float fps = 0; }; using AllRefreshRatesMapType = Loading Loading @@ -208,20 +223,10 @@ public: // Stores the current configId the device operates at void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock); struct InputConfig { HwcConfigIndexType configId = HwcConfigIndexType(0); HwcConfigGroupType configGroup = HwcConfigGroupType(0); nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); private: void init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); void constructAvailableRefreshRates() REQUIRES(mLock); void getSortedRefreshRateList( Loading Loading
services/surfaceflinger/RefreshRateOverlay.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -170,7 +170,7 @@ bool RefreshRateOverlay::createLayer() { void RefreshRateOverlay::primeCache() { auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { auto fps = allRefreshRates.begin()->second->fps; auto fps = allRefreshRates.begin()->second->getFps(); half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); return; Loading @@ -179,7 +179,7 @@ void RefreshRateOverlay::primeCache() { std::vector<uint32_t> supportedFps; supportedFps.reserve(allRefreshRates.size()); for (auto& [ignored, refreshRate] : allRefreshRates) { supportedFps.push_back(refreshRate->fps); supportedFps.push_back(refreshRate->getFps()); } std::sort(supportedFps.begin(), supportedFps.end()); Loading Loading @@ -207,7 +207,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { const int32_t right = left + display->getWidth() / 8; const int32_t buttom = top + display->getHeight() / 32; auto buffer = mBufferCache[refreshRate.fps]; auto buffer = mBufferCache[refreshRate.getFps()]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mLayer->setFrame(Rect(left, top, right, buttom)); Loading
services/surfaceflinger/Scheduler/HwcStrongTypes.h +0 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,5 @@ namespace android { // Strong types for the different indexes as they are referring to a different base. using HwcConfigIndexType = StrongTyping<int, struct HwcConfigIndexTypeTag, Compare, Add, Hash>; using HwcConfigGroupType = StrongTyping<int, struct HwcConfigGroupTypeTag, Compare>; } // namespace android No newline at end of file
services/surfaceflinger/Scheduler/PhaseOffsets.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ std::vector<float> getRefreshRatesFromConfigs( refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { refreshRates.emplace_back(refreshRate->fps); refreshRates.emplace_back(refreshRate->getFps()); } return refreshRates; Loading @@ -59,7 +59,7 @@ namespace impl { PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs), refreshRateConfigs.getCurrentRefreshRate().fps, refreshRateConfigs.getCurrentRefreshRate().getFps(), // Below defines the threshold when an offset is considered to be negative, // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For Loading Loading @@ -275,7 +275,7 @@ std::unordered_map<float, PhaseDurations::Offsets> PhaseDurations::initializeOff PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs) : PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs), refreshRateConfigs.getCurrentRefreshRate().fps, refreshRateConfigs.getCurrentRefreshRate().getFps(), getProperty("debug.sf.late.sf.duration").value_or(-1), getProperty("debug.sf.late.app.duration").value_or(-1), getProperty("debug.sf.early.sf.duration").value_or(mSfDuration), Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +38 −45 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( if (explicitContentFramerate != 0) { contentFramerate = explicitContentFramerate; } else if (contentFramerate == 0) { contentFramerate = round<int>(mMaxSupportedRefreshRate->fps); contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps()); } ATRACE_INT("ContentFPS", contentFramerate); Loading Loading @@ -177,7 +177,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( continue; } const auto displayPeriod = scores[i].first->vsyncPeriod; const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod(); const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate); if (layer.vote == LayerVoteType::ExplicitDefault) { const auto layerScore = [&]() { Loading Loading @@ -309,21 +309,30 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) { init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { std::vector<InputConfig> inputConfigs; for (size_t configId = 0; configId < configs.size(); ++configId) { auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup()); inputConfigs.push_back({HwcConfigIndexType(static_cast<int>(configId)), configGroup, configs[configId]->getVsyncPeriod()}); LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast<size_t>(configId.value())); const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, base::StringPrintf("%2.ffps", fps), fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } } init(inputConfigs, currentConfigId); std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentConfigId; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); constructAvailableRefreshRates(); } bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { Loading Loading @@ -406,10 +415,13 @@ void RefreshRateConfigs::getSortedRefreshRateList( std::sort(outRefreshRates->begin(), outRefreshRates->end(), [](const auto refreshRate1, const auto refreshRate2) { if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) { return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; if (refreshRate1->hwcConfig->getVsyncPeriod() != refreshRate2->hwcConfig->getVsyncPeriod()) { return refreshRate1->hwcConfig->getVsyncPeriod() > refreshRate2->hwcConfig->getVsyncPeriod(); } else { return refreshRate1->configGroup > refreshRate2->configGroup; return refreshRate1->hwcConfig->getConfigGroup() > refreshRate2->hwcConfig->getConfigGroup(); } }); } Loading @@ -417,13 +429,20 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup; const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", policy->defaultConfig.value(), group.value(), policy->minRefreshRate, policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate, policy->maxRefreshRate); getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { return (policy->allowGroupSwitching || refreshRate.configGroup == group) && const auto& hwcConfig = refreshRate.hwcConfig; return hwcConfig->getHeight() == defaultConfig->getHeight() && hwcConfig->getWidth() == defaultConfig->getWidth() && hwcConfig->getDpiX() == defaultConfig->getDpiX() && hwcConfig->getDpiY() == defaultConfig->getDpiY() && (policy->allowGroupSwitching || hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate); }, &mAvailableRefreshRates); Loading @@ -440,30 +459,4 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { policy->maxRefreshRate); } // NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor void RefreshRateConfigs::init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS { LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); for (const auto& config : configs) { const float fps = 1e9f / config.vsyncPeriod; mRefreshRates.emplace(config.configId, std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod, config.configGroup, base::StringPrintf("%2.ffps", fps), fps)); if (config.configId == currentHwcConfig) { mCurrentRefreshRate = mRefreshRates.at(config.configId).get(); } } std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentHwcConfig; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); constructAvailableRefreshRates(); } } // namespace android::scheduler
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +38 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include "Scheduler/StrongTyping.h" namespace android::scheduler { class RefreshRateConfigsTest; using namespace std::chrono_literals; enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 }; Loading @@ -49,30 +51,27 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); struct RefreshRate { // The tolerance within which we consider FPS approximately equals. static constexpr float FPS_EPSILON = 0.001f; class RefreshRate { private: // Effectively making the constructor private while allowing // std::make_unique to create the object struct ConstructorTag { explicit ConstructorTag(int) {} }; RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod, HwcConfigGroupType configGroup, std::string name, float fps) : configId(configId), vsyncPeriod(vsyncPeriod), configGroup(configGroup), name(std::move(name)), fps(fps) {} public: RefreshRate(HwcConfigIndexType configId, std::shared_ptr<const HWC2::Display::Config> config, std::string name, float fps, ConstructorTag) : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {} RefreshRate(const RefreshRate&) = delete; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // Vsync period in nanoseconds. const nsecs_t vsyncPeriod; // This configGroup for the config. const HwcConfigGroupType configGroup; // Human readable name of the refresh rate. const std::string name; // Refresh rate in frames per second const float fps = 0; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } const std::string& getName() const { return name; } float getFps() const { return fps; } // Checks whether the fps of this RefreshRate struct is within a given min and max refresh // rate passed in. FPS_EPSILON is applied to the boundaries for approximation. Loading @@ -81,11 +80,27 @@ public: } bool operator!=(const RefreshRate& other) const { return configId != other.configId || vsyncPeriod != other.vsyncPeriod || configGroup != other.configGroup; return configId != other.configId || hwcConfig != other.hwcConfig; } bool operator==(const RefreshRate& other) const { return !(*this != other); } private: friend RefreshRateConfigs; friend RefreshRateConfigsTest; // The tolerance within which we consider FPS approximately equals. static constexpr float FPS_EPSILON = 0.001f; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // The config itself std::shared_ptr<const HWC2::Display::Config> hwcConfig; // Human readable name of the refresh rate. const std::string name; // Refresh rate in frames per second const float fps = 0; }; using AllRefreshRatesMapType = Loading Loading @@ -208,20 +223,10 @@ public: // Stores the current configId the device operates at void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock); struct InputConfig { HwcConfigIndexType configId = HwcConfigIndexType(0); HwcConfigGroupType configGroup = HwcConfigGroupType(0); nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); private: void init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); void constructAvailableRefreshRates() REQUIRES(mLock); void getSortedRefreshRateList( Loading