blob: 7dc98cce9449750c6738679410dff65da35a03c5 [file] [log] [blame]
Ady Abrahamb4b1e0a2019-11-20 18:25:35 -08001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "RefreshRateConfigs.h"
17
18namespace android::scheduler {
19using RefreshRate = RefreshRateConfigs::RefreshRate;
20using RefreshRateType = RefreshRateConfigs::RefreshRateType;
21
22// Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access
23// from multiple threads. This can only be called if refreshRateSwitching() returns true.
24// TODO(b/122916473): Get this information from configs prepared by vendors, instead of
25// baking them in.
26const std::map<RefreshRateType, RefreshRate>& RefreshRateConfigs::getRefreshRateMap() const {
27 LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported);
28 return mRefreshRateMap;
29}
30
31const RefreshRate& RefreshRateConfigs::getRefreshRateFromType(RefreshRateType type) const {
32 if (!mRefreshRateSwitchingSupported) {
33 return getCurrentRefreshRate().second;
34 } else {
35 auto refreshRate = mRefreshRateMap.find(type);
36 LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end());
37 return refreshRate->second;
38 }
39}
40
41std::pair<RefreshRateType, const RefreshRate&> RefreshRateConfigs::getCurrentRefreshRate() const {
42 int currentConfig = mCurrentConfig;
43 if (mRefreshRateSwitchingSupported) {
44 for (const auto& [type, refresh] : mRefreshRateMap) {
45 if (refresh.configId == currentConfig) {
46 return {type, refresh};
47 }
48 }
49 LOG_ALWAYS_FATAL();
50 }
51 return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]};
52}
53
54const RefreshRate& RefreshRateConfigs::getRefreshRateFromConfigId(int configId) const {
55 LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size());
56 return mRefreshRates[configId];
57}
58
59RefreshRateType RefreshRateConfigs::getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const {
60 if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT;
61
62 for (const auto& [type, refreshRate] : mRefreshRateMap) {
63 if (refreshRate.hwcId == hwcId) {
64 return type;
65 }
66 }
67
68 return RefreshRateType::DEFAULT;
69}
70
71void RefreshRateConfigs::setCurrentConfig(int config) {
72 LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size());
73 mCurrentConfig = config;
74}
75
76RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching,
77 const std::vector<InputConfig>& configs, int currentConfig) {
78 init(refreshRateSwitching, configs, currentConfig);
79}
80
81RefreshRateConfigs::RefreshRateConfigs(
82 bool refreshRateSwitching,
83 const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
84 int currentConfig) {
85 std::vector<InputConfig> inputConfigs;
86 for (const auto& config : configs) {
87 inputConfigs.push_back({config->getId(), config->getVsyncPeriod()});
88 }
89 init(refreshRateSwitching, inputConfigs, currentConfig);
90}
91
92void RefreshRateConfigs::init(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
93 int currentConfig) {
94 mRefreshRateSwitchingSupported = refreshRateSwitching;
95 LOG_ALWAYS_FATAL_IF(configs.empty());
96 LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size());
97 mCurrentConfig = currentConfig;
98
99 auto buildRefreshRate = [&](int configId) -> RefreshRate {
100 const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod;
101 const float fps = 1e9 / vsyncPeriod;
102 return {configId, base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps),
103 vsyncPeriod, configs[configId].hwcId};
104 };
105
106 for (int i = 0; i < configs.size(); ++i) {
107 mRefreshRates.push_back(buildRefreshRate(i));
108 }
109
110 if (!mRefreshRateSwitchingSupported) return;
111
112 auto findDefaultAndPerfConfigs = [&]() -> std::optional<std::pair<int, int>> {
113 if (configs.size() < 2) {
114 return {};
115 }
116
117 std::vector<const RefreshRate*> sortedRefreshRates;
118 for (const auto& refreshRate : mRefreshRates) {
119 sortedRefreshRates.push_back(&refreshRate);
120 }
121 std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(),
122 [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) {
123 return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
124 });
125
126 // When the configs are ordered by the resync rate, we assume that
127 // the first one is DEFAULT and the second one is PERFORMANCE,
128 // i.e. the higher rate.
129 if (sortedRefreshRates[0]->vsyncPeriod == 0 || sortedRefreshRates[1]->vsyncPeriod == 0) {
130 return {};
131 }
132
133 return std::pair<int, int>(sortedRefreshRates[0]->configId,
134 sortedRefreshRates[1]->configId);
135 };
136
137 auto defaultAndPerfConfigs = findDefaultAndPerfConfigs();
138 if (!defaultAndPerfConfigs) {
139 mRefreshRateSwitchingSupported = false;
140 return;
141 }
142
143 mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first];
144 mRefreshRateMap[RefreshRateType::PERFORMANCE] = mRefreshRates[defaultAndPerfConfigs->second];
145}
146
147} // namespace android::scheduler