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