blob: c595aa63094767ad17cf89074dc39f93933b5075 [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>
Marin Shalamanova7fe3042021-01-29 21:02:08 +010020#include <ui/DisplayMode.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>
Alec Mouri671d0f52019-09-05 13:59:19 -070023
24#include <algorithm>
25#include <optional>
26#include <type_traits>
27#include <vector>
28
29namespace android::display::impl {
30
31/**
32 * Implementation of ADisplayConfig
33 */
34struct 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.
69static_assert(std::is_trivially_destructible<DisplayConfigImpl>::value);
70
71/**
72 * Implementation of ADisplay
73 */
74struct 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 /**
Alec Mouri46170512019-11-20 11:04:55 -080087 * The preferred WCG dataspace
88 */
89 ADataSpace wcgDataspace;
90
91 /**
92 * The preferred WCG pixel format
93 */
94 AHardwareBuffer_Format wcgPixelFormat;
95
96 /**
Alec Mouri671d0f52019-09-05 13:59:19 -070097 * 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.
109static_assert(std::is_trivially_destructible<DisplayImpl>::value);
110
111} // namespace android::display::impl
112
113using namespace android;
114using namespace android::display::impl;
115
116#define CHECK_NOT_NULL(name) \
117 LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
118
119namespace {
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800120
Alec Mouri671d0f52019-09-05 13:59:19 -0700121sp<IBinder> getToken(ADisplay* display) {
122 DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
123 return SurfaceComposerClient::getPhysicalDisplayToken(impl->id);
124}
125
Alec Mouri671d0f52019-09-05 13:59:19 -0700126} // namespace
127
Alec Mourid9ff3272019-11-19 16:23:59 -0800128namespace android {
129
Alec Mouri671d0f52019-09-05 13:59:19 -0700130int 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
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100137 std::vector<DisplayConfigImpl> modesPerDisplay[size];
138 int numModes = 0;
Alec Mouri671d0f52019-09-05 13:59:19 -0700139 for (int i = 0; i < size; ++i) {
140 const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800141
142 DisplayInfo info;
143 if (const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info);
144 status != OK) {
145 return status;
146 }
147
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100148 Vector<ui::DisplayMode> modes;
149 if (const status_t status = SurfaceComposerClient::getDisplayModes(token, &modes);
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800150 status != OK) {
Alec Mouri671d0f52019-09-05 13:59:19 -0700151 return status;
152 }
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100153 if (modes.empty()) {
Alec Mouri671d0f52019-09-05 13:59:19 -0700154 return NO_INIT;
155 }
156
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100157 numModes += modes.size();
158 modesPerDisplay[i].reserve(modes.size());
159 for (int j = 0; j < modes.size(); ++j) {
160 const ui::DisplayMode& mode = modes[j];
161 modesPerDisplay[i].emplace_back(
162 DisplayConfigImpl{mode.resolution.getWidth(), mode.resolution.getHeight(),
163 info.density, mode.refreshRate, mode.sfVsyncOffset,
164 mode.appVsyncOffset});
Alec Mouri671d0f52019-09-05 13:59:19 -0700165 }
166 }
167
168 const std::optional<PhysicalDisplayId> internalId =
169 SurfaceComposerClient::getInternalDisplayId();
Alec Mouri46170512019-11-20 11:04:55 -0800170 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 }
Alec Mouri671d0f52019-09-05 13:59:19 -0700181
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 +
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100195 sizeof(DisplayConfigImpl) * numModes));
Alec Mouri671d0f52019-09-05 13:59:19 -0700196 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;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100203 const std::vector<DisplayConfigImpl>& configs = modesPerDisplay[i];
Alec Mouri671d0f52019-09-05 13:59:19 -0700204 memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size());
205
Alec Mouri46170512019-11-20 11:04:55 -0800206 displayData[i] = DisplayImpl{id,
207 type,
208 static_cast<ADataSpace>(wcgDataspace),
209 static_cast<AHardwareBuffer_Format>(wcgPixelFormat),
210 configs.size(),
211 configData};
Alec Mouri671d0f52019-09-05 13:59:19 -0700212 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
222void ADisplay_release(ADisplay** displays) {
223 if (displays == nullptr) {
224 return;
225 }
226 free(displays);
227}
228
229float 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
239ADisplayType ADisplay_getDisplayType(ADisplay* display) {
240 CHECK_NOT_NULL(display);
241
242 return reinterpret_cast<DisplayImpl*>(display)->type;
243}
244
Alec Mouri46170512019-11-20 11:04:55 -0800245void 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
Alec Mouri671d0f52019-09-05 13:59:19 -0700256int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) {
257 CHECK_NOT_NULL(display);
258
259 sp<IBinder> token = getToken(display);
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100260 const int index = SurfaceComposerClient::getActiveDisplayModeId(token);
Alec Mouri671d0f52019-09-05 13:59:19 -0700261 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
271float ADisplayConfig_getDensity(ADisplayConfig* config) {
272 CHECK_NOT_NULL(config);
273
274 return reinterpret_cast<DisplayConfigImpl*>(config)->density;
275}
276
277int32_t ADisplayConfig_getWidth(ADisplayConfig* config) {
278 CHECK_NOT_NULL(config);
279
280 return reinterpret_cast<DisplayConfigImpl*>(config)->width;
281}
282
283int32_t ADisplayConfig_getHeight(ADisplayConfig* config) {
284 CHECK_NOT_NULL(config);
285
286 return reinterpret_cast<DisplayConfigImpl*>(config)->height;
287}
288
289float ADisplayConfig_getFps(ADisplayConfig* config) {
290 CHECK_NOT_NULL(config);
291
292 return reinterpret_cast<DisplayConfigImpl*>(config)->fps;
293}
294
295int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) {
296 CHECK_NOT_NULL(config);
297
298 return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset;
299}
300
301int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) {
302 CHECK_NOT_NULL(config);
303
304 return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset;
305}
Alec Mourid9ff3272019-11-19 16:23:59 -0800306
307} // namespace android