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