xref: /aosp_15_r20/external/mesa3d/src/util/u_gralloc/u_gralloc.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2022 Roman Stratiienko ([email protected])
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "u_gralloc_internal.h"
9 
10 #include <assert.h>
11 #include <errno.h>
12 
13 #include "drm-uapi/drm_fourcc.h"
14 #include "util/log.h"
15 #include "util/macros.h"
16 #include "util/simple_mtx.h"
17 #include "util/u_atomic.h"
18 #include "util/u_memory.h"
19 
20 static simple_mtx_t u_gralloc_mutex = SIMPLE_MTX_INITIALIZER;
21 
22 static const struct u_grallocs {
23    enum u_gralloc_type type;
24    struct u_gralloc *(*create)();
25 } u_grallocs[] = {
26    /* Prefer the CrOS API as it is significantly faster than IMapper4 */
27    {.type = U_GRALLOC_TYPE_CROS, .create = u_gralloc_cros_api_create},
28 #ifdef USE_IMAPPER4_METADATA_API
29    {.type = U_GRALLOC_TYPE_GRALLOC4, .create = u_gralloc_imapper_api_create},
30 #endif /* USE_IMAPPER4_METADATA_API */
31    {.type = U_GRALLOC_TYPE_LIBDRM, .create = u_gralloc_libdrm_create},
32    {.type = U_GRALLOC_TYPE_QCOM, .create = u_gralloc_qcom_create},
33    {.type = U_GRALLOC_TYPE_FALLBACK, .create = u_gralloc_fallback_create},
34 };
35 
36 static struct u_gralloc_cache {
37    struct u_gralloc *u_gralloc;
38    int refcount;
39 } u_gralloc_cache[U_GRALLOC_TYPE_COUNT] = {0};
40 
41 struct u_gralloc *
u_gralloc_create(enum u_gralloc_type type)42 u_gralloc_create(enum u_gralloc_type type)
43 {
44    struct u_gralloc *out_gralloc = NULL;
45 
46    simple_mtx_lock(&u_gralloc_mutex);
47 
48    if (u_gralloc_cache[type].u_gralloc != NULL) {
49       u_gralloc_cache[type].refcount++;
50       out_gralloc = u_gralloc_cache[type].u_gralloc;
51       goto out;
52    }
53 
54    for (int i = 0; i < ARRAY_SIZE(u_grallocs); i++) {
55       if (u_grallocs[i].type != type && type != U_GRALLOC_TYPE_AUTO)
56          continue;
57 
58       u_gralloc_cache[type].u_gralloc = u_grallocs[i].create();
59       if (u_gralloc_cache[type].u_gralloc) {
60          assert(u_gralloc_cache[type].u_gralloc->ops.get_buffer_basic_info);
61          assert(u_gralloc_cache[type].u_gralloc->ops.destroy);
62 
63          u_gralloc_cache[type].u_gralloc->type = u_grallocs[i].type;
64          u_gralloc_cache[type].refcount = 1;
65 
66          out_gralloc = u_gralloc_cache[type].u_gralloc;
67          goto out;
68       }
69    }
70 
71 out:
72    simple_mtx_unlock(&u_gralloc_mutex);
73 
74    return out_gralloc;
75 }
76 
77 void
u_gralloc_destroy(struct u_gralloc ** gralloc)78 u_gralloc_destroy(struct u_gralloc **gralloc)
79 {
80    int i;
81 
82    if (*gralloc == NULL)
83       return;
84 
85    simple_mtx_lock(&u_gralloc_mutex);
86 
87    for (i = 0; i < ARRAY_SIZE(u_gralloc_cache); i++) {
88       if (u_gralloc_cache[i].u_gralloc == *gralloc) {
89          u_gralloc_cache[i].refcount--;
90          if (u_gralloc_cache[i].refcount == 0) {
91             u_gralloc_cache[i].u_gralloc->ops.destroy(
92                u_gralloc_cache[i].u_gralloc);
93             u_gralloc_cache[i].u_gralloc = NULL;
94          }
95          break;
96       }
97    }
98 
99    simple_mtx_unlock(&u_gralloc_mutex);
100 
101    assert(i < ARRAY_SIZE(u_grallocs));
102 
103    *gralloc = NULL;
104 }
105 
106 int
u_gralloc_get_buffer_basic_info(struct u_gralloc * gralloc,struct u_gralloc_buffer_handle * hnd,struct u_gralloc_buffer_basic_info * out)107 u_gralloc_get_buffer_basic_info(struct u_gralloc *gralloc,
108                                 struct u_gralloc_buffer_handle *hnd,
109                                 struct u_gralloc_buffer_basic_info *out)
110 {
111    struct u_gralloc_buffer_basic_info info = {0};
112    int ret;
113 
114    ret = gralloc->ops.get_buffer_basic_info(gralloc, hnd, &info);
115 
116    if (ret)
117       return ret;
118 
119    *out = info;
120 
121    return 0;
122 }
123 
124 int
u_gralloc_get_buffer_color_info(struct u_gralloc * gralloc,struct u_gralloc_buffer_handle * hnd,struct u_gralloc_buffer_color_info * out)125 u_gralloc_get_buffer_color_info(struct u_gralloc *gralloc,
126                                 struct u_gralloc_buffer_handle *hnd,
127                                 struct u_gralloc_buffer_color_info *out)
128 {
129    struct u_gralloc_buffer_color_info info = {0};
130    int ret;
131 
132    if (!gralloc->ops.get_buffer_color_info)
133       return -ENOTSUP;
134 
135    ret = gralloc->ops.get_buffer_color_info(gralloc, hnd, &info);
136 
137    if (ret)
138       return ret;
139 
140    *out = info;
141 
142    return 0;
143 }
144 
145 int
u_gralloc_get_front_rendering_usage(struct u_gralloc * gralloc,uint64_t * out_usage)146 u_gralloc_get_front_rendering_usage(struct u_gralloc *gralloc,
147                                     uint64_t *out_usage)
148 {
149    if (!gralloc->ops.get_front_rendering_usage)
150       return -ENOTSUP;
151 
152    return gralloc->ops.get_front_rendering_usage(gralloc, out_usage);
153 }
154 
155 int
u_gralloc_get_type(struct u_gralloc * gralloc)156 u_gralloc_get_type(struct u_gralloc *gralloc)
157 {
158    return gralloc->type;
159 }
160