xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/DisplayHardware/DisplayMode.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
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 
19 #include <cstddef>
20 #include <memory>
21 
22 #include <android-base/stringprintf.h>
23 #include <android/configuration.h>
24 #include <ftl/mixins.h>
25 #include <ftl/small_map.h>
26 #include <ui/DisplayId.h>
27 #include <ui/DisplayMode.h>
28 #include <ui/Size.h>
29 #include <utils/Timers.h>
30 
31 #include <common/FlagManager.h>
32 #include <scheduler/Fps.h>
33 
34 #include "Hal.h"
35 
36 namespace android {
37 
38 using aidl::android::hardware::graphics::composer3::OutputType;
39 namespace hal = android::hardware::graphics::composer::hal;
40 
41 class DisplayMode;
42 using DisplayModePtr = std::shared_ptr<const DisplayMode>;
43 
44 // Prevent confusion with fps_approx_ops on the underlying Fps.
45 bool operator<(const DisplayModePtr&, const DisplayModePtr&) = delete;
46 bool operator>(const DisplayModePtr&, const DisplayModePtr&) = delete;
47 bool operator<=(const DisplayModePtr&, const DisplayModePtr&) = delete;
48 bool operator>=(const DisplayModePtr&, const DisplayModePtr&) = delete;
49 
50 struct DisplayModeId : ftl::DefaultConstructible<DisplayModeId, ui::DisplayModeId>,
51                        ftl::Incrementable<DisplayModeId>,
52                        ftl::Equatable<DisplayModeId>,
53                        ftl::Orderable<DisplayModeId> {
54     using DefaultConstructible::DefaultConstructible;
55 };
56 
57 using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>;
58 using DisplayModeIterator = DisplayModes::const_iterator;
59 
60 class DisplayMode {
61 public:
62     class Builder {
63     public:
Builder(hal::HWConfigId id)64         explicit Builder(hal::HWConfigId id) : mDisplayMode(new DisplayMode(id)) {}
65 
build()66         DisplayModePtr build() {
67             return std::const_pointer_cast<const DisplayMode>(std::move(mDisplayMode));
68         }
69 
setId(DisplayModeId id)70         Builder& setId(DisplayModeId id) {
71             mDisplayMode->mId = id;
72             return *this;
73         }
74 
setPhysicalDisplayId(PhysicalDisplayId id)75         Builder& setPhysicalDisplayId(PhysicalDisplayId id) {
76             mDisplayMode->mPhysicalDisplayId = id;
77             return *this;
78         }
79 
setResolution(ui::Size resolution)80         Builder& setResolution(ui::Size resolution) {
81             mDisplayMode->mResolution = resolution;
82             return *this;
83         }
84 
setVsyncPeriod(nsecs_t vsyncPeriod)85         Builder& setVsyncPeriod(nsecs_t vsyncPeriod) {
86             mDisplayMode->mVsyncRate = Fps::fromPeriodNsecs(vsyncPeriod);
87             return *this;
88         }
89 
setVrrConfig(std::optional<hal::VrrConfig> vrrConfig)90         Builder& setVrrConfig(std::optional<hal::VrrConfig> vrrConfig) {
91             mDisplayMode->mVrrConfig = std::move(vrrConfig);
92             return *this;
93         }
94 
setDpiX(float dpiX)95         Builder& setDpiX(float dpiX) {
96             if (dpiX == -1.f) {
97                 mDisplayMode->mDpi.x = getDefaultDensity();
98             } else {
99                 mDisplayMode->mDpi.x = dpiX;
100             }
101             return *this;
102         }
103 
setDpiY(float dpiY)104         Builder& setDpiY(float dpiY) {
105             if (dpiY == -1.f) {
106                 mDisplayMode->mDpi.y = getDefaultDensity();
107             } else {
108                 mDisplayMode->mDpi.y = dpiY;
109             }
110             return *this;
111         }
112 
setGroup(int32_t group)113         Builder& setGroup(int32_t group) {
114             mDisplayMode->mGroup = group;
115             return *this;
116         }
117 
setHdrOutputType(OutputType type)118         Builder& setHdrOutputType(OutputType type) {
119             mDisplayMode->mHdrOutputType = type;
120             return *this;
121         }
122 
123     private:
getDefaultDensity()124         float getDefaultDensity() {
125             // Default density is based on TVs: 1080p displays get XHIGH density, lower-
126             // resolution displays get TV density. Maybe eventually we'll need to update
127             // it for 4k displays, though hopefully those will just report accurate DPI
128             // information to begin with. This is also used for virtual displays and
129             // older HWC implementations, so be careful about orientation.
130 
131             if (std::max(mDisplayMode->getWidth(), mDisplayMode->getHeight()) >= 1080) {
132                 return ACONFIGURATION_DENSITY_XHIGH;
133             } else {
134                 return ACONFIGURATION_DENSITY_TV;
135             }
136         }
137 
138         std::shared_ptr<DisplayMode> mDisplayMode;
139     };
140 
getId()141     DisplayModeId getId() const { return mId; }
142 
getHwcId()143     hal::HWConfigId getHwcId() const { return mHwcId; }
getPhysicalDisplayId()144     PhysicalDisplayId getPhysicalDisplayId() const { return mPhysicalDisplayId; }
145 
getResolution()146     ui::Size getResolution() const { return mResolution; }
getWidth()147     int32_t getWidth() const { return mResolution.getWidth(); }
getHeight()148     int32_t getHeight() const { return mResolution.getHeight(); }
149 
150     // Peak refresh rate represents the highest refresh rate that can be used
151     // for the presentation.
getPeakFps()152     Fps getPeakFps() const {
153         return FlagManager::getInstance().vrr_config() && mVrrConfig
154                 ? Fps::fromPeriodNsecs(mVrrConfig->minFrameIntervalNs)
155                 : mVsyncRate;
156     }
157 
getVsyncRate()158     Fps getVsyncRate() const { return mVsyncRate; }
159 
getVrrConfig()160     std::optional<hal::VrrConfig> getVrrConfig() const { return mVrrConfig; }
161 
162     struct Dpi {
163         float x = -1;
164         float y = -1;
165 
166         bool operator==(Dpi other) const { return x == other.x && y == other.y; }
167     };
168 
getDpi()169     Dpi getDpi() const { return mDpi; }
170 
171     // Switches between modes in the same group are seamless, i.e.
172     // without visual interruptions such as a black screen.
getGroup()173     int32_t getGroup() const { return mGroup; }
174 
getHdrOutputType()175     OutputType getHdrOutputType() const { return mHdrOutputType; }
176 
177 private:
DisplayMode(hal::HWConfigId id)178     explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
179 
180     const hal::HWConfigId mHwcId;
181     DisplayModeId mId;
182 
183     PhysicalDisplayId mPhysicalDisplayId;
184 
185     ui::Size mResolution;
186     Fps mVsyncRate;
187     Dpi mDpi;
188     int32_t mGroup = -1;
189     std::optional<hal::VrrConfig> mVrrConfig;
190     OutputType mHdrOutputType;
191 };
192 
equalsExceptDisplayModeId(const DisplayMode & lhs,const DisplayMode & rhs)193 inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
194     return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
195             lhs.getVsyncRate().getPeriodNsecs() == rhs.getVsyncRate().getPeriodNsecs() &&
196             lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup() &&
197             lhs.getVrrConfig() == rhs.getVrrConfig() &&
198             lhs.getHdrOutputType() == rhs.getHdrOutputType();
199 }
200 
to_string(const DisplayMode & mode)201 inline std::string to_string(const DisplayMode& mode) {
202     return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, vsyncRate=%s, "
203                               "dpi=%.2fx%.2f, group=%d, vrrConfig=%s, supportedHdrTypes=%s}",
204                               ftl::to_underlying(mode.getId()), mode.getHwcId(), mode.getWidth(),
205                               mode.getHeight(), to_string(mode.getVsyncRate()).c_str(),
206                               mode.getDpi().x, mode.getDpi().y, mode.getGroup(),
207                               to_string(mode.getVrrConfig()).c_str(),
208                               toString(mode.getHdrOutputType()).c_str());
209 }
210 
211 template <typename... DisplayModePtrs>
makeModes(const DisplayModePtrs &...modePtrs)212 inline DisplayModes makeModes(const DisplayModePtrs&... modePtrs) {
213     DisplayModes modes;
214     // Note: The omission of std::move(modePtrs) is intentional, because order of evaluation for
215     // arguments is unspecified.
216     (modes.try_emplace(modePtrs->getId(), modePtrs), ...);
217     return modes;
218 }
219 
220 } // namespace android
221