1 /*
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 #include <apex/display.h>
18 #include <gui/SurfaceComposerClient.h>
19 #include <ui/DisplayMode.h>
20 #include <ui/DynamicDisplayInfo.h>
21 #include <ui/GraphicTypes.h>
22 #include <ui/PixelFormat.h>
23 #include <ui/StaticDisplayInfo.h>
24
25 #include <algorithm>
26 #include <optional>
27 #include <type_traits>
28 #include <vector>
29
30 namespace android::display::impl {
31
32 /**
33 * Implementation of ADisplayConfig
34 */
35 struct DisplayConfigImpl {
36 /**
37 * The ID of the display configuration.
38 */
39 size_t id;
40
41 /**
42 * The width in pixels of the display configuration.
43 */
44 int32_t width{0};
45
46 /**
47 * The height in pixels of the display configuration.
48 */
49
50 int32_t height{0};
51
52 /**
53 * The display density.
54 */
55 float density{0};
56
57 /**
58 * The refresh rate of the display configuration, in frames per second.
59 */
60 float fps{0.0};
61
62 /**
63 * The vsync offset at which surfaceflinger runs, in nanoseconds.
64 */
65 int64_t sfOffset{0};
66
67 /**
68 * The vsync offset at which applications run, in nanoseconds.
69 */
70 int64_t appOffset{0};
71 };
72
73 // DisplayConfigImpl allocation is not managed through C++ memory apis, so
74 // preventing calling the destructor here.
75 static_assert(std::is_trivially_destructible<DisplayConfigImpl>::value);
76
77 /**
78 * Implementation of ADisplay
79 */
80 struct DisplayImpl {
81 /**
82 * A physical display ID, unique to this display.
83 */
84 PhysicalDisplayId id;
85
86 /**
87 * The type of the display, i.e. whether it is an internal or external
88 * display.
89 */
90 ADisplayType type;
91
92 /**
93 * The preferred WCG dataspace
94 */
95 ADataSpace wcgDataspace;
96
97 /**
98 * The preferred WCG pixel format
99 */
100 AHardwareBuffer_Format wcgPixelFormat;
101
102 /**
103 * Number of supported configs
104 */
105 size_t numConfigs;
106
107 /**
108 * Set of supported configs by this display.
109 */
110 DisplayConfigImpl* configs;
111 };
112
113 // DisplayImpl allocation is not managed through C++ memory apis, so
114 // preventing calling the destructor here.
115 static_assert(std::is_trivially_destructible<DisplayImpl>::value);
116
117 } // namespace android::display::impl
118
119 using namespace android;
120 using namespace android::display::impl;
121
122 #define CHECK_NOT_NULL(name) \
123 LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
124
125 namespace {
126
getToken(ADisplay * display)127 sp<IBinder> getToken(ADisplay* display) {
128 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
129 return SurfaceComposerClient::getPhysicalDisplayToken(impl->id);
130 }
131
132 } // namespace
133
134 namespace android {
135
ADisplay_acquirePhysicalDisplays(ADisplay *** outDisplays)136 int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) {
137 const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
138 const size_t size = ids.size();
139 if (size == 0) {
140 return NO_INIT;
141 }
142
143 std::vector<DisplayConfigImpl> modesPerDisplay[size];
144 int numModes = 0;
145 for (int i = 0; i < size; ++i) {
146 const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
147
148 ui::StaticDisplayInfo staticInfo;
149 if (const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &staticInfo);
150 status != OK) {
151 return status;
152 }
153
154 ui::DynamicDisplayInfo dynamicInfo;
155 if (const status_t status =
156 SurfaceComposerClient::getDynamicDisplayInfo(token, &dynamicInfo);
157 status != OK) {
158 return status;
159 }
160 const auto& modes = dynamicInfo.supportedDisplayModes;
161 if (modes.empty()) {
162 return NO_INIT;
163 }
164
165 numModes += modes.size();
166 modesPerDisplay[i].reserve(modes.size());
167 for (int j = 0; j < modes.size(); ++j) {
168 const ui::DisplayMode& mode = modes[j];
169 modesPerDisplay[i].emplace_back(
170 DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(),
171 mode.resolution.getHeight(), staticInfo.density,
172 mode.refreshRate, mode.sfVsyncOffset, mode.appVsyncOffset});
173 }
174 }
175
176 const std::optional<PhysicalDisplayId> internalId =
177 SurfaceComposerClient::getInternalDisplayId();
178 ui::Dataspace defaultDataspace;
179 ui::PixelFormat defaultPixelFormat;
180 ui::Dataspace wcgDataspace;
181 ui::PixelFormat wcgPixelFormat;
182
183 const status_t status =
184 SurfaceComposerClient::getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
185 &wcgDataspace, &wcgPixelFormat);
186 if (status != NO_ERROR) {
187 return status;
188 }
189
190 // Here we allocate all our required memory in one block. The layout is as
191 // follows:
192 // ------------------------------------------------------------
193 // | DisplayImpl pointers | DisplayImpls | DisplayConfigImpls |
194 // ------------------------------------------------------------
195 //
196 // The caller will be given a DisplayImpl** which points to the beginning of
197 // the block of DisplayImpl pointers.
198 // Each DisplayImpl* points to a DisplayImpl in the second block.
199 // Each DisplayImpl contains a DisplayConfigImpl*, which points to a
200 // contiguous block of DisplayConfigImpls specific to that display.
201 DisplayImpl** const impls = reinterpret_cast<DisplayImpl**>(
202 malloc((sizeof(DisplayImpl) + sizeof(DisplayImpl*)) * size +
203 sizeof(DisplayConfigImpl) * numModes));
204 DisplayImpl* const displayData = reinterpret_cast<DisplayImpl*>(impls + size);
205 DisplayConfigImpl* configData = reinterpret_cast<DisplayConfigImpl*>(displayData + size);
206
207 for (size_t i = 0; i < size; ++i) {
208 const PhysicalDisplayId id = ids[i];
209 const ADisplayType type = (internalId == id) ? ADisplayType::DISPLAY_TYPE_INTERNAL
210 : ADisplayType::DISPLAY_TYPE_EXTERNAL;
211 const std::vector<DisplayConfigImpl>& configs = modesPerDisplay[i];
212 memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size());
213
214 displayData[i] = DisplayImpl{id,
215 type,
216 static_cast<ADataSpace>(wcgDataspace),
217 static_cast<AHardwareBuffer_Format>(wcgPixelFormat),
218 configs.size(),
219 configData};
220 impls[i] = displayData + i;
221 // Advance the configData pointer so that future configs are written to
222 // the correct display.
223 configData += configs.size();
224 }
225
226 *outDisplays = reinterpret_cast<ADisplay**>(impls);
227 return size;
228 }
229
ADisplay_release(ADisplay ** displays)230 void ADisplay_release(ADisplay** displays) {
231 if (displays == nullptr) {
232 return;
233 }
234 free(displays);
235 }
236
ADisplay_getMaxSupportedFps(ADisplay * display)237 float ADisplay_getMaxSupportedFps(ADisplay* display) {
238 CHECK_NOT_NULL(display);
239 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
240 float maxFps = 0.0;
241 for (int i = 0; i < impl->numConfigs; ++i) {
242 maxFps = std::max(maxFps, impl->configs[i].fps);
243 }
244 return maxFps;
245 }
246
ADisplay_getDisplayType(ADisplay * display)247 ADisplayType ADisplay_getDisplayType(ADisplay* display) {
248 CHECK_NOT_NULL(display);
249
250 return reinterpret_cast<DisplayImpl*>(display)->type;
251 }
252
ADisplay_getPreferredWideColorFormat(ADisplay * display,ADataSpace * outDataspace,AHardwareBuffer_Format * outPixelFormat)253 void ADisplay_getPreferredWideColorFormat(ADisplay* display, ADataSpace* outDataspace,
254 AHardwareBuffer_Format* outPixelFormat) {
255 CHECK_NOT_NULL(display);
256 CHECK_NOT_NULL(outDataspace);
257 CHECK_NOT_NULL(outPixelFormat);
258
259 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
260 *outDataspace = impl->wcgDataspace;
261 *outPixelFormat = impl->wcgPixelFormat;
262 }
263
ADisplay_getCurrentConfig(ADisplay * display,ADisplayConfig ** outConfig)264 int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) {
265 CHECK_NOT_NULL(display);
266
267 sp<IBinder> token = getToken(display);
268 ui::DynamicDisplayInfo info;
269 if (const auto status = SurfaceComposerClient::getDynamicDisplayInfo(token, &info);
270 status != OK) {
271 return status;
272 }
273
274 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
275 for (size_t i = 0; i < impl->numConfigs; i++) {
276 auto* config = impl->configs + i;
277 if (config->id == info.activeDisplayModeId) {
278 *outConfig = reinterpret_cast<ADisplayConfig*>(config);
279 return OK;
280 }
281 }
282
283 return NAME_NOT_FOUND;
284 }
285
ADisplayConfig_getDensity(ADisplayConfig * config)286 float ADisplayConfig_getDensity(ADisplayConfig* config) {
287 CHECK_NOT_NULL(config);
288
289 return reinterpret_cast<DisplayConfigImpl*>(config)->density;
290 }
291
ADisplayConfig_getWidth(ADisplayConfig * config)292 int32_t ADisplayConfig_getWidth(ADisplayConfig* config) {
293 CHECK_NOT_NULL(config);
294
295 return reinterpret_cast<DisplayConfigImpl*>(config)->width;
296 }
297
ADisplayConfig_getHeight(ADisplayConfig * config)298 int32_t ADisplayConfig_getHeight(ADisplayConfig* config) {
299 CHECK_NOT_NULL(config);
300
301 return reinterpret_cast<DisplayConfigImpl*>(config)->height;
302 }
303
ADisplayConfig_getFps(ADisplayConfig * config)304 float ADisplayConfig_getFps(ADisplayConfig* config) {
305 CHECK_NOT_NULL(config);
306
307 return reinterpret_cast<DisplayConfigImpl*>(config)->fps;
308 }
309
ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig * config)310 int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) {
311 CHECK_NOT_NULL(config);
312
313 return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset;
314 }
315
ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig * config)316 int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) {
317 CHECK_NOT_NULL(config);
318
319 return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset;
320 }
321
322 } // namespace android
323