blob: 422513be9bf3890288fcc83c6226b5d504ad2947 [file] [log] [blame]
Marin Shalamanov3ea1d602020-12-16 19:59:39 +01001/*
2 * Copyright 2020 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
Dominik Laskowskif6b4ba62021-11-09 12:46:10 -080019#include <cstddef>
20#include <memory>
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010021
Marin Shalamanov5801c942020-12-17 17:00:13 +010022#include <android-base/stringprintf.h>
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010023#include <android/configuration.h>
Dominik Laskowskib0054a22022-03-03 09:03:06 -080024#include <ftl/small_map.h>
Ady Abraham5e7ee862021-06-23 17:43:41 -070025#include <ui/DisplayId.h>
Marin Shalamanov228f46b2021-01-28 21:11:45 +010026#include <ui/DisplayMode.h>
Marin Shalamanov045b7002021-01-07 16:56:24 +010027#include <ui/Size.h>
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010028#include <utils/Timers.h>
29
Dominik Laskowskif6b4ba62021-11-09 12:46:10 -080030#include <scheduler/Fps.h>
31
32#include "DisplayHardware/Hal.h"
33#include "Scheduler/StrongTyping.h"
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010034
ramindania04b8a52023-08-07 18:49:47 -070035#include <com_android_graphics_surfaceflinger_flags.h>
36
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010037namespace android {
38
39namespace hal = android::hardware::graphics::composer::hal;
40
41class DisplayMode;
42using DisplayModePtr = std::shared_ptr<const DisplayMode>;
Dominik Laskowskib0054a22022-03-03 09:03:06 -080043
44// Prevent confusion with fps_approx_ops on the underlying Fps.
45bool operator<(const DisplayModePtr&, const DisplayModePtr&) = delete;
46bool operator>(const DisplayModePtr&, const DisplayModePtr&) = delete;
47bool operator<=(const DisplayModePtr&, const DisplayModePtr&) = delete;
48bool operator>=(const DisplayModePtr&, const DisplayModePtr&) = delete;
49
50using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare>;
51
52using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>;
53using DisplayModeIterator = DisplayModes::const_iterator;
ramindania04b8a52023-08-07 18:49:47 -070054using namespace com::android::graphics::surfaceflinger;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010055
56class DisplayMode {
57public:
58 class Builder {
59 public:
60 explicit Builder(hal::HWConfigId id) : mDisplayMode(new DisplayMode(id)) {}
61
62 DisplayModePtr build() {
63 return std::const_pointer_cast<const DisplayMode>(std::move(mDisplayMode));
64 }
65
Marin Shalamanov23c44202020-12-22 19:09:20 +010066 Builder& setId(DisplayModeId id) {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010067 mDisplayMode->mId = id;
68 return *this;
69 }
70
Ady Abraham5e7ee862021-06-23 17:43:41 -070071 Builder& setPhysicalDisplayId(PhysicalDisplayId id) {
72 mDisplayMode->mPhysicalDisplayId = id;
73 return *this;
74 }
75
Dominik Laskowskib0054a22022-03-03 09:03:06 -080076 Builder& setResolution(ui::Size resolution) {
77 mDisplayMode->mResolution = resolution;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010078 return *this;
79 }
80
Dominik Laskowskib0054a22022-03-03 09:03:06 -080081 Builder& setVsyncPeriod(nsecs_t vsyncPeriod) {
ramindania04b8a52023-08-07 18:49:47 -070082 mDisplayMode->mVsyncRate = Fps::fromPeriodNsecs(vsyncPeriod);
83 return *this;
84 }
85
86 Builder& setVrrConfig(std::optional<hal::VrrConfig> vrrConfig) {
87 mDisplayMode->mVrrConfig = std::move(vrrConfig);
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010088 return *this;
89 }
90
ramindani0cd1d8d2023-06-13 13:43:23 -070091 Builder& setDpiX(float dpiX) {
92 if (dpiX == -1.f) {
Dominik Laskowskib0054a22022-03-03 09:03:06 -080093 mDisplayMode->mDpi.x = getDefaultDensity();
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010094 } else {
ramindani0cd1d8d2023-06-13 13:43:23 -070095 mDisplayMode->mDpi.x = dpiX;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +010096 }
97 return *this;
98 }
99
ramindani0cd1d8d2023-06-13 13:43:23 -0700100 Builder& setDpiY(float dpiY) {
101 if (dpiY == -1.f) {
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800102 mDisplayMode->mDpi.y = getDefaultDensity();
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100103 } else {
ramindani0cd1d8d2023-06-13 13:43:23 -0700104 mDisplayMode->mDpi.y = dpiY;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100105 }
106 return *this;
107 }
108
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100109 Builder& setGroup(int32_t group) {
110 mDisplayMode->mGroup = group;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100111 return *this;
112 }
113
114 private:
115 float getDefaultDensity() {
116 // Default density is based on TVs: 1080p displays get XHIGH density, lower-
117 // resolution displays get TV density. Maybe eventually we'll need to update
118 // it for 4k displays, though hopefully those will just report accurate DPI
119 // information to begin with. This is also used for virtual displays and
120 // older HWC implementations, so be careful about orientation.
121
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800122 if (std::max(mDisplayMode->getWidth(), mDisplayMode->getHeight()) >= 1080) {
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100123 return ACONFIGURATION_DENSITY_XHIGH;
124 } else {
125 return ACONFIGURATION_DENSITY_TV;
126 }
127 }
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800128
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100129 std::shared_ptr<DisplayMode> mDisplayMode;
130 };
131
Marin Shalamanov23c44202020-12-22 19:09:20 +0100132 DisplayModeId getId() const { return mId; }
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800133
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100134 hal::HWConfigId getHwcId() const { return mHwcId; }
Ady Abraham5e7ee862021-06-23 17:43:41 -0700135 PhysicalDisplayId getPhysicalDisplayId() const { return mPhysicalDisplayId; }
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100136
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800137 ui::Size getResolution() const { return mResolution; }
138 int32_t getWidth() const { return mResolution.getWidth(); }
139 int32_t getHeight() const { return mResolution.getHeight(); }
140
ramindania04b8a52023-08-07 18:49:47 -0700141 // Peak refresh rate represents the highest refresh rate that can be used
142 // for the presentation.
143 Fps getPeakFps() const {
144 return flags::vrr_config() && mVrrConfig
145 ? Fps::fromPeriodNsecs(mVrrConfig->minFrameIntervalNs)
146 : mVsyncRate;
147 }
148
149 Fps getVsyncRate() const { return mVsyncRate; }
150
151 std::optional<hal::VrrConfig> getVrrConfig() const { return mVrrConfig; }
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800152
153 struct Dpi {
154 float x = -1;
155 float y = -1;
156
157 bool operator==(Dpi other) const { return x == other.x && y == other.y; }
158 };
159
160 Dpi getDpi() const { return mDpi; }
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100161
162 // Switches between modes in the same group are seamless, i.e.
163 // without visual interruptions such as a black screen.
164 int32_t getGroup() const { return mGroup; }
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100165
166private:
167 explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
168
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800169 const hal::HWConfigId mHwcId;
Marin Shalamanov23c44202020-12-22 19:09:20 +0100170 DisplayModeId mId;
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800171
Ady Abraham5e7ee862021-06-23 17:43:41 -0700172 PhysicalDisplayId mPhysicalDisplayId;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100173
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800174 ui::Size mResolution;
ramindania04b8a52023-08-07 18:49:47 -0700175 Fps mVsyncRate;
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800176 Dpi mDpi;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100177 int32_t mGroup = -1;
ramindania04b8a52023-08-07 18:49:47 -0700178 std::optional<hal::VrrConfig> mVrrConfig;
Marin Shalamanov3ea1d602020-12-16 19:59:39 +0100179};
180
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800181inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
182 return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
ramindania04b8a52023-08-07 18:49:47 -0700183 lhs.getVsyncRate().getPeriodNsecs() == rhs.getVsyncRate().getPeriodNsecs() &&
184 lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup();
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800185}
186
Marin Shalamanov5801c942020-12-17 17:00:13 +0100187inline std::string to_string(const DisplayMode& mode) {
ramindania04b8a52023-08-07 18:49:47 -0700188 return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, vsyncRate=%s, "
189 "dpi=%.2fx%.2f, group=%d, vrrConfig=%s}",
Marin Shalamanov5801c942020-12-17 17:00:13 +0100190 mode.getId().value(), mode.getHwcId(), mode.getWidth(),
ramindania04b8a52023-08-07 18:49:47 -0700191 mode.getHeight(), to_string(mode.getVsyncRate()).c_str(),
192 mode.getDpi().x, mode.getDpi().y, mode.getGroup(),
193 to_string(mode.getVrrConfig()).c_str());
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800194}
195
196template <typename... DisplayModePtrs>
197inline DisplayModes makeModes(const DisplayModePtrs&... modePtrs) {
198 DisplayModes modes;
199 // Note: The omission of std::move(modePtrs) is intentional, because order of evaluation for
200 // arguments is unspecified.
201 (modes.try_emplace(modePtrs->getId(), modePtrs), ...);
202 return modes;
Marin Shalamanov5801c942020-12-17 17:00:13 +0100203}
204
Dominik Laskowskif6b4ba62021-11-09 12:46:10 -0800205} // namespace android