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