blob: 6288194714e1770a4dba3e0cc1ae388af717bb3b [file] [log] [blame]
Alec Mouri671d0f52019-09-05 13:59:19 -07001/*
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>
Marin Shalamanova7fe3042021-01-29 21:02:08 +010019#include <ui/DisplayMode.h>
Marin Shalamanov228f46b2021-01-28 21:11:45 +010020#include <ui/DynamicDisplayInfo.h>
Alec Mouri671d0f52019-09-05 13:59:19 -070021#include <ui/GraphicTypes.h>
Alec Mouri46170512019-11-20 11:04:55 -080022#include <ui/PixelFormat.h>
Marin Shalamanov228f46b2021-01-28 21:11:45 +010023#include <ui/StaticDisplayInfo.h>
Alec Mouri671d0f52019-09-05 13:59:19 -070024
25#include <algorithm>
26#include <optional>
27#include <type_traits>
28#include <vector>
29
30namespace android::display::impl {
31
32/**
33 * Implementation of ADisplayConfig
34 */
35struct DisplayConfigImpl {
36 /**
Marin Shalamanov228f46b2021-01-28 21:11:45 +010037 * The ID of the display configuration.
38 */
39 size_t id;
40
41 /**
Alec Mouri671d0f52019-09-05 13:59:19 -070042 * 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.
75static_assert(std::is_trivially_destructible<DisplayConfigImpl>::value);
76
77/**
78 * Implementation of ADisplay
79 */
80struct 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 /**
Alec Mouri46170512019-11-20 11:04:55 -080093 * The preferred WCG dataspace
94 */
95 ADataSpace wcgDataspace;
96
97 /**
98 * The preferred WCG pixel format
99 */
100 AHardwareBuffer_Format wcgPixelFormat;
101
102 /**
Alec Mouri671d0f52019-09-05 13:59:19 -0700103 * 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.
115static_assert(std::is_trivially_destructible<DisplayImpl>::value);
116
117} // namespace android::display::impl
118
119using namespace android;
120using namespace android::display::impl;
121
122#define CHECK_NOT_NULL(name) \
123 LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
124
125namespace {
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800126
Alec Mouri671d0f52019-09-05 13:59:19 -0700127sp<IBinder> getToken(ADisplay* display) {
128 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
129 return SurfaceComposerClient::getPhysicalDisplayToken(impl->id);
130}
131
Alec Mouri671d0f52019-09-05 13:59:19 -0700132} // namespace
133
Alec Mourid9ff3272019-11-19 16:23:59 -0800134namespace android {
135
Alec Mouri671d0f52019-09-05 13:59:19 -0700136int 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
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100143 std::vector<DisplayConfigImpl> modesPerDisplay[size];
144 int numModes = 0;
Alec Mouri671d0f52019-09-05 13:59:19 -0700145 for (int i = 0; i < size; ++i) {
146 const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800147
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100148 ui::StaticDisplayInfo staticInfo;
149 if (const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &staticInfo);
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800150 status != OK) {
151 return status;
152 }
153
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100154 ui::DynamicDisplayInfo dynamicInfo;
155 if (const status_t status =
156 SurfaceComposerClient::getDynamicDisplayInfo(token, &dynamicInfo);
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800157 status != OK) {
Alec Mouri671d0f52019-09-05 13:59:19 -0700158 return status;
159 }
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100160 const auto& modes = dynamicInfo.supportedDisplayModes;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100161 if (modes.empty()) {
Alec Mouri671d0f52019-09-05 13:59:19 -0700162 return NO_INIT;
163 }
164
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100165 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(
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100170 DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(),
171 mode.resolution.getHeight(), staticInfo.density,
172 mode.refreshRate, mode.sfVsyncOffset, mode.appVsyncOffset});
Alec Mouri671d0f52019-09-05 13:59:19 -0700173 }
174 }
175
176 const std::optional<PhysicalDisplayId> internalId =
177 SurfaceComposerClient::getInternalDisplayId();
Alec Mouri46170512019-11-20 11:04:55 -0800178 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 }
Alec Mouri671d0f52019-09-05 13:59:19 -0700189
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 +
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100203 sizeof(DisplayConfigImpl) * numModes));
Alec Mouri671d0f52019-09-05 13:59:19 -0700204 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;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100211 const std::vector<DisplayConfigImpl>& configs = modesPerDisplay[i];
Alec Mouri671d0f52019-09-05 13:59:19 -0700212 memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size());
213
Alec Mouri46170512019-11-20 11:04:55 -0800214 displayData[i] = DisplayImpl{id,
215 type,
216 static_cast<ADataSpace>(wcgDataspace),
217 static_cast<AHardwareBuffer_Format>(wcgPixelFormat),
218 configs.size(),
219 configData};
Alec Mouri671d0f52019-09-05 13:59:19 -0700220 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
230void ADisplay_release(ADisplay** displays) {
231 if (displays == nullptr) {
232 return;
233 }
234 free(displays);
235}
236
237float 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
247ADisplayType ADisplay_getDisplayType(ADisplay* display) {
248 CHECK_NOT_NULL(display);
249
250 return reinterpret_cast<DisplayImpl*>(display)->type;
251}
252
Alec Mouri46170512019-11-20 11:04:55 -0800253void 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
Alec Mouri671d0f52019-09-05 13:59:19 -0700264int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) {
265 CHECK_NOT_NULL(display);
266
267 sp<IBinder> token = getToken(display);
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100268 ui::DynamicDisplayInfo info;
269 if (const auto status = SurfaceComposerClient::getDynamicDisplayInfo(token, &info);
270 status != OK) {
271 return status;
Alec Mouri671d0f52019-09-05 13:59:19 -0700272 }
273
274 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100275 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 }
Alec Mouri671d0f52019-09-05 13:59:19 -0700282
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100283 return NAME_NOT_FOUND;
Alec Mouri671d0f52019-09-05 13:59:19 -0700284}
285
286float ADisplayConfig_getDensity(ADisplayConfig* config) {
287 CHECK_NOT_NULL(config);
288
289 return reinterpret_cast<DisplayConfigImpl*>(config)->density;
290}
291
292int32_t ADisplayConfig_getWidth(ADisplayConfig* config) {
293 CHECK_NOT_NULL(config);
294
295 return reinterpret_cast<DisplayConfigImpl*>(config)->width;
296}
297
298int32_t ADisplayConfig_getHeight(ADisplayConfig* config) {
299 CHECK_NOT_NULL(config);
300
301 return reinterpret_cast<DisplayConfigImpl*>(config)->height;
302}
303
304float ADisplayConfig_getFps(ADisplayConfig* config) {
305 CHECK_NOT_NULL(config);
306
307 return reinterpret_cast<DisplayConfigImpl*>(config)->fps;
308}
309
310int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) {
311 CHECK_NOT_NULL(config);
312
313 return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset;
314}
315
316int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) {
317 CHECK_NOT_NULL(config);
318
319 return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset;
320}
Alec Mourid9ff3272019-11-19 16:23:59 -0800321
322} // namespace android