1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright © 2021, Google Inc.
5 * SPDX-License-Identifier: MIT
6 */
7
8 #include <assert.h>
9 #include <dlfcn.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <hardware/gralloc.h>
13
14 #include "util/log.h"
15 #include "util/u_memory.h"
16
17 #include "u_gralloc_internal.h"
18
19 /* More recent CrOS gralloc has a perform op that fills out the struct below
20 * with canonical information about the buffer and its modifier, planes,
21 * offsets and strides. If we have this, we can skip straight to
22 * createImageFromDmaBufs2() and avoid all the guessing and recalculations.
23 * This also gives us the modifier and plane offsets/strides for multiplanar
24 * compressed buffers (eg Intel CCS buffers) in order to make that work in
25 * Android.
26 */
27
28 struct cros_gralloc {
29 struct u_gralloc base;
30 gralloc_module_t *gralloc_module;
31 };
32
33 static const char cros_gralloc_module_name[] = "CrOS Gralloc";
34
35 #define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
36 #define CROS_GRALLOC_DRM_GET_USAGE 5
37 #define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1
38
39 struct cros_gralloc0_buffer_info {
40 uint32_t drm_fourcc;
41 int num_fds;
42 int fds[4];
43 uint64_t modifier;
44 int offset[4];
45 int stride[4];
46 };
47
48 static int
cros_get_buffer_info(struct u_gralloc * gralloc,struct u_gralloc_buffer_handle * hnd,struct u_gralloc_buffer_basic_info * out)49 cros_get_buffer_info(struct u_gralloc *gralloc,
50 struct u_gralloc_buffer_handle *hnd,
51 struct u_gralloc_buffer_basic_info *out)
52 {
53 struct cros_gralloc0_buffer_info info;
54 struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
55 gralloc_module_t *gr_mod = gr->gralloc_module;
56
57 if (gr_mod->perform(gr_mod, CROS_GRALLOC_DRM_GET_BUFFER_INFO, hnd->handle,
58 &info) == 0) {
59 out->drm_fourcc = info.drm_fourcc;
60 out->modifier = info.modifier;
61 out->num_planes = info.num_fds;
62 for (int i = 0; i < out->num_planes; i++) {
63 out->fds[i] = info.fds[i];
64 out->offsets[i] = info.offset[i];
65 out->strides[i] = info.stride[i];
66 }
67
68 return 0;
69 }
70
71 return -EINVAL;
72 }
73
74 static int
cros_get_front_rendering_usage(struct u_gralloc * gralloc,uint64_t * out_usage)75 cros_get_front_rendering_usage(struct u_gralloc *gralloc, uint64_t *out_usage)
76 {
77 struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
78 uint32_t front_rendering_usage = 0;
79
80 if (gr->gralloc_module->perform(
81 gr->gralloc_module, CROS_GRALLOC_DRM_GET_USAGE,
82 CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,
83 &front_rendering_usage) == 0) {
84 *out_usage = front_rendering_usage;
85 return 0;
86 }
87
88 return -ENOTSUP;
89 }
90
91 static int
destroy(struct u_gralloc * gralloc)92 destroy(struct u_gralloc *gralloc)
93 {
94 struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
95 if (gr->gralloc_module)
96 dlclose(gr->gralloc_module->common.dso);
97
98 FREE(gr);
99
100 return 0;
101 }
102
103 struct u_gralloc *
u_gralloc_cros_api_create()104 u_gralloc_cros_api_create()
105 {
106 struct cros_gralloc *gr = CALLOC_STRUCT(cros_gralloc);
107 int err = 0;
108
109 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
110 (const hw_module_t **)&gr->gralloc_module);
111
112 if (err)
113 goto fail;
114
115 if (strcmp(gr->gralloc_module->common.name, cros_gralloc_module_name) != 0)
116 goto fail;
117
118 if (!gr->gralloc_module->perform) {
119 mesa_logw("Oops. CrOS gralloc doesn't have perform callback");
120 goto fail;
121 }
122
123 gr->base.ops.get_buffer_basic_info = cros_get_buffer_info;
124 gr->base.ops.get_front_rendering_usage = cros_get_front_rendering_usage;
125 gr->base.ops.destroy = destroy;
126
127 mesa_logi("Using gralloc0 CrOS API");
128
129 return &gr->base;
130
131 fail:
132 destroy(&gr->base);
133
134 return NULL;
135 }
136