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