xref: /aosp_15_r20/external/mesa3d/src/util/u_gralloc/u_gralloc_cros_api.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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