TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / android / hwcomposer / hwcomposer.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include <hardware/hardware.h>
19 #include <hardware/hwcomposer.h>
20
21 #include <map>
22 #include <vector>
23 #include <algorithm>
24 #include <string>
25
26 #define LOG_NDEBUG 1
27 #include <cutils/log.h>
28
29 #include "HostConnection.h"
30 #include "gralloc_cb.h"
31
32 #define DEFINE_HOST_CONNECTION() \
33     HostConnection *hostCon = HostConnection::get(); \
34     renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
35
36 #define DEFINE_AND_VALIDATE_HOST_CONNECTION() \
37     HostConnection *hostCon = HostConnection::get(); \
38     if (!hostCon) { \
39         ALOGE("hwcomposer.anbox: Failed to get host connection\n"); \
40         return -EIO; \
41     } \
42     renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
43     if (!rcEnc) { \
44         ALOGE("hwcomposer.anbox: Failed to get renderControl encoder context\n"); \
45         return -EIO; \
46     }
47
48 struct HwcContext {
49     hwc_composer_device_1_t device;
50
51     // These 3 variables could be reduced to first_overlay only, however it makes
52     // the conditions in the code more complicated. In order to keep things as
53     // simple as possible, there are 3 major ways to display a frame.
54     // 1. Show only the framebuffer.
55     // 2. Show the framebuffer with some overlays above it.
56     // 3. Show all overlays and hide the framebuffer.
57     //
58     // Since the framebuffer has no alpha channel and is opaque, it can only ever
59     // be the rearmost layer that we end up putting on screen, otherwise it will
60     // cover up all layers behind it, since its display frame is the whole window.
61     //
62     // Without framebuffer_visible, the condition of whether to display the
63     // frambuffer becomes more complex and possibly if (numHwLayers == 0 ||
64     // hwLayers[0]->compositionType != HWC_OVERLAY) but that might not be correct.
65     //
66     // The range [first_overlay, first_overlay+num_overlay) is a natural way to
67     // structure the loop and prevents requiring state and iterating through all
68     // the non-OVERLAY layers in hwc_set.
69     bool framebuffer_visible;
70     size_t first_overlay;
71     size_t num_overlays;
72 };
73
74 static void dump_layer(hwc_layer_1_t const* l) {
75     ALOGD("\tname='%s', type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
76             l->name, l->compositionType, l->flags, l->handle, l->transform, l->blending,
77             l->sourceCrop.left,
78             l->sourceCrop.top,
79             l->sourceCrop.right,
80             l->sourceCrop.bottom,
81             l->displayFrame.left,
82             l->displayFrame.top,
83             l->displayFrame.right,
84             l->displayFrame.bottom);
85 }
86
87 static int hwc_prepare(hwc_composer_device_1_t* dev, size_t numDisplays,
88                        hwc_display_contents_1_t** displays) {
89     auto context = reinterpret_cast<HwcContext*>(dev);
90
91     if (displays == NULL || displays[0] == NULL)
92         return -EINVAL;
93
94     // Anbox only supports the primary display.
95     if (displays[0]->flags & HWC_GEOMETRY_CHANGED) {
96         const size_t& num_hw_layers = displays[0]->numHwLayers;
97         size_t i = 1;
98         bool visible = (num_hw_layers == 1);
99
100         // Iterate backwards and skip the first (end) layer, which is the
101         // framebuffer target layer. According to the SurfaceFlinger folks, the
102         // actual location of this layer is up to the HWC implementation to
103         // decide, but is in the well know last slot of the list. This does not
104         // imply that the framebuffer target layer must be topmost.
105         for (; i < num_hw_layers; i++) {
106           hwc_layer_1_t* layer = &displays[0]->hwLayers[num_hw_layers - 1 - i];
107
108 #if 0
109           dump_layer(layer);
110 #endif
111
112           if (layer->flags & HWC_SKIP_LAYER) {
113             // All layers below and including this one will be drawn into the
114             // framebuffer. Stop marking further layers as HWC_OVERLAY.
115             visible = true;
116             break;
117           }
118
119           switch (layer->compositionType) {
120             case HWC_OVERLAY:
121             case HWC_FRAMEBUFFER:
122               layer->compositionType = HWC_OVERLAY;
123               break;
124             case HWC_BACKGROUND:
125               break;
126             default:
127               ALOGE("hwcomposor: Invalid compositionType %d",
128                       layer->compositionType);
129               break;
130           }
131         }
132         context->first_overlay = num_hw_layers - i;
133         context->num_overlays = i - 1;
134         context->framebuffer_visible = visible;
135     }
136
137     return 0;
138 }
139
140 /*
141  * We're using "implicit" synchronization, so make sure we aren't passing any
142  * sync object descriptors around.
143  */
144 static void check_sync_fds(size_t numDisplays, hwc_display_contents_1_t** displays)
145 {
146     unsigned int i, j;
147     for (i = 0; i < numDisplays; i++) {
148         hwc_display_contents_1_t* list = displays[i];
149         if (list->retireFenceFd >= 0) {
150             ALOGW("retireFenceFd[%u] was %d", i, list->retireFenceFd);
151             list->retireFenceFd = -1;
152         }
153
154         for (j = 0; j < list->numHwLayers; j++) {
155             hwc_layer_1_t* layer = &list->hwLayers[j];
156             if (layer->acquireFenceFd >= 0) {
157                 ALOGW("acquireFenceFd[%u][%u] was %d, closing", i, j, layer->acquireFenceFd);
158                 close(layer->acquireFenceFd);
159                 layer->acquireFenceFd = -1;
160             }
161             if (layer->releaseFenceFd >= 0) {
162                 ALOGW("releaseFenceFd[%u][%u] was %d", i, j, layer->releaseFenceFd);
163                 layer->releaseFenceFd = -1;
164             }
165         }
166     }
167 }
168
169 static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays,
170                    hwc_display_contents_1_t** displays) {
171     auto context = reinterpret_cast<HwcContext*>(dev);
172
173     if (displays == NULL || displays[0] == NULL)
174         return -EFAULT;
175
176     DEFINE_AND_VALIDATE_HOST_CONNECTION();
177
178     for (size_t i = 0 ; i < displays[0]->numHwLayers ; i++) {
179         const auto layer = &displays[0]->hwLayers[i];
180
181         if (layer->flags & HWC_SKIP_LAYER ||
182             layer->flags & HWC_IS_CURSOR_LAYER)
183             continue;
184
185 #if 0
186         dump_layer(layer);
187 #endif
188
189         // FIXME this is just dirty ... but layer->handle is a const native_handle_t and canBePosted
190         // can't be called with a const.
191         auto cb = const_cast<cb_handle_t*>(reinterpret_cast<const cb_handle_t*>(layer->handle));
192         if (!cb_handle_t::validate(cb)) {
193             ALOGE("Buffer handle is invalid\n");
194             return -EINVAL;
195         }
196
197         rcEnc->rcPostLayer(rcEnc,
198                            layer->name,
199                            cb->hostHandle,
200                            layer->planeAlpha / 255,
201                            layer->sourceCrop.left,
202                            layer->sourceCrop.top,
203                            layer->sourceCrop.right,
204                            layer->sourceCrop.bottom,
205                            layer->displayFrame.left,
206                            layer->displayFrame.top,
207                            layer->displayFrame.right,
208                            layer->displayFrame.bottom);
209         hostCon->flush();
210     }
211
212     rcEnc->rcPostAllLayersDone(rcEnc);
213
214     check_sync_fds(numDisplays, displays);
215
216     return 0;
217 }
218
219 static int hwc_event_control(hwc_composer_device_1* dev, int disp,
220                              int event, int enabled) {
221     return -EFAULT;
222 }
223
224 static void hwc_register_procs(hwc_composer_device_1* dev,
225                                hwc_procs_t const* procs) {
226 }
227
228 static int hwc_blank(hwc_composer_device_1* dev, int disp, int blank) {
229     return 0;
230 }
231
232 static int hwc_query(hwc_composer_device_1* dev, int what, int* value) {
233     return 0;
234 }
235
236 static int hwc_device_close(hw_device_t* dev) {
237     auto context = reinterpret_cast<HwcContext*>(dev);
238     delete context;
239     return 0;
240 }
241
242 static int hwc_get_display_configs(hwc_composer_device_1* dev, int disp,
243                                    uint32_t* configs, size_t* numConfigs) {
244   if (disp != 0) {
245     return -EINVAL;
246   }
247
248   if (*numConfigs > 0) {
249     // Config[0] will be passed in to getDisplayAttributes as the disp
250     // parameter. The ARC display supports only 1 configuration.
251     configs[0] = 0;
252     *numConfigs = 1;
253   }
254   return 0;
255 }
256
257 static int hwc_get_display_attributes(hwc_composer_device_1* dev,
258                                       int disp, uint32_t config,
259                                       const uint32_t* attributes,
260                                       int32_t* values) {
261   if (disp != 0 || config != 0) {
262     return -EINVAL;
263   }
264
265   DEFINE_AND_VALIDATE_HOST_CONNECTION();
266
267   while (*attributes != HWC_DISPLAY_NO_ATTRIBUTE) {
268     switch (*attributes) {
269       case HWC_DISPLAY_VSYNC_PERIOD:
270         *values = rcEnc->rcGetDisplayVsyncPeriod(rcEnc, disp);
271         break;
272       case HWC_DISPLAY_WIDTH:
273         *values = rcEnc->rcGetDisplayWidth(rcEnc, disp);
274         break;
275       case HWC_DISPLAY_HEIGHT:
276         *values = rcEnc->rcGetDisplayHeight(rcEnc, disp);
277         break;
278       case HWC_DISPLAY_DPI_X:
279         *values = 1000 * rcEnc->rcGetDisplayDpiX(rcEnc, disp);
280         break;
281       case HWC_DISPLAY_DPI_Y:
282         *values = 1000 * rcEnc->rcGetDisplayDpiY(rcEnc, disp);
283         break;
284       default:
285         ALOGE("Unknown attribute value 0x%02x", *attributes);
286     }
287     ++attributes;
288     ++values;
289   }
290   return 0;
291 }
292
293 static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) {
294     ALOGD("%s", __PRETTY_FUNCTION__);
295
296     if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0)
297         return -EINVAL;
298
299     auto dev = new HwcContext;
300     dev->device.common.tag = HARDWARE_DEVICE_TAG;
301     dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
302     dev->device.common.module = const_cast<hw_module_t*>(module);
303     dev->device.common.close = hwc_device_close;
304     dev->device.prepare = hwc_prepare;
305     dev->device.set = hwc_set;
306     dev->device.eventControl = hwc_event_control;
307     dev->device.blank = hwc_blank;
308     dev->device.query = hwc_query;
309     dev->device.getDisplayConfigs = hwc_get_display_configs;
310     dev->device.getDisplayAttributes = hwc_get_display_attributes;
311     dev->device.registerProcs = hwc_register_procs;
312     dev->device.dump = nullptr;
313
314     *device = &dev->device.common;
315
316     return 0;
317 }
318
319 static hw_module_methods_t hwc_module_methods = {
320     .open = hwc_device_open
321 };
322
323 hwc_module_t HAL_MODULE_INFO_SYM = {
324     .common = {
325         .tag = HARDWARE_MODULE_TAG,
326         .version_major = 1,
327         .version_minor = 0,
328         .id = HWC_HARDWARE_MODULE_ID,
329         .name = "Hardware Composer Module",
330         .author = "Anbox Developers",
331         .methods = &hwc_module_methods,
332     }
333 };