• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
121 
getToken(ADisplay * display)122 sp<IBinder> getToken(ADisplay* display) {
123     DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
124     return SurfaceComposerClient::getPhysicalDisplayToken(impl->id);
125 }
126 
127 } // namespace
128 
129 namespace android {
130 
ADisplay_acquirePhysicalDisplays(ADisplay *** outDisplays)131 int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) {
132     const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
133     const size_t size = ids.size();
134     if (size == 0) {
135         return NO_INIT;
136     }
137 
138     std::vector<DisplayConfigImpl> modesPerDisplay[size];
139     int numModes = 0;
140     for (int i = 0; i < size; ++i) {
141         const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
142 
143         ui::StaticDisplayInfo staticInfo;
144         if (const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &staticInfo);
145             status != OK) {
146             return status;
147         }
148 
149         ui::DynamicDisplayInfo dynamicInfo;
150         if (const status_t status =
151                     SurfaceComposerClient::getDynamicDisplayInfo(token, &dynamicInfo);
152             status != OK) {
153             return status;
154         }
155         const auto& modes = dynamicInfo.supportedDisplayModes;
156         if (modes.empty()) {
157             return NO_INIT;
158         }
159 
160         numModes += modes.size();
161         modesPerDisplay[i].reserve(modes.size());
162         for (int j = 0; j < modes.size(); ++j) {
163             const ui::DisplayMode& mode = modes[j];
164             modesPerDisplay[i].emplace_back(
165                     DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(),
166                                       mode.resolution.getHeight(), mode.refreshRate,
167                                       mode.sfVsyncOffset, mode.appVsyncOffset});
168         }
169     }
170 
171     const std::optional<PhysicalDisplayId> internalId =
172             SurfaceComposerClient::getInternalDisplayId();
173     ui::Dataspace defaultDataspace;
174     ui::PixelFormat defaultPixelFormat;
175     ui::Dataspace wcgDataspace;
176     ui::PixelFormat wcgPixelFormat;
177 
178     const status_t status =
179             SurfaceComposerClient::getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
180                                                             &wcgDataspace, &wcgPixelFormat);
181     if (status != NO_ERROR) {
182         return status;
183     }
184 
185     // Here we allocate all our required memory in one block. The layout is as
186     // follows:
187     // ------------------------------------------------------------
188     // | DisplayImpl pointers | DisplayImpls | DisplayConfigImpls |
189     // ------------------------------------------------------------
190     //
191     // The caller will be given a DisplayImpl** which points to the beginning of
192     // the block of DisplayImpl pointers.
193     // Each DisplayImpl* points to a DisplayImpl in the second block.
194     // Each DisplayImpl contains a DisplayConfigImpl*, which points to a
195     // contiguous block of DisplayConfigImpls specific to that display.
196     DisplayImpl** const impls = reinterpret_cast<DisplayImpl**>(
197             malloc((sizeof(DisplayImpl) + sizeof(DisplayImpl*)) * size +
198                    sizeof(DisplayConfigImpl) * numModes));
199     DisplayImpl* const displayData = reinterpret_cast<DisplayImpl*>(impls + size);
200     DisplayConfigImpl* configData = reinterpret_cast<DisplayConfigImpl*>(displayData + size);
201 
202     for (size_t i = 0; i < size; ++i) {
203         const PhysicalDisplayId id = ids[i];
204         const ADisplayType type = (internalId == id) ? ADisplayType::DISPLAY_TYPE_INTERNAL
205                                                      : ADisplayType::DISPLAY_TYPE_EXTERNAL;
206         const std::vector<DisplayConfigImpl>& configs = modesPerDisplay[i];
207         memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size());
208 
209         displayData[i] = DisplayImpl{id,
210                                      type,
211                                      static_cast<ADataSpace>(wcgDataspace),
212                                      static_cast<AHardwareBuffer_Format>(wcgPixelFormat),
213                                      configs.size(),
214                                      configData};
215         impls[i] = displayData + i;
216         // Advance the configData pointer so that future configs are written to
217         // the correct display.
218         configData += configs.size();
219     }
220 
221     *outDisplays = reinterpret_cast<ADisplay**>(impls);
222     return size;
223 }
224 
ADisplay_release(ADisplay ** displays)225 void ADisplay_release(ADisplay** displays) {
226     if (displays == nullptr) {
227         return;
228     }
229     free(displays);
230 }
231 
ADisplay_getMaxSupportedFps(ADisplay * display)232 float ADisplay_getMaxSupportedFps(ADisplay* display) {
233     CHECK_NOT_NULL(display);
234     DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
235     float maxFps = 0.0;
236     for (int i = 0; i < impl->numConfigs; ++i) {
237         maxFps = std::max(maxFps, impl->configs[i].fps);
238     }
239     return maxFps;
240 }
241 
ADisplay_getDisplayType(ADisplay * display)242 ADisplayType ADisplay_getDisplayType(ADisplay* display) {
243     CHECK_NOT_NULL(display);
244 
245     return reinterpret_cast<DisplayImpl*>(display)->type;
246 }
247 
ADisplay_getPreferredWideColorFormat(ADisplay * display,ADataSpace * outDataspace,AHardwareBuffer_Format * outPixelFormat)248 void ADisplay_getPreferredWideColorFormat(ADisplay* display, ADataSpace* outDataspace,
249                                           AHardwareBuffer_Format* outPixelFormat) {
250     CHECK_NOT_NULL(display);
251     CHECK_NOT_NULL(outDataspace);
252     CHECK_NOT_NULL(outPixelFormat);
253 
254     DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
255     *outDataspace = impl->wcgDataspace;
256     *outPixelFormat = impl->wcgPixelFormat;
257 }
258 
ADisplay_getCurrentConfig(ADisplay * display,ADisplayConfig ** outConfig)259 int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) {
260     CHECK_NOT_NULL(display);
261 
262     sp<IBinder> token = getToken(display);
263     ui::DynamicDisplayInfo info;
264     if (const auto status = SurfaceComposerClient::getDynamicDisplayInfo(token, &info);
265         status != OK) {
266         return status;
267     }
268 
269     DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
270     for (size_t i = 0; i < impl->numConfigs; i++) {
271         auto* config = impl->configs + i;
272         if (config->id == info.activeDisplayModeId) {
273             *outConfig = reinterpret_cast<ADisplayConfig*>(config);
274             return OK;
275         }
276     }
277 
278     return NAME_NOT_FOUND;
279 }
280 
ADisplayConfig_getWidth(ADisplayConfig * config)281 int32_t ADisplayConfig_getWidth(ADisplayConfig* config) {
282     CHECK_NOT_NULL(config);
283 
284     return reinterpret_cast<DisplayConfigImpl*>(config)->width;
285 }
286 
ADisplayConfig_getHeight(ADisplayConfig * config)287 int32_t ADisplayConfig_getHeight(ADisplayConfig* config) {
288     CHECK_NOT_NULL(config);
289 
290     return reinterpret_cast<DisplayConfigImpl*>(config)->height;
291 }
292 
ADisplayConfig_getFps(ADisplayConfig * config)293 float ADisplayConfig_getFps(ADisplayConfig* config) {
294     CHECK_NOT_NULL(config);
295 
296     return reinterpret_cast<DisplayConfigImpl*>(config)->fps;
297 }
298 
ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig * config)299 int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) {
300     CHECK_NOT_NULL(config);
301 
302     return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset;
303 }
304 
ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig * config)305 int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) {
306     CHECK_NOT_NULL(config);
307 
308     return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset;
309 }
310 
311 } // namespace android
312