blob: c43d5852700ddbb9b99d6b09f7beca50e657da76 [file] [log] [blame]
Dominik Laskowski6e465152022-09-28 11:00:25 -04001/*
2 * Copyright 2024 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#undef LOG_TAG
18#define LOG_TAG "DisplayModeController"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "Display/DisplayModeController.h"
22#include "Display/DisplaySnapshot.h"
Dominik Laskowski5c989f52024-04-11 13:57:14 -040023#include "DisplayHardware/HWComposer.h"
Dominik Laskowski6e465152022-09-28 11:00:25 -040024
Dominik Laskowski5c989f52024-04-11 13:57:14 -040025#include <common/FlagManager.h>
26#include <ftl/concat.h>
27#include <ftl/expected.h>
Dominik Laskowski6e465152022-09-28 11:00:25 -040028#include <log/log.h>
29
30namespace android::display {
31
Dominik Laskowski5c989f52024-04-11 13:57:14 -040032template <size_t N>
33inline std::string DisplayModeController::Display::concatId(const char (&str)[N]) const {
34 return std::string(ftl::Concat(str, ' ', snapshot.get().displayId().value).str());
35}
36
37DisplayModeController::Display::Display(DisplaySnapshotRef snapshot,
38 RefreshRateSelectorPtr selectorPtr)
39 : snapshot(snapshot),
40 selectorPtr(std::move(selectorPtr)),
41 pendingModeFpsTrace(concatId("PendingModeFps")),
42 activeModeFpsTrace(concatId("ActiveModeFps")),
43 renderRateFpsTrace(concatId("RenderRateFps")),
44 hasDesiredModeTrace(concatId("HasDesiredMode"), false) {}
45
46void DisplayModeController::registerDisplay(PhysicalDisplayId displayId,
47 DisplaySnapshotRef snapshotRef,
48 RefreshRateSelectorPtr selectorPtr) {
49 std::lock_guard lock(mDisplayLock);
50 mDisplays.emplace_or_replace(displayId, std::make_unique<Display>(snapshotRef, selectorPtr));
51}
52
Dominik Laskowski6e465152022-09-28 11:00:25 -040053void DisplayModeController::registerDisplay(DisplaySnapshotRef snapshotRef,
54 DisplayModeId activeModeId,
55 scheduler::RefreshRateSelector::Config config) {
56 const auto& snapshot = snapshotRef.get();
57 const auto displayId = snapshot.displayId();
58
Dominik Laskowski5c989f52024-04-11 13:57:14 -040059 std::lock_guard lock(mDisplayLock);
60 mDisplays.emplace_or_replace(displayId,
61 std::make_unique<Display>(snapshotRef, snapshot.displayModes(),
62 activeModeId, config));
Dominik Laskowski6e465152022-09-28 11:00:25 -040063}
64
65void DisplayModeController::unregisterDisplay(PhysicalDisplayId displayId) {
Dominik Laskowski5c989f52024-04-11 13:57:14 -040066 std::lock_guard lock(mDisplayLock);
Dominik Laskowski6e465152022-09-28 11:00:25 -040067 const bool ok = mDisplays.erase(displayId);
68 ALOGE_IF(!ok, "%s: Unknown display %s", __func__, to_string(displayId).c_str());
69}
70
Dominik Laskowski5c989f52024-04-11 13:57:14 -040071auto DisplayModeController::selectorPtrFor(PhysicalDisplayId displayId) const
72 -> RefreshRateSelectorPtr {
73 std::lock_guard lock(mDisplayLock);
Dominik Laskowski6e465152022-09-28 11:00:25 -040074 return mDisplays.get(displayId)
Dominik Laskowski5c989f52024-04-11 13:57:14 -040075 .transform([](const DisplayPtr& displayPtr) { return displayPtr->selectorPtr; })
Dominik Laskowski6e465152022-09-28 11:00:25 -040076 .value_or(nullptr);
77}
78
Dominik Laskowski5c989f52024-04-11 13:57:14 -040079auto DisplayModeController::setDesiredMode(PhysicalDisplayId displayId,
80 DisplayModeRequest&& desiredMode) -> DesiredModeAction {
81 std::lock_guard lock(mDisplayLock);
82 const auto& displayPtr =
83 FTL_EXPECT(mDisplays.get(displayId).ok_or(DesiredModeAction::None)).get();
84
85 {
Vishnu Nairbe0ad902024-06-27 23:38:43 +000086 SFTRACE_NAME(displayPtr->concatId(__func__).c_str());
Dominik Laskowski5c989f52024-04-11 13:57:14 -040087 ALOGD("%s %s", displayPtr->concatId(__func__).c_str(), to_string(desiredMode).c_str());
88
89 std::scoped_lock lock(displayPtr->desiredModeLock);
90
91 if (auto& desiredModeOpt = displayPtr->desiredModeOpt) {
92 // A mode transition was already scheduled, so just override the desired mode.
93 const bool emitEvent = desiredModeOpt->emitEvent;
94 const bool force = desiredModeOpt->force;
95 desiredModeOpt = std::move(desiredMode);
96 desiredModeOpt->emitEvent |= emitEvent;
97 if (FlagManager::getInstance().connected_display()) {
98 desiredModeOpt->force |= force;
99 }
100 return DesiredModeAction::None;
101 }
102
103 // If the desired mode is already active...
104 const auto activeMode = displayPtr->selectorPtr->getActiveMode();
105 if (const auto& desiredModePtr = desiredMode.mode.modePtr;
106 !desiredMode.force && activeMode.modePtr->getId() == desiredModePtr->getId()) {
107 if (activeMode == desiredMode.mode) {
108 return DesiredModeAction::None;
109 }
110
111 // ...but the render rate changed:
112 setActiveModeLocked(displayId, desiredModePtr->getId(), desiredModePtr->getVsyncRate(),
113 desiredMode.mode.fps);
114 return DesiredModeAction::InitiateRenderRateSwitch;
115 }
116
117 // Restore peak render rate to schedule the next frame as soon as possible.
118 setActiveModeLocked(displayId, activeMode.modePtr->getId(),
119 activeMode.modePtr->getVsyncRate(), activeMode.modePtr->getPeakFps());
120
121 // Initiate a mode change.
122 displayPtr->desiredModeOpt = std::move(desiredMode);
123 displayPtr->hasDesiredModeTrace = true;
124 }
125
126 return DesiredModeAction::InitiateDisplayModeSwitch;
127}
128
129auto DisplayModeController::getDesiredMode(PhysicalDisplayId displayId) const
130 -> DisplayModeRequestOpt {
131 std::lock_guard lock(mDisplayLock);
132 const auto& displayPtr =
133 FTL_EXPECT(mDisplays.get(displayId).ok_or(DisplayModeRequestOpt())).get();
134
135 {
136 std::scoped_lock lock(displayPtr->desiredModeLock);
137 return displayPtr->desiredModeOpt;
138 }
139}
140
141auto DisplayModeController::getPendingMode(PhysicalDisplayId displayId) const
142 -> DisplayModeRequestOpt {
143 std::lock_guard lock(mDisplayLock);
144 const auto& displayPtr =
145 FTL_EXPECT(mDisplays.get(displayId).ok_or(DisplayModeRequestOpt())).get();
146
147 {
148 std::scoped_lock lock(displayPtr->desiredModeLock);
149 return displayPtr->pendingModeOpt;
150 }
151}
152
153bool DisplayModeController::isModeSetPending(PhysicalDisplayId displayId) const {
154 std::lock_guard lock(mDisplayLock);
155 const auto& displayPtr = FTL_EXPECT(mDisplays.get(displayId).ok_or(false)).get();
156
157 {
158 std::scoped_lock lock(displayPtr->desiredModeLock);
159 return displayPtr->isModeSetPending;
160 }
161}
162
163scheduler::FrameRateMode DisplayModeController::getActiveMode(PhysicalDisplayId displayId) const {
164 return selectorPtrFor(displayId)->getActiveMode();
165}
166
167void DisplayModeController::clearDesiredMode(PhysicalDisplayId displayId) {
168 std::lock_guard lock(mDisplayLock);
169 const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
170
171 {
172 std::scoped_lock lock(displayPtr->desiredModeLock);
173 displayPtr->desiredModeOpt.reset();
174 displayPtr->hasDesiredModeTrace = false;
175 }
176}
177
178bool DisplayModeController::initiateModeChange(PhysicalDisplayId displayId,
179 DisplayModeRequest&& desiredMode,
180 const hal::VsyncPeriodChangeConstraints& constraints,
181 hal::VsyncPeriodChangeTimeline& outTimeline) {
182 std::lock_guard lock(mDisplayLock);
183 const auto& displayPtr = FTL_EXPECT(mDisplays.get(displayId).ok_or(false)).get();
184
185 // TODO: b/255635711 - Flow the DisplayModeRequest through the desired/pending/active states.
186 // For now, `desiredMode` and `desiredModeOpt` are one and the same, but the latter is not
187 // cleared until the next `SF::initiateDisplayModeChanges`. However, the desired mode has been
188 // consumed at this point, so clear the `force` flag to prevent an endless loop of
189 // `initiateModeChange`.
190 if (FlagManager::getInstance().connected_display()) {
191 std::scoped_lock lock(displayPtr->desiredModeLock);
192 if (displayPtr->desiredModeOpt) {
193 displayPtr->desiredModeOpt->force = false;
194 }
195 }
196
197 displayPtr->pendingModeOpt = std::move(desiredMode);
198 displayPtr->isModeSetPending = true;
199
200 const auto& mode = *displayPtr->pendingModeOpt->mode.modePtr;
201
202 if (mComposerPtr->setActiveModeWithConstraints(displayId, mode.getHwcId(), constraints,
203 &outTimeline) != OK) {
204 return false;
205 }
206
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000207 SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue());
Dominik Laskowski5c989f52024-04-11 13:57:14 -0400208 return true;
209}
210
211void DisplayModeController::finalizeModeChange(PhysicalDisplayId displayId, DisplayModeId modeId,
212 Fps vsyncRate, Fps renderFps) {
213 std::lock_guard lock(mDisplayLock);
214 setActiveModeLocked(displayId, modeId, vsyncRate, renderFps);
215
216 const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
217 displayPtr->isModeSetPending = false;
218}
219
220void DisplayModeController::setActiveMode(PhysicalDisplayId displayId, DisplayModeId modeId,
221 Fps vsyncRate, Fps renderFps) {
222 std::lock_guard lock(mDisplayLock);
223 setActiveModeLocked(displayId, modeId, vsyncRate, renderFps);
224}
225
226void DisplayModeController::setActiveModeLocked(PhysicalDisplayId displayId, DisplayModeId modeId,
227 Fps vsyncRate, Fps renderFps) {
228 const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
229
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000230 SFTRACE_INT(displayPtr->activeModeFpsTrace.c_str(), vsyncRate.getIntValue());
231 SFTRACE_INT(displayPtr->renderRateFpsTrace.c_str(), renderFps.getIntValue());
Dominik Laskowski5c989f52024-04-11 13:57:14 -0400232
233 displayPtr->selectorPtr->setActiveMode(modeId, renderFps);
234
235 if (mActiveModeListener) {
236 mActiveModeListener(displayId, vsyncRate, renderFps);
237 }
238}
239
Dominik Laskowski6e465152022-09-28 11:00:25 -0400240} // namespace android::display