blob: d8137085dd58f9beda91333cc58ffa452a458d08 [file] [log] [blame]
Ana Krulecb43429d2019-01-09 14:28:51 -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
17#pragma once
18
19#include <algorithm>
20#include <numeric>
21
Ana Krulecb43429d2019-01-09 14:28:51 -080022#include "android-base/stringprintf.h"
23
Ana Krulec4593b692019-01-11 22:07:25 -080024#include "DisplayHardware/HWComposer.h"
25#include "Scheduler/SchedulerUtils.h"
26
Ana Krulecb43429d2019-01-09 14:28:51 -080027namespace android {
28namespace scheduler {
29
30/**
Ady Abraham1902d072019-03-01 17:18:59 -080031 * This class is used to encapsulate configuration for refresh rates. It holds information
Ana Krulecb43429d2019-01-09 14:28:51 -080032 * about available refresh rates on the device, and the mapping between the numbers and human
33 * readable names.
34 */
35class RefreshRateConfigs {
36public:
Steven Thomase9eb1832019-08-28 16:08:35 -070037 // Enum to indicate which vsync rate to run at. Default is the old 60Hz, and performance
Ana Krulecb43429d2019-01-09 14:28:51 -080038 // is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs.
Steven Thomase9eb1832019-08-28 16:08:35 -070039 enum class RefreshRateType { DEFAULT, PERFORMANCE };
Ana Krulecb43429d2019-01-09 14:28:51 -080040
41 struct RefreshRate {
Ana Krulecb43429d2019-01-09 14:28:51 -080042 // This config ID corresponds to the position of the config in the vector that is stored
43 // on the device.
44 int configId;
45 // Human readable name of the refresh rate.
46 std::string name;
Alec Mourifb571ea2019-01-24 18:42:10 -080047 // Refresh rate in frames per second, rounded to the nearest integer.
48 uint32_t fps = 0;
Steven Thomase9eb1832019-08-28 16:08:35 -070049 // Vsync period in nanoseconds.
50 nsecs_t vsyncPeriod;
51 // Hwc config Id (returned from HWC2::Display::Config::getId())
52 hwc2_config_t hwcId;
Ana Krulecb43429d2019-01-09 14:28:51 -080053 };
54
Steven Thomase9eb1832019-08-28 16:08:35 -070055 // Returns true if this device is doing refresh rate switching. This won't change at runtime.
56 bool refreshRateSwitchingSupported() const { return mRefreshRateSwitchingSupported; }
57
58 // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access
59 // from multiple threads. This can only be called if refreshRateSwitching() returns true.
Ana Krulecb43429d2019-01-09 14:28:51 -080060 // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
61 // baking them in.
Steven Thomase9eb1832019-08-28 16:08:35 -070062 const std::map<RefreshRateType, RefreshRate>& getRefreshRateMap() const {
63 LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported);
64 return mRefreshRateMap;
Alec Mouri0a1cc962019-03-14 12:33:02 -070065 }
Ana Krulecb43429d2019-01-09 14:28:51 -080066
Steven Thomase9eb1832019-08-28 16:08:35 -070067 const RefreshRate& getRefreshRateFromType(RefreshRateType type) const {
68 if (!mRefreshRateSwitchingSupported) {
69 return getCurrentRefreshRate().second;
70 } else {
71 auto refreshRate = mRefreshRateMap.find(type);
72 LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end());
73 return refreshRate->second;
74 }
75 }
76
77 std::pair<RefreshRateType, const RefreshRate&> getCurrentRefreshRate() const {
78 int currentConfig = mCurrentConfig;
79 if (mRefreshRateSwitchingSupported) {
80 for (const auto& [type, refresh] : mRefreshRateMap) {
81 if (refresh.configId == currentConfig) {
82 return {type, refresh};
83 }
84 }
85 LOG_ALWAYS_FATAL();
86 }
87 return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]};
88 }
89
90 const RefreshRate& getRefreshRateFromConfigId(int configId) const {
91 LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size());
92 return mRefreshRates[configId];
93 }
94
95 RefreshRateType getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const {
96 if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT;
97
98 for (const auto& [type, refreshRate] : mRefreshRateMap) {
99 if (refreshRate.hwcId == hwcId) {
Ady Abraham796beb02019-04-11 15:23:07 -0700100 return type;
101 }
102 }
103
104 return RefreshRateType::DEFAULT;
105 }
106
Steven Thomase9eb1832019-08-28 16:08:35 -0700107 void setCurrentConfig(int config) {
108 LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size());
109 mCurrentConfig = config;
110 }
Dominik Laskowski22488f62019-03-28 09:53:04 -0700111
Steven Thomase9eb1832019-08-28 16:08:35 -0700112 struct InputConfig {
113 hwc2_config_t hwcId = 0;
114 nsecs_t vsyncPeriod = 0;
115 };
Ana Krulec4593b692019-01-11 22:07:25 -0800116
Steven Thomase9eb1832019-08-28 16:08:35 -0700117 RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
118 int currentConfig) {
119 init(refreshRateSwitching, configs, currentConfig);
120 }
121
122 RefreshRateConfigs(bool refreshRateSwitching,
123 const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
124 int currentConfig) {
125 std::vector<InputConfig> inputConfigs;
126 for (const auto& config : configs) {
127 inputConfigs.push_back({config->getId(), config->getVsyncPeriod()});
Ana Krulec4593b692019-01-11 22:07:25 -0800128 }
Steven Thomase9eb1832019-08-28 16:08:35 -0700129 init(refreshRateSwitching, inputConfigs, currentConfig);
Ana Krulec4593b692019-01-11 22:07:25 -0800130 }
131
Dominik Laskowski22488f62019-03-28 09:53:04 -0700132private:
Steven Thomase9eb1832019-08-28 16:08:35 -0700133 void init(bool refreshRateSwitching, const std::vector<InputConfig>& configs,
134 int currentConfig) {
135 mRefreshRateSwitchingSupported = refreshRateSwitching;
136 LOG_ALWAYS_FATAL_IF(configs.empty());
137 LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size());
138 mCurrentConfig = currentConfig;
139
140 auto buildRefreshRate = [&](int configId) -> RefreshRate {
141 const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod;
142 const float fps = 1e9 / vsyncPeriod;
143 return {configId, base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps),
144 vsyncPeriod, configs[configId].hwcId};
145 };
146
147 for (int i = 0; i < configs.size(); ++i) {
148 mRefreshRates.push_back(buildRefreshRate(i));
149 }
150
151 if (!mRefreshRateSwitchingSupported) return;
152
153 auto findDefaultAndPerfConfigs = [&]() -> std::optional<std::pair<int, int>> {
154 if (configs.size() < 2) {
155 return {};
156 }
157
158 std::vector<const RefreshRate*> sortedRefreshRates;
159 for (const auto& refreshRate : mRefreshRates) {
160 sortedRefreshRates.push_back(&refreshRate);
161 }
162 std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(),
163 [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) {
164 return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
165 });
166
167 // When the configs are ordered by the resync rate, we assume that
168 // the first one is DEFAULT and the second one is PERFORMANCE,
169 // i.e. the higher rate.
170 if (sortedRefreshRates[0]->vsyncPeriod == 0 ||
171 sortedRefreshRates[1]->vsyncPeriod == 0) {
172 return {};
173 }
174
175 return std::pair<int, int>(sortedRefreshRates[0]->configId,
176 sortedRefreshRates[1]->configId);
177 };
178
179 auto defaultAndPerfConfigs = findDefaultAndPerfConfigs();
180 if (!defaultAndPerfConfigs) {
181 mRefreshRateSwitchingSupported = false;
182 return;
183 }
184
185 mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first];
186 mRefreshRateMap[RefreshRateType::PERFORMANCE] =
187 mRefreshRates[defaultAndPerfConfigs->second];
188 }
189
190 // Whether this device is doing refresh rate switching or not. This must not change after this
191 // object is initialized.
192 bool mRefreshRateSwitchingSupported;
193 // The list of refresh rates, indexed by display config ID. This must not change after this
194 // object is initialized.
195 std::vector<RefreshRate> mRefreshRates;
196 // The mapping of refresh rate type to RefreshRate. This must not change after this object is
197 // initialized.
198 std::map<RefreshRateType, RefreshRate> mRefreshRateMap;
199 // The ID of the current config. This will change at runtime. This is set by SurfaceFlinger on
200 // the main thread, and read by the Scheduler (and other objects) on other threads, so it's
201 // atomic.
202 std::atomic<int> mCurrentConfig;
Ana Krulecb43429d2019-01-09 14:28:51 -0800203};
204
205} // namespace scheduler
Alec Mourifb571ea2019-01-24 18:42:10 -0800206} // namespace android