OSDN Git Service

gralloc0_register_buffer: initialize gralloc0 when needed
[android-x86/external-minigbm.git] / cros_gralloc / gralloc0 / gralloc0.cc
1 /*
2  * Copyright 2016 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #include "../../helpers.h"
8 #include "../../util.h"
9 #include "../cros_gralloc_driver.h"
10
11 #include <cassert>
12 #include <hardware/gralloc.h>
13 #include <memory.h>
14 #include <xf86drm.h>
15 #include "drm_framebuffer.h"
16 #include "gralloc_drm.h"
17
18 struct gralloc0_module {
19         gralloc_module_t base;
20         std::unique_ptr<alloc_device_t> alloc;
21         std::unique_ptr<cros_gralloc_driver> driver;
22         struct drm_framebuffer *fb;
23         bool initialized;
24         std::mutex initialization_mutex;
25 };
26
27 struct cros_gralloc0_buffer_info {
28         uint32_t drm_fourcc;
29         int num_fds;
30         int fds[4];
31         uint64_t modifier;
32         uint32_t offset[4];
33         uint32_t stride[4];
34 };
35
36 /* This enumeration must match the one in <gralloc_drm.h>.
37  * The functions supported by this gralloc's temporary private API are listed
38  * below. Use of these functions is highly discouraged and should only be
39  * reserved for cases where no alternative to get same information (such as
40  * querying ANativeWindow) exists.
41  */
42 // clang-format off
43 enum {
44         GRALLOC_DRM_GET_STRIDE,
45         GRALLOC_DRM_GET_FORMAT,
46         GRALLOC_DRM_GET_DIMENSIONS,
47         GRALLOC_DRM_GET_BACKING_STORE,
48         GRALLOC_DRM_GET_BUFFER_INFO,
49 };
50 // clang-format on
51
52 // Gralloc0 doesn't define a video decoder flag. However, the IAllocator gralloc0
53 // passthrough gives the low 32-bits of the BufferUsage flags to gralloc0 in their
54 // entirety, so we can detect the video decoder flag passed by IAllocator clients.
55 #define BUFFER_USAGE_VIDEO_DECODER (1 << 22)
56
57 static uint64_t gralloc0_convert_usage(int usage)
58 {
59         uint64_t use_flags = BO_USE_NONE;
60
61         if (usage & GRALLOC_USAGE_CURSOR)
62                 use_flags |= BO_USE_NONE;
63         if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY)
64                 use_flags |= BO_USE_SW_READ_RARELY;
65         if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
66                 use_flags |= BO_USE_SW_READ_OFTEN;
67         if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
68                 use_flags |= BO_USE_SW_WRITE_RARELY;
69         if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN)
70                 use_flags |= BO_USE_SW_WRITE_OFTEN;
71         if (usage & GRALLOC_USAGE_HW_TEXTURE)
72                 use_flags |= BO_USE_TEXTURE;
73         if (usage & GRALLOC_USAGE_HW_RENDER)
74                 use_flags |= BO_USE_RENDERING;
75         if (usage & GRALLOC_USAGE_HW_2D)
76                 use_flags |= BO_USE_RENDERING;
77         if (usage & GRALLOC_USAGE_HW_COMPOSER)
78                 /* HWC wants to use display hardware, but can defer to OpenGL. */
79                 use_flags |= BO_USE_SCANOUT | BO_USE_TEXTURE;
80         if (usage & GRALLOC_USAGE_HW_FB)
81                 use_flags |= BO_USE_FRAMEBUFFER;
82         if (usage & GRALLOC_USAGE_EXTERNAL_DISP)
83                 /*
84                  * This flag potentially covers external display for the normal drivers (i915,
85                  * rockchip) and usb monitors (evdi/udl). It's complicated so ignore it.
86                  * */
87                 use_flags |= BO_USE_NONE;
88         /* Map this flag to linear until real HW protection is available on Android. */
89         if (usage & GRALLOC_USAGE_PROTECTED)
90                 use_flags |= BO_USE_LINEAR;
91         if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
92                 use_flags |= BO_USE_HW_VIDEO_ENCODER;
93                 /*HACK: See b/30054495 */
94                 use_flags |= BO_USE_SW_READ_OFTEN;
95         }
96         if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
97                 use_flags |= BO_USE_CAMERA_WRITE;
98         if (usage & GRALLOC_USAGE_HW_CAMERA_READ)
99                 use_flags |= BO_USE_CAMERA_READ;
100         if (usage & GRALLOC_USAGE_RENDERSCRIPT)
101                 use_flags |= BO_USE_RENDERSCRIPT;
102         if (usage & BUFFER_USAGE_VIDEO_DECODER)
103                 use_flags |= BO_USE_HW_VIDEO_DECODER;
104
105         return use_flags;
106 }
107
108 static uint32_t gralloc0_convert_map_usage(int map_usage)
109 {
110         uint32_t map_flags = BO_MAP_NONE;
111
112         if (map_usage & GRALLOC_USAGE_SW_READ_MASK)
113                 map_flags |= BO_MAP_READ;
114         if (map_usage & GRALLOC_USAGE_SW_WRITE_MASK)
115                 map_flags |= BO_MAP_WRITE;
116
117         return map_flags;
118 }
119
120 static int gralloc0_droid_yuv_format(int droid_format)
121 {
122
123         return (droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888 ||
124                 droid_format == HAL_PIXEL_FORMAT_YV12);
125 }
126
127 static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usage,
128                           buffer_handle_t *handle, int *stride)
129 {
130         int32_t ret;
131         bool supported;
132         struct cros_gralloc_buffer_descriptor descriptor;
133         auto mod = (struct gralloc0_module const *)dev->common.module;
134
135         descriptor.width = w;
136         descriptor.height = h;
137         descriptor.droid_format = format;
138         descriptor.droid_usage = usage;
139         descriptor.drm_format = cros_gralloc_convert_format(format);
140         descriptor.use_flags = gralloc0_convert_usage(usage);
141         descriptor.reserved_region_size = 0;
142
143         supported = mod->driver->is_supported(&descriptor);
144         if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
145                 descriptor.use_flags &= ~BO_USE_SCANOUT;
146                 supported = mod->driver->is_supported(&descriptor);
147         }
148         if (!supported && (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
149             !gralloc0_droid_yuv_format(format)) {
150                 // Unmask BO_USE_HW_VIDEO_ENCODER in the case of non-yuv formats
151                 // because they are not input to a hw encoder but used as an
152                 // intermediate format (e.g. camera).
153                 descriptor.use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
154                 supported = mod->driver->is_supported(&descriptor);
155         }
156
157         if (!supported) {
158                 drv_log("Unsupported combination -- HAL format: %u, HAL usage: %u, "
159                         "drv_format: %4.4s, use_flags: %llu\n",
160                         format, usage, reinterpret_cast<char *>(&descriptor.drm_format),
161                         static_cast<unsigned long long>(descriptor.use_flags));
162                 return -EINVAL;
163         }
164
165         ret = mod->driver->allocate(&descriptor, handle);
166         if (ret)
167                 return ret;
168
169         auto hnd = cros_gralloc_convert_handle(*handle);
170         *stride = hnd->pixel_stride;
171
172         return 0;
173 }
174
175 static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle)
176 {
177         auto mod = (struct gralloc0_module const *)dev->common.module;
178         return mod->driver->release(handle);
179 }
180
181 static int gralloc0_close(struct hw_device_t *dev)
182 {
183         /* Memory is freed by managed pointers on process close. */
184         return 0;
185 }
186
187 static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc,
188                           bool framebuffer = false)
189 {
190         std::lock_guard<std::mutex> lock(mod->initialization_mutex);
191
192         if (mod->initialized)
193                 return 0;
194
195         mod->driver = std::make_unique<cros_gralloc_driver>();
196         if (framebuffer ? mod->driver->init_master() : mod->driver->init()) {
197                 drv_log("Failed to initialize driver.\n");
198                 return -ENODEV;
199         }
200
201         if (initialize_alloc) {
202                 mod->alloc = std::make_unique<alloc_device_t>();
203                 mod->alloc->alloc = gralloc0_alloc;
204                 mod->alloc->free = gralloc0_free;
205                 mod->alloc->common.tag = HARDWARE_DEVICE_TAG;
206                 mod->alloc->common.version = 0;
207                 mod->alloc->common.module = (hw_module_t *)mod;
208                 mod->alloc->common.close = gralloc0_close;
209         }
210
211         if (framebuffer) {
212                 int ret = drm_framebuffer_init(mod->driver->get_fd(), &mod->fb);
213                 if (ret)
214                         return ret;
215         }
216
217         mod->initialized = true;
218         return 0;
219 }
220
221 static int gralloc0_open_fb0(struct gralloc0_module *mod, struct hw_device_t **dev)
222 {
223         int ret;
224
225         if (!mod->initialized) {
226                 ret = gralloc0_init(mod, true, true);
227                 if (ret)
228                         return ret;
229         }
230
231         if (!mod->fb) {
232                 /*
233                  * On Pie and above the FB HAL is opened before the Gralloc HAL.
234                  * This has the advantage that we can open the DRM card node in this case,
235                  * and open the render node in all other cases.
236                  *
237                  * On earlier Android versions this is not the case, so we need to make
238                  * sure the FB HAL was actually initialized.
239                  *
240                  * TODO: Currently it does not attempt to set master on the opened render
241                  * node. That means it will only work with DRM authentication disabled.
242                  */
243                 std::lock_guard<std::mutex> lock(mod->initialization_mutex);
244                 drv_log("FB HAL opened after Gralloc HAL, we might not be DRM master!\n");
245
246                 ret = drm_framebuffer_init(mod->driver->get_fd(), &mod->fb);
247                 if (ret)
248                         return ret;
249         }
250
251         *dev = (struct hw_device_t *) mod->fb;
252         return 0;
253 }
254
255 static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev)
256 {
257         auto const_module = reinterpret_cast<const struct gralloc0_module *>(mod);
258         auto module = const_cast<struct gralloc0_module *>(const_module);
259
260         if (!strcmp(name, GRALLOC_HARDWARE_FB0))
261                 return gralloc0_open_fb0(module, dev);
262
263         if (module->initialized) {
264                 *dev = &module->alloc->common;
265                 return 0;
266         }
267
268         if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
269                 drv_log("Incorrect device name - %s.\n", name);
270                 return -EINVAL;
271         }
272
273         if (gralloc0_init(module, true))
274                 return -ENODEV;
275
276         *dev = &module->alloc->common;
277         return 0;
278 }
279
280 static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
281 {
282         auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
283         auto mod = const_cast<struct gralloc0_module *>(const_module);
284
285         if (!mod->initialized)
286                 if (gralloc0_init(mod, true))
287                         return -ENODEV;
288
289         int ret = mod->driver->retain(handle);
290         if (ret == 0 && mod->fb)
291                 drm_framebuffer_import(mod->fb, handle);
292         return ret;
293 }
294
295 static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
296 {
297         auto mod = (struct gralloc0_module const *)module;
298         return mod->driver->release(handle);
299 }
300
301 static int gralloc0_lock(struct gralloc_module_t const *module, buffer_handle_t handle, int usage,
302                          int l, int t, int w, int h, void **vaddr)
303 {
304         return module->lockAsync(module, handle, usage, l, t, w, h, vaddr, -1);
305 }
306
307 static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
308 {
309         int32_t fence_fd, ret;
310         auto mod = (struct gralloc0_module const *)module;
311         ret = mod->driver->unlock(handle, &fence_fd);
312         if (ret)
313                 return ret;
314
315         ret = cros_gralloc_sync_wait(fence_fd, /*close_acquire_fence=*/true);
316         if (ret)
317                 return ret;
318
319         return 0;
320 }
321
322 static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
323 {
324         va_list args;
325         int32_t *out_format, ret;
326         uint64_t *out_store;
327         buffer_handle_t handle;
328         uint32_t *out_width, *out_height, *out_stride;
329         uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
330         uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
331         struct cros_gralloc0_buffer_info *info;
332         auto mod = (struct gralloc0_module const *)module;
333
334         switch (op) {
335         case GRALLOC_MODULE_PERFORM_GET_DRM_FD:
336         case GRALLOC_MODULE_PERFORM_ENTER_VT:
337         case GRALLOC_MODULE_PERFORM_LEAVE_VT:
338         case GRALLOC_DRM_GET_STRIDE:
339         case GRALLOC_DRM_GET_FORMAT:
340         case GRALLOC_DRM_GET_DIMENSIONS:
341         case GRALLOC_DRM_GET_BACKING_STORE:
342         case GRALLOC_DRM_GET_BUFFER_INFO:
343                 break;
344         default:
345                 return -EINVAL;
346         }
347
348         va_start(args, op);
349         ret = 0;
350
351         switch (op) {
352         case GRALLOC_MODULE_PERFORM_GET_DRM_FD: {
353                 int *fd = va_arg(args, int*);
354                 *fd = mod->driver->get_fd();
355                 break;
356         }
357         case GRALLOC_MODULE_PERFORM_ENTER_VT:
358                 ret = drmSetMaster(mod->driver->get_fd());
359                 break;
360         case GRALLOC_MODULE_PERFORM_LEAVE_VT:
361                 ret = drmDropMaster(mod->driver->get_fd());
362                 break;
363         default:
364                 goto other;
365         }
366
367         va_end(args);
368         return ret;
369
370 other:
371         handle = va_arg(args, buffer_handle_t);
372         auto hnd = cros_gralloc_convert_handle(handle);
373         if (!hnd) {
374                 drv_log("Invalid handle.\n");
375                 return -EINVAL;
376         }
377
378         switch (op) {
379         case GRALLOC_DRM_GET_STRIDE:
380                 out_stride = va_arg(args, uint32_t *);
381                 ret = mod->driver->resource_info(handle, strides, offsets);
382                 if (ret)
383                         break;
384
385                 if (strides[0] != hnd->strides[0]) {
386                         uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
387                         *out_stride = DIV_ROUND_UP(strides[0], bytes_per_pixel);
388                 } else {
389                         *out_stride = hnd->pixel_stride;
390                 }
391
392                 break;
393         case GRALLOC_DRM_GET_FORMAT:
394                 out_format = va_arg(args, int32_t *);
395                 *out_format = hnd->droid_format;
396                 break;
397         case GRALLOC_DRM_GET_DIMENSIONS:
398                 out_width = va_arg(args, uint32_t *);
399                 out_height = va_arg(args, uint32_t *);
400                 *out_width = hnd->width;
401                 *out_height = hnd->height;
402                 break;
403         case GRALLOC_DRM_GET_BACKING_STORE:
404                 out_store = va_arg(args, uint64_t *);
405                 ret = mod->driver->get_backing_store(handle, out_store);
406                 break;
407         case GRALLOC_DRM_GET_BUFFER_INFO:
408                 info = va_arg(args, struct cros_gralloc0_buffer_info *);
409                 info->drm_fourcc = drv_get_standard_fourcc(hnd->format);
410                 info->num_fds = hnd->num_planes;
411                 info->modifier = hnd->format_modifier;
412                 for (uint32_t i = 0; i < hnd->num_planes; i++) {
413                         info->fds[i] = hnd->fds[i];
414                         info->offset[i] = hnd->offsets[i];
415                         info->stride[i] = hnd->strides[i];
416                 }
417                 break;
418         default:
419                 ret = -EINVAL;
420         }
421
422         va_end(args);
423
424         return ret;
425 }
426
427 static int gralloc0_lock_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle,
428                                int usage, int l, int t, int w, int h, struct android_ycbcr *ycbcr)
429 {
430         return module->lockAsync_ycbcr(module, handle, usage, l, t, w, h, ycbcr, -1);
431 }
432
433 static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_handle_t handle,
434                                int usage, int l, int t, int w, int h, void **vaddr, int fence_fd)
435 {
436         int32_t ret;
437         uint32_t map_flags;
438         uint8_t *addr[DRV_MAX_PLANES];
439         auto mod = (struct gralloc0_module const *)module;
440         struct rectangle rect = { .x = static_cast<uint32_t>(l),
441                                   .y = static_cast<uint32_t>(t),
442                                   .width = static_cast<uint32_t>(w),
443                                   .height = static_cast<uint32_t>(h) };
444
445         auto hnd = cros_gralloc_convert_handle(handle);
446         if (!hnd) {
447                 drv_log("Invalid handle.\n");
448                 return -EINVAL;
449         }
450
451         if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
452                 drv_log("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.\n");
453                 return -EINVAL;
454         }
455
456         assert(l >= 0);
457         assert(t >= 0);
458         assert(w >= 0);
459         assert(h >= 0);
460
461         map_flags = gralloc0_convert_map_usage(usage);
462         ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
463         *vaddr = addr[0];
464         return ret;
465 }
466
467 static int gralloc0_unlock_async(struct gralloc_module_t const *module, buffer_handle_t handle,
468                                  int *fence_fd)
469 {
470         auto mod = (struct gralloc0_module const *)module;
471         return mod->driver->unlock(handle, fence_fd);
472 }
473
474 static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle,
475                                      int usage, int l, int t, int w, int h,
476                                      struct android_ycbcr *ycbcr, int fence_fd)
477 {
478         int32_t ret;
479         uint32_t map_flags;
480         uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
481         uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
482         uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
483         auto mod = (struct gralloc0_module const *)module;
484         struct rectangle rect = { .x = static_cast<uint32_t>(l),
485                                   .y = static_cast<uint32_t>(t),
486                                   .width = static_cast<uint32_t>(w),
487                                   .height = static_cast<uint32_t>(h) };
488
489         auto hnd = cros_gralloc_convert_handle(handle);
490         if (!hnd) {
491                 drv_log("Invalid handle.\n");
492                 return -EINVAL;
493         }
494
495         if (!gralloc0_droid_yuv_format(hnd->droid_format) &&
496             hnd->droid_format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
497                 drv_log("Non-YUV format not compatible.\n");
498                 return -EINVAL;
499         }
500
501         assert(l >= 0);
502         assert(t >= 0);
503         assert(w >= 0);
504         assert(h >= 0);
505
506         map_flags = gralloc0_convert_map_usage(usage);
507         ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
508         if (ret)
509                 return ret;
510
511         if (!map_flags) {
512                 ret = mod->driver->resource_info(handle, strides, offsets);
513                 if (ret)
514                         return ret;
515
516                 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
517                         addr[plane] =
518                             reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(offsets[plane]));
519         }
520
521         switch (hnd->format) {
522         case DRM_FORMAT_NV12:
523                 ycbcr->y = addr[0];
524                 ycbcr->cb = addr[1];
525                 ycbcr->cr = addr[1] + 1;
526                 ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
527                 ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
528                 ycbcr->chroma_step = 2;
529                 break;
530         case DRM_FORMAT_YVU420:
531         case DRM_FORMAT_YVU420_ANDROID:
532                 ycbcr->y = addr[0];
533                 ycbcr->cb = addr[2];
534                 ycbcr->cr = addr[1];
535                 ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
536                 ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
537                 ycbcr->chroma_step = 1;
538                 break;
539         default:
540                 module->unlock(module, handle);
541                 return -EINVAL;
542         }
543
544         return 0;
545 }
546
547 // clang-format off
548 static struct hw_module_methods_t gralloc0_module_methods = { .open = gralloc0_open };
549 // clang-format on
550
551 struct gralloc0_module HAL_MODULE_INFO_SYM = {
552         .base =
553             {
554                 .common =
555                     {
556                         .tag = HARDWARE_MODULE_TAG,
557                         .module_api_version = GRALLOC_MODULE_API_VERSION_0_3,
558                         .hal_api_version = 0,
559                         .id = GRALLOC_HARDWARE_MODULE_ID,
560                         .name = "CrOS Gralloc",
561                         .author = "Chrome OS",
562                         .methods = &gralloc0_module_methods,
563                     },
564
565                 .registerBuffer = gralloc0_register_buffer,
566                 .unregisterBuffer = gralloc0_unregister_buffer,
567                 .lock = gralloc0_lock,
568                 .unlock = gralloc0_unlock,
569                 .perform = gralloc0_perform,
570                 .lock_ycbcr = gralloc0_lock_ycbcr,
571                 .lockAsync = gralloc0_lock_async,
572                 .unlockAsync = gralloc0_unlock_async,
573                 .lockAsync_ycbcr = gralloc0_lock_async_ycbcr,
574             },
575
576         .alloc = nullptr,
577         .driver = nullptr,
578         .initialized = false,
579 };