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