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