1*d95af8dfSAndroid Build Coastguard Worker /*
2*d95af8dfSAndroid Build Coastguard Worker * Copyright 2016 The Chromium OS Authors. All rights reserved.
3*d95af8dfSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
4*d95af8dfSAndroid Build Coastguard Worker * found in the LICENSE file.
5*d95af8dfSAndroid Build Coastguard Worker */
6*d95af8dfSAndroid Build Coastguard Worker #include <assert.h>
7*d95af8dfSAndroid Build Coastguard Worker #include <errno.h>
8*d95af8dfSAndroid Build Coastguard Worker #include <fcntl.h>
9*d95af8dfSAndroid Build Coastguard Worker #include <inttypes.h>
10*d95af8dfSAndroid Build Coastguard Worker #include <pthread.h>
11*d95af8dfSAndroid Build Coastguard Worker #include <stdint.h>
12*d95af8dfSAndroid Build Coastguard Worker #include <stdio.h>
13*d95af8dfSAndroid Build Coastguard Worker #include <string.h>
14*d95af8dfSAndroid Build Coastguard Worker #include <sys/mman.h>
15*d95af8dfSAndroid Build Coastguard Worker #include <sys/types.h>
16*d95af8dfSAndroid Build Coastguard Worker #include <unistd.h>
17*d95af8dfSAndroid Build Coastguard Worker #include <xf86drm.h>
18*d95af8dfSAndroid Build Coastguard Worker
19*d95af8dfSAndroid Build Coastguard Worker #ifdef __ANDROID__
20*d95af8dfSAndroid Build Coastguard Worker #include <cutils/log.h>
21*d95af8dfSAndroid Build Coastguard Worker #include <libgen.h>
22*d95af8dfSAndroid Build Coastguard Worker #define MINIGBM_DEBUG "vendor.minigbm.debug"
23*d95af8dfSAndroid Build Coastguard Worker #else
24*d95af8dfSAndroid Build Coastguard Worker #define MINIGBM_DEBUG "MINIGBM_DEBUG"
25*d95af8dfSAndroid Build Coastguard Worker #endif
26*d95af8dfSAndroid Build Coastguard Worker
27*d95af8dfSAndroid Build Coastguard Worker #include "drv_helpers.h"
28*d95af8dfSAndroid Build Coastguard Worker #include "drv_priv.h"
29*d95af8dfSAndroid Build Coastguard Worker #include "util.h"
30*d95af8dfSAndroid Build Coastguard Worker
31*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_AMDGPU
32*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_amdgpu;
33*d95af8dfSAndroid Build Coastguard Worker #endif
34*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_I915
35*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_i915;
36*d95af8dfSAndroid Build Coastguard Worker #endif
37*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_MSM
38*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_msm;
39*d95af8dfSAndroid Build Coastguard Worker #endif
40*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_VC4
41*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_vc4;
42*d95af8dfSAndroid Build Coastguard Worker #endif
43*d95af8dfSAndroid Build Coastguard Worker
44*d95af8dfSAndroid Build Coastguard Worker // Dumb / generic drivers
45*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_evdi;
46*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_marvell;
47*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_mediatek;
48*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_meson;
49*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_nouveau;
50*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_komeda;
51*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_radeon;
52*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_rockchip;
53*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_sun4i_drm;
54*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_synaptics;
55*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_virtgpu;
56*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_udl;
57*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_vkms;
58*d95af8dfSAndroid Build Coastguard Worker
59*d95af8dfSAndroid Build Coastguard Worker extern const struct backend backend_mock;
60*d95af8dfSAndroid Build Coastguard Worker
61*d95af8dfSAndroid Build Coastguard Worker static const struct backend *drv_backend_list[] = {
62*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_AMDGPU
63*d95af8dfSAndroid Build Coastguard Worker &backend_amdgpu,
64*d95af8dfSAndroid Build Coastguard Worker #endif
65*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_I915
66*d95af8dfSAndroid Build Coastguard Worker &backend_i915,
67*d95af8dfSAndroid Build Coastguard Worker #endif
68*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_MSM
69*d95af8dfSAndroid Build Coastguard Worker &backend_msm,
70*d95af8dfSAndroid Build Coastguard Worker #endif
71*d95af8dfSAndroid Build Coastguard Worker #ifdef DRV_VC4
72*d95af8dfSAndroid Build Coastguard Worker &backend_vc4,
73*d95af8dfSAndroid Build Coastguard Worker #endif
74*d95af8dfSAndroid Build Coastguard Worker &backend_evdi, &backend_komeda, &backend_marvell, &backend_mediatek,
75*d95af8dfSAndroid Build Coastguard Worker &backend_meson, &backend_nouveau, &backend_radeon, &backend_rockchip,
76*d95af8dfSAndroid Build Coastguard Worker &backend_sun4i_drm, &backend_synaptics, &backend_udl, &backend_virtgpu,
77*d95af8dfSAndroid Build Coastguard Worker &backend_vkms, &backend_mock
78*d95af8dfSAndroid Build Coastguard Worker };
79*d95af8dfSAndroid Build Coastguard Worker
drv_preload(bool load)80*d95af8dfSAndroid Build Coastguard Worker void drv_preload(bool load)
81*d95af8dfSAndroid Build Coastguard Worker {
82*d95af8dfSAndroid Build Coastguard Worker unsigned int i;
83*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) {
84*d95af8dfSAndroid Build Coastguard Worker const struct backend *b = drv_backend_list[i];
85*d95af8dfSAndroid Build Coastguard Worker if (b->preload)
86*d95af8dfSAndroid Build Coastguard Worker b->preload(load);
87*d95af8dfSAndroid Build Coastguard Worker }
88*d95af8dfSAndroid Build Coastguard Worker }
89*d95af8dfSAndroid Build Coastguard Worker
drv_get_backend(int fd)90*d95af8dfSAndroid Build Coastguard Worker static const struct backend *drv_get_backend(int fd)
91*d95af8dfSAndroid Build Coastguard Worker {
92*d95af8dfSAndroid Build Coastguard Worker drmVersionPtr drm_version;
93*d95af8dfSAndroid Build Coastguard Worker unsigned int i;
94*d95af8dfSAndroid Build Coastguard Worker
95*d95af8dfSAndroid Build Coastguard Worker drm_version = drmGetVersion(fd);
96*d95af8dfSAndroid Build Coastguard Worker
97*d95af8dfSAndroid Build Coastguard Worker if (!drm_version)
98*d95af8dfSAndroid Build Coastguard Worker return NULL;
99*d95af8dfSAndroid Build Coastguard Worker
100*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) {
101*d95af8dfSAndroid Build Coastguard Worker const struct backend *b = drv_backend_list[i];
102*d95af8dfSAndroid Build Coastguard Worker if (!strcmp(drm_version->name, b->name)) {
103*d95af8dfSAndroid Build Coastguard Worker drmFreeVersion(drm_version);
104*d95af8dfSAndroid Build Coastguard Worker return b;
105*d95af8dfSAndroid Build Coastguard Worker }
106*d95af8dfSAndroid Build Coastguard Worker }
107*d95af8dfSAndroid Build Coastguard Worker
108*d95af8dfSAndroid Build Coastguard Worker drmFreeVersion(drm_version);
109*d95af8dfSAndroid Build Coastguard Worker return NULL;
110*d95af8dfSAndroid Build Coastguard Worker }
111*d95af8dfSAndroid Build Coastguard Worker
drv_create(int fd)112*d95af8dfSAndroid Build Coastguard Worker struct driver *drv_create(int fd)
113*d95af8dfSAndroid Build Coastguard Worker {
114*d95af8dfSAndroid Build Coastguard Worker struct driver *drv;
115*d95af8dfSAndroid Build Coastguard Worker int ret;
116*d95af8dfSAndroid Build Coastguard Worker
117*d95af8dfSAndroid Build Coastguard Worker drv = (struct driver *)calloc(1, sizeof(*drv));
118*d95af8dfSAndroid Build Coastguard Worker
119*d95af8dfSAndroid Build Coastguard Worker if (!drv)
120*d95af8dfSAndroid Build Coastguard Worker return NULL;
121*d95af8dfSAndroid Build Coastguard Worker
122*d95af8dfSAndroid Build Coastguard Worker const char *minigbm_debug;
123*d95af8dfSAndroid Build Coastguard Worker minigbm_debug = drv_get_os_option(MINIGBM_DEBUG);
124*d95af8dfSAndroid Build Coastguard Worker drv->compression =
125*d95af8dfSAndroid Build Coastguard Worker (minigbm_debug == NULL) || (strstr(minigbm_debug, "nocompression") == NULL);
126*d95af8dfSAndroid Build Coastguard Worker drv->log_bos = (minigbm_debug && strstr(minigbm_debug, "log_bos") != NULL);
127*d95af8dfSAndroid Build Coastguard Worker
128*d95af8dfSAndroid Build Coastguard Worker drv->fd = fd;
129*d95af8dfSAndroid Build Coastguard Worker drv->backend = drv_get_backend(fd);
130*d95af8dfSAndroid Build Coastguard Worker
131*d95af8dfSAndroid Build Coastguard Worker if (!drv->backend)
132*d95af8dfSAndroid Build Coastguard Worker goto free_driver;
133*d95af8dfSAndroid Build Coastguard Worker
134*d95af8dfSAndroid Build Coastguard Worker if (pthread_mutex_init(&drv->buffer_table_lock, NULL))
135*d95af8dfSAndroid Build Coastguard Worker goto free_driver;
136*d95af8dfSAndroid Build Coastguard Worker
137*d95af8dfSAndroid Build Coastguard Worker drv->buffer_table = drmHashCreate();
138*d95af8dfSAndroid Build Coastguard Worker if (!drv->buffer_table)
139*d95af8dfSAndroid Build Coastguard Worker goto free_buffer_table_lock;
140*d95af8dfSAndroid Build Coastguard Worker
141*d95af8dfSAndroid Build Coastguard Worker if (pthread_mutex_init(&drv->mappings_lock, NULL))
142*d95af8dfSAndroid Build Coastguard Worker goto free_buffer_table;
143*d95af8dfSAndroid Build Coastguard Worker
144*d95af8dfSAndroid Build Coastguard Worker drv->mappings = drv_array_init(sizeof(struct mapping));
145*d95af8dfSAndroid Build Coastguard Worker if (!drv->mappings)
146*d95af8dfSAndroid Build Coastguard Worker goto free_mappings_lock;
147*d95af8dfSAndroid Build Coastguard Worker
148*d95af8dfSAndroid Build Coastguard Worker drv->combos = drv_array_init(sizeof(struct combination));
149*d95af8dfSAndroid Build Coastguard Worker if (!drv->combos)
150*d95af8dfSAndroid Build Coastguard Worker goto free_mappings;
151*d95af8dfSAndroid Build Coastguard Worker
152*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->init) {
153*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->init(drv);
154*d95af8dfSAndroid Build Coastguard Worker if (ret) {
155*d95af8dfSAndroid Build Coastguard Worker drv_array_destroy(drv->combos);
156*d95af8dfSAndroid Build Coastguard Worker goto free_mappings;
157*d95af8dfSAndroid Build Coastguard Worker }
158*d95af8dfSAndroid Build Coastguard Worker }
159*d95af8dfSAndroid Build Coastguard Worker
160*d95af8dfSAndroid Build Coastguard Worker return drv;
161*d95af8dfSAndroid Build Coastguard Worker
162*d95af8dfSAndroid Build Coastguard Worker free_mappings:
163*d95af8dfSAndroid Build Coastguard Worker drv_array_destroy(drv->mappings);
164*d95af8dfSAndroid Build Coastguard Worker free_mappings_lock:
165*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_destroy(&drv->mappings_lock);
166*d95af8dfSAndroid Build Coastguard Worker free_buffer_table:
167*d95af8dfSAndroid Build Coastguard Worker drmHashDestroy(drv->buffer_table);
168*d95af8dfSAndroid Build Coastguard Worker free_buffer_table_lock:
169*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_destroy(&drv->buffer_table_lock);
170*d95af8dfSAndroid Build Coastguard Worker free_driver:
171*d95af8dfSAndroid Build Coastguard Worker free(drv);
172*d95af8dfSAndroid Build Coastguard Worker return NULL;
173*d95af8dfSAndroid Build Coastguard Worker }
174*d95af8dfSAndroid Build Coastguard Worker
drv_destroy(struct driver * drv)175*d95af8dfSAndroid Build Coastguard Worker void drv_destroy(struct driver *drv)
176*d95af8dfSAndroid Build Coastguard Worker {
177*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->close)
178*d95af8dfSAndroid Build Coastguard Worker drv->backend->close(drv);
179*d95af8dfSAndroid Build Coastguard Worker
180*d95af8dfSAndroid Build Coastguard Worker drv_array_destroy(drv->combos);
181*d95af8dfSAndroid Build Coastguard Worker
182*d95af8dfSAndroid Build Coastguard Worker drv_array_destroy(drv->mappings);
183*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_destroy(&drv->mappings_lock);
184*d95af8dfSAndroid Build Coastguard Worker
185*d95af8dfSAndroid Build Coastguard Worker drmHashDestroy(drv->buffer_table);
186*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_destroy(&drv->buffer_table_lock);
187*d95af8dfSAndroid Build Coastguard Worker
188*d95af8dfSAndroid Build Coastguard Worker free(drv);
189*d95af8dfSAndroid Build Coastguard Worker }
190*d95af8dfSAndroid Build Coastguard Worker
drv_get_fd(struct driver * drv)191*d95af8dfSAndroid Build Coastguard Worker int drv_get_fd(struct driver *drv)
192*d95af8dfSAndroid Build Coastguard Worker {
193*d95af8dfSAndroid Build Coastguard Worker return drv->fd;
194*d95af8dfSAndroid Build Coastguard Worker }
195*d95af8dfSAndroid Build Coastguard Worker
drv_get_name(struct driver * drv)196*d95af8dfSAndroid Build Coastguard Worker const char *drv_get_name(struct driver *drv)
197*d95af8dfSAndroid Build Coastguard Worker {
198*d95af8dfSAndroid Build Coastguard Worker return drv->backend->name;
199*d95af8dfSAndroid Build Coastguard Worker }
200*d95af8dfSAndroid Build Coastguard Worker
drv_get_combination(struct driver * drv,uint32_t format,uint64_t use_flags)201*d95af8dfSAndroid Build Coastguard Worker struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags)
202*d95af8dfSAndroid Build Coastguard Worker {
203*d95af8dfSAndroid Build Coastguard Worker struct combination *curr, *best;
204*d95af8dfSAndroid Build Coastguard Worker
205*d95af8dfSAndroid Build Coastguard Worker if (format == DRM_FORMAT_NONE || use_flags == BO_USE_NONE)
206*d95af8dfSAndroid Build Coastguard Worker return 0;
207*d95af8dfSAndroid Build Coastguard Worker
208*d95af8dfSAndroid Build Coastguard Worker best = NULL;
209*d95af8dfSAndroid Build Coastguard Worker uint32_t i;
210*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < drv_array_size(drv->combos); i++) {
211*d95af8dfSAndroid Build Coastguard Worker curr = drv_array_at_idx(drv->combos, i);
212*d95af8dfSAndroid Build Coastguard Worker if ((format == curr->format) && use_flags == (curr->use_flags & use_flags))
213*d95af8dfSAndroid Build Coastguard Worker if (!best || best->metadata.priority < curr->metadata.priority)
214*d95af8dfSAndroid Build Coastguard Worker best = curr;
215*d95af8dfSAndroid Build Coastguard Worker }
216*d95af8dfSAndroid Build Coastguard Worker
217*d95af8dfSAndroid Build Coastguard Worker return best;
218*d95af8dfSAndroid Build Coastguard Worker }
219*d95af8dfSAndroid Build Coastguard Worker
drv_bo_new(struct driver * drv,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags,bool is_test_buffer)220*d95af8dfSAndroid Build Coastguard Worker struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
221*d95af8dfSAndroid Build Coastguard Worker uint64_t use_flags, bool is_test_buffer)
222*d95af8dfSAndroid Build Coastguard Worker {
223*d95af8dfSAndroid Build Coastguard Worker
224*d95af8dfSAndroid Build Coastguard Worker struct bo *bo;
225*d95af8dfSAndroid Build Coastguard Worker bo = (struct bo *)calloc(1, sizeof(*bo));
226*d95af8dfSAndroid Build Coastguard Worker
227*d95af8dfSAndroid Build Coastguard Worker if (!bo)
228*d95af8dfSAndroid Build Coastguard Worker return NULL;
229*d95af8dfSAndroid Build Coastguard Worker
230*d95af8dfSAndroid Build Coastguard Worker bo->drv = drv;
231*d95af8dfSAndroid Build Coastguard Worker bo->meta.width = width;
232*d95af8dfSAndroid Build Coastguard Worker bo->meta.height = height;
233*d95af8dfSAndroid Build Coastguard Worker bo->meta.format = format;
234*d95af8dfSAndroid Build Coastguard Worker bo->meta.use_flags = use_flags;
235*d95af8dfSAndroid Build Coastguard Worker bo->meta.num_planes = drv_num_planes_from_format(format);
236*d95af8dfSAndroid Build Coastguard Worker bo->is_test_buffer = is_test_buffer;
237*d95af8dfSAndroid Build Coastguard Worker
238*d95af8dfSAndroid Build Coastguard Worker if (!bo->meta.num_planes) {
239*d95af8dfSAndroid Build Coastguard Worker free(bo);
240*d95af8dfSAndroid Build Coastguard Worker errno = EINVAL;
241*d95af8dfSAndroid Build Coastguard Worker return NULL;
242*d95af8dfSAndroid Build Coastguard Worker }
243*d95af8dfSAndroid Build Coastguard Worker
244*d95af8dfSAndroid Build Coastguard Worker return bo;
245*d95af8dfSAndroid Build Coastguard Worker }
246*d95af8dfSAndroid Build Coastguard Worker
drv_bo_mapping_destroy(struct bo * bo)247*d95af8dfSAndroid Build Coastguard Worker static void drv_bo_mapping_destroy(struct bo *bo)
248*d95af8dfSAndroid Build Coastguard Worker {
249*d95af8dfSAndroid Build Coastguard Worker struct driver *drv = bo->drv;
250*d95af8dfSAndroid Build Coastguard Worker uint32_t idx = 0;
251*d95af8dfSAndroid Build Coastguard Worker
252*d95af8dfSAndroid Build Coastguard Worker /*
253*d95af8dfSAndroid Build Coastguard Worker * This function is called right before the buffer is destroyed. It will free any mappings
254*d95af8dfSAndroid Build Coastguard Worker * associated with the buffer.
255*d95af8dfSAndroid Build Coastguard Worker */
256*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_lock(&drv->mappings_lock);
257*d95af8dfSAndroid Build Coastguard Worker for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
258*d95af8dfSAndroid Build Coastguard Worker while (idx < drv_array_size(drv->mappings)) {
259*d95af8dfSAndroid Build Coastguard Worker struct mapping *mapping =
260*d95af8dfSAndroid Build Coastguard Worker (struct mapping *)drv_array_at_idx(drv->mappings, idx);
261*d95af8dfSAndroid Build Coastguard Worker if (mapping->vma->handle != bo->handle.u32) {
262*d95af8dfSAndroid Build Coastguard Worker idx++;
263*d95af8dfSAndroid Build Coastguard Worker continue;
264*d95af8dfSAndroid Build Coastguard Worker }
265*d95af8dfSAndroid Build Coastguard Worker
266*d95af8dfSAndroid Build Coastguard Worker if (!--mapping->vma->refcount) {
267*d95af8dfSAndroid Build Coastguard Worker int ret = drv->backend->bo_unmap(bo, mapping->vma);
268*d95af8dfSAndroid Build Coastguard Worker if (ret) {
269*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
270*d95af8dfSAndroid Build Coastguard Worker assert(ret);
271*d95af8dfSAndroid Build Coastguard Worker drv_loge("munmap failed\n");
272*d95af8dfSAndroid Build Coastguard Worker return;
273*d95af8dfSAndroid Build Coastguard Worker }
274*d95af8dfSAndroid Build Coastguard Worker
275*d95af8dfSAndroid Build Coastguard Worker free(mapping->vma);
276*d95af8dfSAndroid Build Coastguard Worker }
277*d95af8dfSAndroid Build Coastguard Worker
278*d95af8dfSAndroid Build Coastguard Worker /* This shrinks and shifts the array, so don't increment idx. */
279*d95af8dfSAndroid Build Coastguard Worker drv_array_remove(drv->mappings, idx);
280*d95af8dfSAndroid Build Coastguard Worker }
281*d95af8dfSAndroid Build Coastguard Worker }
282*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
283*d95af8dfSAndroid Build Coastguard Worker }
284*d95af8dfSAndroid Build Coastguard Worker
285*d95af8dfSAndroid Build Coastguard Worker /*
286*d95af8dfSAndroid Build Coastguard Worker * Acquire a reference on plane buffers of the bo.
287*d95af8dfSAndroid Build Coastguard Worker */
drv_bo_acquire(struct bo * bo)288*d95af8dfSAndroid Build Coastguard Worker static void drv_bo_acquire(struct bo *bo)
289*d95af8dfSAndroid Build Coastguard Worker {
290*d95af8dfSAndroid Build Coastguard Worker struct driver *drv = bo->drv;
291*d95af8dfSAndroid Build Coastguard Worker
292*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_lock(&drv->buffer_table_lock);
293*d95af8dfSAndroid Build Coastguard Worker for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
294*d95af8dfSAndroid Build Coastguard Worker uintptr_t num = 0;
295*d95af8dfSAndroid Build Coastguard Worker
296*d95af8dfSAndroid Build Coastguard Worker if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num))
297*d95af8dfSAndroid Build Coastguard Worker drmHashDelete(drv->buffer_table, bo->handle.u32);
298*d95af8dfSAndroid Build Coastguard Worker
299*d95af8dfSAndroid Build Coastguard Worker drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num + 1));
300*d95af8dfSAndroid Build Coastguard Worker }
301*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->buffer_table_lock);
302*d95af8dfSAndroid Build Coastguard Worker }
303*d95af8dfSAndroid Build Coastguard Worker
304*d95af8dfSAndroid Build Coastguard Worker /*
305*d95af8dfSAndroid Build Coastguard Worker * Release a reference on plane buffers of the bo. Return true when the bo has lost all its
306*d95af8dfSAndroid Build Coastguard Worker * references. Otherwise, return false.
307*d95af8dfSAndroid Build Coastguard Worker */
drv_bo_release(struct bo * bo)308*d95af8dfSAndroid Build Coastguard Worker static bool drv_bo_release(struct bo *bo)
309*d95af8dfSAndroid Build Coastguard Worker {
310*d95af8dfSAndroid Build Coastguard Worker struct driver *drv = bo->drv;
311*d95af8dfSAndroid Build Coastguard Worker uintptr_t num;
312*d95af8dfSAndroid Build Coastguard Worker
313*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->bo_release)
314*d95af8dfSAndroid Build Coastguard Worker drv->backend->bo_release(bo);
315*d95af8dfSAndroid Build Coastguard Worker
316*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_lock(&drv->buffer_table_lock);
317*d95af8dfSAndroid Build Coastguard Worker for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
318*d95af8dfSAndroid Build Coastguard Worker if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
319*d95af8dfSAndroid Build Coastguard Worker drmHashDelete(drv->buffer_table, bo->handle.u32);
320*d95af8dfSAndroid Build Coastguard Worker
321*d95af8dfSAndroid Build Coastguard Worker if (num > 1) {
322*d95af8dfSAndroid Build Coastguard Worker drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num - 1));
323*d95af8dfSAndroid Build Coastguard Worker }
324*d95af8dfSAndroid Build Coastguard Worker }
325*d95af8dfSAndroid Build Coastguard Worker }
326*d95af8dfSAndroid Build Coastguard Worker
327*d95af8dfSAndroid Build Coastguard Worker /* The same buffer can back multiple planes with different offsets. */
328*d95af8dfSAndroid Build Coastguard Worker for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
329*d95af8dfSAndroid Build Coastguard Worker if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
330*d95af8dfSAndroid Build Coastguard Worker /* num is positive if found in the hashmap. */
331*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->buffer_table_lock);
332*d95af8dfSAndroid Build Coastguard Worker return false;
333*d95af8dfSAndroid Build Coastguard Worker }
334*d95af8dfSAndroid Build Coastguard Worker }
335*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->buffer_table_lock);
336*d95af8dfSAndroid Build Coastguard Worker
337*d95af8dfSAndroid Build Coastguard Worker return true;
338*d95af8dfSAndroid Build Coastguard Worker }
339*d95af8dfSAndroid Build Coastguard Worker
drv_bo_create(struct driver * drv,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags)340*d95af8dfSAndroid Build Coastguard Worker struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
341*d95af8dfSAndroid Build Coastguard Worker uint64_t use_flags)
342*d95af8dfSAndroid Build Coastguard Worker {
343*d95af8dfSAndroid Build Coastguard Worker int ret;
344*d95af8dfSAndroid Build Coastguard Worker struct bo *bo;
345*d95af8dfSAndroid Build Coastguard Worker bool is_test_alloc;
346*d95af8dfSAndroid Build Coastguard Worker
347*d95af8dfSAndroid Build Coastguard Worker is_test_alloc = use_flags & BO_USE_TEST_ALLOC;
348*d95af8dfSAndroid Build Coastguard Worker use_flags &= ~BO_USE_TEST_ALLOC;
349*d95af8dfSAndroid Build Coastguard Worker
350*d95af8dfSAndroid Build Coastguard Worker bo = drv_bo_new(drv, width, height, format, use_flags, is_test_alloc);
351*d95af8dfSAndroid Build Coastguard Worker
352*d95af8dfSAndroid Build Coastguard Worker if (!bo)
353*d95af8dfSAndroid Build Coastguard Worker return NULL;
354*d95af8dfSAndroid Build Coastguard Worker
355*d95af8dfSAndroid Build Coastguard Worker ret = -EINVAL;
356*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->bo_compute_metadata) {
357*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_compute_metadata(bo, width, height, format, use_flags, NULL,
358*d95af8dfSAndroid Build Coastguard Worker 0);
359*d95af8dfSAndroid Build Coastguard Worker if (!is_test_alloc && ret == 0)
360*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_create_from_metadata(bo);
361*d95af8dfSAndroid Build Coastguard Worker } else if (!is_test_alloc) {
362*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_create(bo, width, height, format, use_flags);
363*d95af8dfSAndroid Build Coastguard Worker }
364*d95af8dfSAndroid Build Coastguard Worker
365*d95af8dfSAndroid Build Coastguard Worker if (ret) {
366*d95af8dfSAndroid Build Coastguard Worker errno = -ret;
367*d95af8dfSAndroid Build Coastguard Worker free(bo);
368*d95af8dfSAndroid Build Coastguard Worker return NULL;
369*d95af8dfSAndroid Build Coastguard Worker }
370*d95af8dfSAndroid Build Coastguard Worker
371*d95af8dfSAndroid Build Coastguard Worker drv_bo_acquire(bo);
372*d95af8dfSAndroid Build Coastguard Worker
373*d95af8dfSAndroid Build Coastguard Worker if (drv->log_bos)
374*d95af8dfSAndroid Build Coastguard Worker drv_bo_log_info(bo, "legacy created");
375*d95af8dfSAndroid Build Coastguard Worker
376*d95af8dfSAndroid Build Coastguard Worker return bo;
377*d95af8dfSAndroid Build Coastguard Worker }
378*d95af8dfSAndroid Build Coastguard Worker
drv_bo_create_with_modifiers(struct driver * drv,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,uint32_t count)379*d95af8dfSAndroid Build Coastguard Worker struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
380*d95af8dfSAndroid Build Coastguard Worker uint32_t format, const uint64_t *modifiers, uint32_t count)
381*d95af8dfSAndroid Build Coastguard Worker {
382*d95af8dfSAndroid Build Coastguard Worker int ret;
383*d95af8dfSAndroid Build Coastguard Worker struct bo *bo;
384*d95af8dfSAndroid Build Coastguard Worker
385*d95af8dfSAndroid Build Coastguard Worker if (!drv->backend->bo_create_with_modifiers && !drv->backend->bo_compute_metadata) {
386*d95af8dfSAndroid Build Coastguard Worker errno = ENOENT;
387*d95af8dfSAndroid Build Coastguard Worker return NULL;
388*d95af8dfSAndroid Build Coastguard Worker }
389*d95af8dfSAndroid Build Coastguard Worker
390*d95af8dfSAndroid Build Coastguard Worker bo = drv_bo_new(drv, width, height, format, BO_USE_NONE, false);
391*d95af8dfSAndroid Build Coastguard Worker
392*d95af8dfSAndroid Build Coastguard Worker if (!bo)
393*d95af8dfSAndroid Build Coastguard Worker return NULL;
394*d95af8dfSAndroid Build Coastguard Worker
395*d95af8dfSAndroid Build Coastguard Worker ret = -EINVAL;
396*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->bo_compute_metadata) {
397*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_compute_metadata(bo, width, height, format, BO_USE_NONE,
398*d95af8dfSAndroid Build Coastguard Worker modifiers, count);
399*d95af8dfSAndroid Build Coastguard Worker if (ret == 0)
400*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_create_from_metadata(bo);
401*d95af8dfSAndroid Build Coastguard Worker } else {
402*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers,
403*d95af8dfSAndroid Build Coastguard Worker count);
404*d95af8dfSAndroid Build Coastguard Worker }
405*d95af8dfSAndroid Build Coastguard Worker
406*d95af8dfSAndroid Build Coastguard Worker if (ret) {
407*d95af8dfSAndroid Build Coastguard Worker free(bo);
408*d95af8dfSAndroid Build Coastguard Worker return NULL;
409*d95af8dfSAndroid Build Coastguard Worker }
410*d95af8dfSAndroid Build Coastguard Worker
411*d95af8dfSAndroid Build Coastguard Worker drv_bo_acquire(bo);
412*d95af8dfSAndroid Build Coastguard Worker
413*d95af8dfSAndroid Build Coastguard Worker if (drv->log_bos)
414*d95af8dfSAndroid Build Coastguard Worker drv_bo_log_info(bo, "created");
415*d95af8dfSAndroid Build Coastguard Worker
416*d95af8dfSAndroid Build Coastguard Worker return bo;
417*d95af8dfSAndroid Build Coastguard Worker }
418*d95af8dfSAndroid Build Coastguard Worker
drv_bo_destroy(struct bo * bo)419*d95af8dfSAndroid Build Coastguard Worker void drv_bo_destroy(struct bo *bo)
420*d95af8dfSAndroid Build Coastguard Worker {
421*d95af8dfSAndroid Build Coastguard Worker if (!bo->is_test_buffer && drv_bo_release(bo)) {
422*d95af8dfSAndroid Build Coastguard Worker drv_bo_mapping_destroy(bo);
423*d95af8dfSAndroid Build Coastguard Worker bo->drv->backend->bo_destroy(bo);
424*d95af8dfSAndroid Build Coastguard Worker }
425*d95af8dfSAndroid Build Coastguard Worker
426*d95af8dfSAndroid Build Coastguard Worker free(bo);
427*d95af8dfSAndroid Build Coastguard Worker }
428*d95af8dfSAndroid Build Coastguard Worker
drv_bo_import(struct driver * drv,struct drv_import_fd_data * data)429*d95af8dfSAndroid Build Coastguard Worker struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
430*d95af8dfSAndroid Build Coastguard Worker {
431*d95af8dfSAndroid Build Coastguard Worker int ret;
432*d95af8dfSAndroid Build Coastguard Worker size_t plane;
433*d95af8dfSAndroid Build Coastguard Worker struct bo *bo;
434*d95af8dfSAndroid Build Coastguard Worker off_t seek_end;
435*d95af8dfSAndroid Build Coastguard Worker
436*d95af8dfSAndroid Build Coastguard Worker bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags, false);
437*d95af8dfSAndroid Build Coastguard Worker
438*d95af8dfSAndroid Build Coastguard Worker if (!bo)
439*d95af8dfSAndroid Build Coastguard Worker return NULL;
440*d95af8dfSAndroid Build Coastguard Worker
441*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_import(bo, data);
442*d95af8dfSAndroid Build Coastguard Worker if (ret) {
443*d95af8dfSAndroid Build Coastguard Worker free(bo);
444*d95af8dfSAndroid Build Coastguard Worker return NULL;
445*d95af8dfSAndroid Build Coastguard Worker }
446*d95af8dfSAndroid Build Coastguard Worker
447*d95af8dfSAndroid Build Coastguard Worker drv_bo_acquire(bo);
448*d95af8dfSAndroid Build Coastguard Worker
449*d95af8dfSAndroid Build Coastguard Worker bo->meta.format_modifier = data->format_modifier;
450*d95af8dfSAndroid Build Coastguard Worker for (plane = 0; plane < bo->meta.num_planes; plane++) {
451*d95af8dfSAndroid Build Coastguard Worker bo->meta.strides[plane] = data->strides[plane];
452*d95af8dfSAndroid Build Coastguard Worker bo->meta.offsets[plane] = data->offsets[plane];
453*d95af8dfSAndroid Build Coastguard Worker
454*d95af8dfSAndroid Build Coastguard Worker seek_end = lseek(data->fds[plane], 0, SEEK_END);
455*d95af8dfSAndroid Build Coastguard Worker if (seek_end == (off_t)(-1)) {
456*d95af8dfSAndroid Build Coastguard Worker drv_loge("lseek() failed with %s\n", strerror(errno));
457*d95af8dfSAndroid Build Coastguard Worker goto destroy_bo;
458*d95af8dfSAndroid Build Coastguard Worker }
459*d95af8dfSAndroid Build Coastguard Worker
460*d95af8dfSAndroid Build Coastguard Worker lseek(data->fds[plane], 0, SEEK_SET);
461*d95af8dfSAndroid Build Coastguard Worker if (plane == bo->meta.num_planes - 1 || data->offsets[plane + 1] == 0)
462*d95af8dfSAndroid Build Coastguard Worker bo->meta.sizes[plane] = seek_end - data->offsets[plane];
463*d95af8dfSAndroid Build Coastguard Worker else
464*d95af8dfSAndroid Build Coastguard Worker bo->meta.sizes[plane] = data->offsets[plane + 1] - data->offsets[plane];
465*d95af8dfSAndroid Build Coastguard Worker
466*d95af8dfSAndroid Build Coastguard Worker if ((int64_t)bo->meta.offsets[plane] + bo->meta.sizes[plane] > seek_end) {
467*d95af8dfSAndroid Build Coastguard Worker drv_loge("buffer size is too large.\n");
468*d95af8dfSAndroid Build Coastguard Worker goto destroy_bo;
469*d95af8dfSAndroid Build Coastguard Worker }
470*d95af8dfSAndroid Build Coastguard Worker
471*d95af8dfSAndroid Build Coastguard Worker bo->meta.total_size += bo->meta.sizes[plane];
472*d95af8dfSAndroid Build Coastguard Worker }
473*d95af8dfSAndroid Build Coastguard Worker
474*d95af8dfSAndroid Build Coastguard Worker if (drv->log_bos)
475*d95af8dfSAndroid Build Coastguard Worker drv_bo_log_info(bo, "imported");
476*d95af8dfSAndroid Build Coastguard Worker
477*d95af8dfSAndroid Build Coastguard Worker return bo;
478*d95af8dfSAndroid Build Coastguard Worker
479*d95af8dfSAndroid Build Coastguard Worker destroy_bo:
480*d95af8dfSAndroid Build Coastguard Worker drv_bo_destroy(bo);
481*d95af8dfSAndroid Build Coastguard Worker return NULL;
482*d95af8dfSAndroid Build Coastguard Worker }
483*d95af8dfSAndroid Build Coastguard Worker
drv_bo_map(struct bo * bo,const struct rectangle * rect,uint32_t map_flags,struct mapping ** map_data,size_t plane)484*d95af8dfSAndroid Build Coastguard Worker void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
485*d95af8dfSAndroid Build Coastguard Worker struct mapping **map_data, size_t plane)
486*d95af8dfSAndroid Build Coastguard Worker {
487*d95af8dfSAndroid Build Coastguard Worker struct driver *drv = bo->drv;
488*d95af8dfSAndroid Build Coastguard Worker uint32_t i;
489*d95af8dfSAndroid Build Coastguard Worker uint8_t *addr;
490*d95af8dfSAndroid Build Coastguard Worker struct mapping mapping = { 0 };
491*d95af8dfSAndroid Build Coastguard Worker
492*d95af8dfSAndroid Build Coastguard Worker assert(rect->width >= 0);
493*d95af8dfSAndroid Build Coastguard Worker assert(rect->height >= 0);
494*d95af8dfSAndroid Build Coastguard Worker assert(rect->x + rect->width <= drv_bo_get_width(bo));
495*d95af8dfSAndroid Build Coastguard Worker assert(rect->y + rect->height <= drv_bo_get_height(bo));
496*d95af8dfSAndroid Build Coastguard Worker assert(BO_MAP_READ_WRITE & map_flags);
497*d95af8dfSAndroid Build Coastguard Worker /* No CPU access for protected buffers. */
498*d95af8dfSAndroid Build Coastguard Worker assert(!(bo->meta.use_flags & BO_USE_PROTECTED));
499*d95af8dfSAndroid Build Coastguard Worker
500*d95af8dfSAndroid Build Coastguard Worker if (bo->is_test_buffer)
501*d95af8dfSAndroid Build Coastguard Worker return MAP_FAILED;
502*d95af8dfSAndroid Build Coastguard Worker
503*d95af8dfSAndroid Build Coastguard Worker mapping.rect = *rect;
504*d95af8dfSAndroid Build Coastguard Worker mapping.refcount = 1;
505*d95af8dfSAndroid Build Coastguard Worker
506*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_lock(&drv->mappings_lock);
507*d95af8dfSAndroid Build Coastguard Worker
508*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < drv_array_size(drv->mappings); i++) {
509*d95af8dfSAndroid Build Coastguard Worker struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
510*d95af8dfSAndroid Build Coastguard Worker if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
511*d95af8dfSAndroid Build Coastguard Worker continue;
512*d95af8dfSAndroid Build Coastguard Worker
513*d95af8dfSAndroid Build Coastguard Worker if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
514*d95af8dfSAndroid Build Coastguard Worker rect->width != prior->rect.width || rect->height != prior->rect.height)
515*d95af8dfSAndroid Build Coastguard Worker continue;
516*d95af8dfSAndroid Build Coastguard Worker
517*d95af8dfSAndroid Build Coastguard Worker prior->refcount++;
518*d95af8dfSAndroid Build Coastguard Worker *map_data = prior;
519*d95af8dfSAndroid Build Coastguard Worker goto exact_match;
520*d95af8dfSAndroid Build Coastguard Worker }
521*d95af8dfSAndroid Build Coastguard Worker
522*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < drv_array_size(drv->mappings); i++) {
523*d95af8dfSAndroid Build Coastguard Worker struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
524*d95af8dfSAndroid Build Coastguard Worker if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
525*d95af8dfSAndroid Build Coastguard Worker continue;
526*d95af8dfSAndroid Build Coastguard Worker
527*d95af8dfSAndroid Build Coastguard Worker prior->vma->refcount++;
528*d95af8dfSAndroid Build Coastguard Worker mapping.vma = prior->vma;
529*d95af8dfSAndroid Build Coastguard Worker goto success;
530*d95af8dfSAndroid Build Coastguard Worker }
531*d95af8dfSAndroid Build Coastguard Worker
532*d95af8dfSAndroid Build Coastguard Worker mapping.vma = calloc(1, sizeof(*mapping.vma));
533*d95af8dfSAndroid Build Coastguard Worker if (!mapping.vma) {
534*d95af8dfSAndroid Build Coastguard Worker *map_data = NULL;
535*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
536*d95af8dfSAndroid Build Coastguard Worker return MAP_FAILED;
537*d95af8dfSAndroid Build Coastguard Worker }
538*d95af8dfSAndroid Build Coastguard Worker
539*d95af8dfSAndroid Build Coastguard Worker memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides));
540*d95af8dfSAndroid Build Coastguard Worker addr = drv->backend->bo_map(bo, mapping.vma, map_flags);
541*d95af8dfSAndroid Build Coastguard Worker if (addr == MAP_FAILED) {
542*d95af8dfSAndroid Build Coastguard Worker *map_data = NULL;
543*d95af8dfSAndroid Build Coastguard Worker free(mapping.vma);
544*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
545*d95af8dfSAndroid Build Coastguard Worker return MAP_FAILED;
546*d95af8dfSAndroid Build Coastguard Worker }
547*d95af8dfSAndroid Build Coastguard Worker
548*d95af8dfSAndroid Build Coastguard Worker mapping.vma->refcount = 1;
549*d95af8dfSAndroid Build Coastguard Worker mapping.vma->addr = addr;
550*d95af8dfSAndroid Build Coastguard Worker mapping.vma->handle = bo->handle.u32;
551*d95af8dfSAndroid Build Coastguard Worker mapping.vma->map_flags = map_flags;
552*d95af8dfSAndroid Build Coastguard Worker
553*d95af8dfSAndroid Build Coastguard Worker success:
554*d95af8dfSAndroid Build Coastguard Worker *map_data = drv_array_append(drv->mappings, &mapping);
555*d95af8dfSAndroid Build Coastguard Worker exact_match:
556*d95af8dfSAndroid Build Coastguard Worker drv_bo_invalidate(bo, *map_data);
557*d95af8dfSAndroid Build Coastguard Worker addr = (uint8_t *)((*map_data)->vma->addr);
558*d95af8dfSAndroid Build Coastguard Worker addr += drv_bo_get_plane_offset(bo, plane);
559*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
560*d95af8dfSAndroid Build Coastguard Worker return (void *)addr;
561*d95af8dfSAndroid Build Coastguard Worker }
562*d95af8dfSAndroid Build Coastguard Worker
drv_bo_unmap(struct bo * bo,struct mapping * mapping)563*d95af8dfSAndroid Build Coastguard Worker int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
564*d95af8dfSAndroid Build Coastguard Worker {
565*d95af8dfSAndroid Build Coastguard Worker struct driver *drv = bo->drv;
566*d95af8dfSAndroid Build Coastguard Worker uint32_t i;
567*d95af8dfSAndroid Build Coastguard Worker int ret = 0;
568*d95af8dfSAndroid Build Coastguard Worker
569*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_lock(&drv->mappings_lock);
570*d95af8dfSAndroid Build Coastguard Worker
571*d95af8dfSAndroid Build Coastguard Worker if (--mapping->refcount)
572*d95af8dfSAndroid Build Coastguard Worker goto out;
573*d95af8dfSAndroid Build Coastguard Worker
574*d95af8dfSAndroid Build Coastguard Worker if (!--mapping->vma->refcount) {
575*d95af8dfSAndroid Build Coastguard Worker ret = drv->backend->bo_unmap(bo, mapping->vma);
576*d95af8dfSAndroid Build Coastguard Worker free(mapping->vma);
577*d95af8dfSAndroid Build Coastguard Worker }
578*d95af8dfSAndroid Build Coastguard Worker
579*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < drv_array_size(drv->mappings); i++) {
580*d95af8dfSAndroid Build Coastguard Worker if (mapping == (struct mapping *)drv_array_at_idx(drv->mappings, i)) {
581*d95af8dfSAndroid Build Coastguard Worker drv_array_remove(drv->mappings, i);
582*d95af8dfSAndroid Build Coastguard Worker break;
583*d95af8dfSAndroid Build Coastguard Worker }
584*d95af8dfSAndroid Build Coastguard Worker }
585*d95af8dfSAndroid Build Coastguard Worker
586*d95af8dfSAndroid Build Coastguard Worker out:
587*d95af8dfSAndroid Build Coastguard Worker pthread_mutex_unlock(&drv->mappings_lock);
588*d95af8dfSAndroid Build Coastguard Worker return ret;
589*d95af8dfSAndroid Build Coastguard Worker }
590*d95af8dfSAndroid Build Coastguard Worker
drv_bo_cached(struct bo * bo)591*d95af8dfSAndroid Build Coastguard Worker bool drv_bo_cached(struct bo *bo)
592*d95af8dfSAndroid Build Coastguard Worker {
593*d95af8dfSAndroid Build Coastguard Worker return bo->meta.cached;
594*d95af8dfSAndroid Build Coastguard Worker }
595*d95af8dfSAndroid Build Coastguard Worker
drv_bo_invalidate(struct bo * bo,struct mapping * mapping)596*d95af8dfSAndroid Build Coastguard Worker int drv_bo_invalidate(struct bo *bo, struct mapping *mapping)
597*d95af8dfSAndroid Build Coastguard Worker {
598*d95af8dfSAndroid Build Coastguard Worker int ret = 0;
599*d95af8dfSAndroid Build Coastguard Worker
600*d95af8dfSAndroid Build Coastguard Worker assert(mapping);
601*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma);
602*d95af8dfSAndroid Build Coastguard Worker assert(mapping->refcount > 0);
603*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma->refcount > 0);
604*d95af8dfSAndroid Build Coastguard Worker
605*d95af8dfSAndroid Build Coastguard Worker if (bo->drv->backend->bo_invalidate)
606*d95af8dfSAndroid Build Coastguard Worker ret = bo->drv->backend->bo_invalidate(bo, mapping);
607*d95af8dfSAndroid Build Coastguard Worker
608*d95af8dfSAndroid Build Coastguard Worker return ret;
609*d95af8dfSAndroid Build Coastguard Worker }
610*d95af8dfSAndroid Build Coastguard Worker
drv_bo_flush(struct bo * bo,struct mapping * mapping)611*d95af8dfSAndroid Build Coastguard Worker int drv_bo_flush(struct bo *bo, struct mapping *mapping)
612*d95af8dfSAndroid Build Coastguard Worker {
613*d95af8dfSAndroid Build Coastguard Worker int ret = 0;
614*d95af8dfSAndroid Build Coastguard Worker
615*d95af8dfSAndroid Build Coastguard Worker assert(mapping);
616*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma);
617*d95af8dfSAndroid Build Coastguard Worker assert(mapping->refcount > 0);
618*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma->refcount > 0);
619*d95af8dfSAndroid Build Coastguard Worker
620*d95af8dfSAndroid Build Coastguard Worker if (bo->drv->backend->bo_flush)
621*d95af8dfSAndroid Build Coastguard Worker ret = bo->drv->backend->bo_flush(bo, mapping);
622*d95af8dfSAndroid Build Coastguard Worker
623*d95af8dfSAndroid Build Coastguard Worker return ret;
624*d95af8dfSAndroid Build Coastguard Worker }
625*d95af8dfSAndroid Build Coastguard Worker
drv_bo_flush_or_unmap(struct bo * bo,struct mapping * mapping)626*d95af8dfSAndroid Build Coastguard Worker int drv_bo_flush_or_unmap(struct bo *bo, struct mapping *mapping)
627*d95af8dfSAndroid Build Coastguard Worker {
628*d95af8dfSAndroid Build Coastguard Worker int ret = 0;
629*d95af8dfSAndroid Build Coastguard Worker
630*d95af8dfSAndroid Build Coastguard Worker assert(mapping);
631*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma);
632*d95af8dfSAndroid Build Coastguard Worker assert(mapping->refcount > 0);
633*d95af8dfSAndroid Build Coastguard Worker assert(mapping->vma->refcount > 0);
634*d95af8dfSAndroid Build Coastguard Worker assert(!(bo->meta.use_flags & BO_USE_PROTECTED));
635*d95af8dfSAndroid Build Coastguard Worker
636*d95af8dfSAndroid Build Coastguard Worker if (bo->drv->backend->bo_flush)
637*d95af8dfSAndroid Build Coastguard Worker ret = bo->drv->backend->bo_flush(bo, mapping);
638*d95af8dfSAndroid Build Coastguard Worker else
639*d95af8dfSAndroid Build Coastguard Worker ret = drv_bo_unmap(bo, mapping);
640*d95af8dfSAndroid Build Coastguard Worker
641*d95af8dfSAndroid Build Coastguard Worker return ret;
642*d95af8dfSAndroid Build Coastguard Worker }
643*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_width(struct bo * bo)644*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_width(struct bo *bo)
645*d95af8dfSAndroid Build Coastguard Worker {
646*d95af8dfSAndroid Build Coastguard Worker return bo->meta.width;
647*d95af8dfSAndroid Build Coastguard Worker }
648*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_height(struct bo * bo)649*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_height(struct bo *bo)
650*d95af8dfSAndroid Build Coastguard Worker {
651*d95af8dfSAndroid Build Coastguard Worker return bo->meta.height;
652*d95af8dfSAndroid Build Coastguard Worker }
653*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_num_planes(struct bo * bo)654*d95af8dfSAndroid Build Coastguard Worker size_t drv_bo_get_num_planes(struct bo *bo)
655*d95af8dfSAndroid Build Coastguard Worker {
656*d95af8dfSAndroid Build Coastguard Worker return bo->meta.num_planes;
657*d95af8dfSAndroid Build Coastguard Worker }
658*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_plane_handle(struct bo * bo,size_t plane)659*d95af8dfSAndroid Build Coastguard Worker union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
660*d95af8dfSAndroid Build Coastguard Worker {
661*d95af8dfSAndroid Build Coastguard Worker return bo->handle;
662*d95af8dfSAndroid Build Coastguard Worker }
663*d95af8dfSAndroid Build Coastguard Worker
664*d95af8dfSAndroid Build Coastguard Worker #ifndef DRM_RDWR
665*d95af8dfSAndroid Build Coastguard Worker #define DRM_RDWR O_RDWR
666*d95af8dfSAndroid Build Coastguard Worker #endif
667*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_plane_fd(struct bo * bo,size_t plane)668*d95af8dfSAndroid Build Coastguard Worker int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
669*d95af8dfSAndroid Build Coastguard Worker {
670*d95af8dfSAndroid Build Coastguard Worker
671*d95af8dfSAndroid Build Coastguard Worker int ret, fd;
672*d95af8dfSAndroid Build Coastguard Worker assert(plane < bo->meta.num_planes);
673*d95af8dfSAndroid Build Coastguard Worker
674*d95af8dfSAndroid Build Coastguard Worker if (bo->is_test_buffer)
675*d95af8dfSAndroid Build Coastguard Worker return -EINVAL;
676*d95af8dfSAndroid Build Coastguard Worker
677*d95af8dfSAndroid Build Coastguard Worker ret = drmPrimeHandleToFD(bo->drv->fd, bo->handle.u32, DRM_CLOEXEC | DRM_RDWR, &fd);
678*d95af8dfSAndroid Build Coastguard Worker
679*d95af8dfSAndroid Build Coastguard Worker // Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping anyways
680*d95af8dfSAndroid Build Coastguard Worker if (ret)
681*d95af8dfSAndroid Build Coastguard Worker ret = drmPrimeHandleToFD(bo->drv->fd, bo->handle.u32, DRM_CLOEXEC, &fd);
682*d95af8dfSAndroid Build Coastguard Worker
683*d95af8dfSAndroid Build Coastguard Worker if (ret)
684*d95af8dfSAndroid Build Coastguard Worker drv_loge("Failed to get plane fd: %s\n", strerror(errno));
685*d95af8dfSAndroid Build Coastguard Worker
686*d95af8dfSAndroid Build Coastguard Worker return (ret) ? ret : fd;
687*d95af8dfSAndroid Build Coastguard Worker }
688*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_plane_offset(struct bo * bo,size_t plane)689*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
690*d95af8dfSAndroid Build Coastguard Worker {
691*d95af8dfSAndroid Build Coastguard Worker assert(plane < bo->meta.num_planes);
692*d95af8dfSAndroid Build Coastguard Worker return bo->meta.offsets[plane];
693*d95af8dfSAndroid Build Coastguard Worker }
694*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_plane_size(struct bo * bo,size_t plane)695*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane)
696*d95af8dfSAndroid Build Coastguard Worker {
697*d95af8dfSAndroid Build Coastguard Worker assert(plane < bo->meta.num_planes);
698*d95af8dfSAndroid Build Coastguard Worker return bo->meta.sizes[plane];
699*d95af8dfSAndroid Build Coastguard Worker }
700*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_plane_stride(struct bo * bo,size_t plane)701*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane)
702*d95af8dfSAndroid Build Coastguard Worker {
703*d95af8dfSAndroid Build Coastguard Worker assert(plane < bo->meta.num_planes);
704*d95af8dfSAndroid Build Coastguard Worker return bo->meta.strides[plane];
705*d95af8dfSAndroid Build Coastguard Worker }
706*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_format_modifier(struct bo * bo)707*d95af8dfSAndroid Build Coastguard Worker uint64_t drv_bo_get_format_modifier(struct bo *bo)
708*d95af8dfSAndroid Build Coastguard Worker {
709*d95af8dfSAndroid Build Coastguard Worker return bo->meta.format_modifier;
710*d95af8dfSAndroid Build Coastguard Worker }
711*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_format(struct bo * bo)712*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_format(struct bo *bo)
713*d95af8dfSAndroid Build Coastguard Worker {
714*d95af8dfSAndroid Build Coastguard Worker return bo->meta.format;
715*d95af8dfSAndroid Build Coastguard Worker }
716*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_tiling(struct bo * bo)717*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_bo_get_tiling(struct bo *bo)
718*d95af8dfSAndroid Build Coastguard Worker {
719*d95af8dfSAndroid Build Coastguard Worker return bo->meta.tiling;
720*d95af8dfSAndroid Build Coastguard Worker }
721*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_use_flags(struct bo * bo)722*d95af8dfSAndroid Build Coastguard Worker uint64_t drv_bo_get_use_flags(struct bo *bo)
723*d95af8dfSAndroid Build Coastguard Worker {
724*d95af8dfSAndroid Build Coastguard Worker return bo->meta.use_flags;
725*d95af8dfSAndroid Build Coastguard Worker }
726*d95af8dfSAndroid Build Coastguard Worker
drv_bo_get_total_size(struct bo * bo)727*d95af8dfSAndroid Build Coastguard Worker size_t drv_bo_get_total_size(struct bo *bo)
728*d95af8dfSAndroid Build Coastguard Worker {
729*d95af8dfSAndroid Build Coastguard Worker return bo->meta.total_size;
730*d95af8dfSAndroid Build Coastguard Worker }
731*d95af8dfSAndroid Build Coastguard Worker
drv_bo_log_info(const struct bo * bo,const char * prefix)732*d95af8dfSAndroid Build Coastguard Worker void drv_bo_log_info(const struct bo *bo, const char *prefix)
733*d95af8dfSAndroid Build Coastguard Worker {
734*d95af8dfSAndroid Build Coastguard Worker const struct bo_metadata *meta = &bo->meta;
735*d95af8dfSAndroid Build Coastguard Worker
736*d95af8dfSAndroid Build Coastguard Worker drv_logd("%s %s bo %p: %dx%d '%c%c%c%c' tiling %d plane %zu mod 0x%" PRIx64
737*d95af8dfSAndroid Build Coastguard Worker " use 0x%" PRIx64 " size %zu\n",
738*d95af8dfSAndroid Build Coastguard Worker prefix, bo->drv->backend->name, bo, meta->width, meta->height, meta->format & 0xff,
739*d95af8dfSAndroid Build Coastguard Worker (meta->format >> 8) & 0xff, (meta->format >> 16) & 0xff,
740*d95af8dfSAndroid Build Coastguard Worker (meta->format >> 24) & 0xff, meta->tiling, meta->num_planes, meta->format_modifier,
741*d95af8dfSAndroid Build Coastguard Worker meta->use_flags, meta->total_size);
742*d95af8dfSAndroid Build Coastguard Worker for (uint32_t i = 0; i < meta->num_planes; i++) {
743*d95af8dfSAndroid Build Coastguard Worker drv_logd(" bo %p plane %d: offset %d size %d stride %d\n", bo, i, meta->offsets[i],
744*d95af8dfSAndroid Build Coastguard Worker meta->sizes[i], meta->strides[i]);
745*d95af8dfSAndroid Build Coastguard Worker }
746*d95af8dfSAndroid Build Coastguard Worker }
747*d95af8dfSAndroid Build Coastguard Worker
748*d95af8dfSAndroid Build Coastguard Worker /*
749*d95af8dfSAndroid Build Coastguard Worker * Map internal fourcc codes back to standard fourcc codes.
750*d95af8dfSAndroid Build Coastguard Worker */
drv_get_standard_fourcc(uint32_t fourcc_internal)751*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal)
752*d95af8dfSAndroid Build Coastguard Worker {
753*d95af8dfSAndroid Build Coastguard Worker return (fourcc_internal == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : fourcc_internal;
754*d95af8dfSAndroid Build Coastguard Worker }
755*d95af8dfSAndroid Build Coastguard Worker
drv_resolve_format_and_use_flags(struct driver * drv,uint32_t format,uint64_t use_flags,uint32_t * out_format,uint64_t * out_use_flags)756*d95af8dfSAndroid Build Coastguard Worker void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags,
757*d95af8dfSAndroid Build Coastguard Worker uint32_t *out_format, uint64_t *out_use_flags)
758*d95af8dfSAndroid Build Coastguard Worker {
759*d95af8dfSAndroid Build Coastguard Worker assert(drv->backend->resolve_format_and_use_flags);
760*d95af8dfSAndroid Build Coastguard Worker
761*d95af8dfSAndroid Build Coastguard Worker drv->backend->resolve_format_and_use_flags(drv, format, use_flags, out_format,
762*d95af8dfSAndroid Build Coastguard Worker out_use_flags);
763*d95af8dfSAndroid Build Coastguard Worker }
764*d95af8dfSAndroid Build Coastguard Worker
drv_log_prefix(enum drv_log_level level,const char * prefix,const char * func,int line,const char * format,...)765*d95af8dfSAndroid Build Coastguard Worker void drv_log_prefix(enum drv_log_level level, const char *prefix, const char *func, int line,
766*d95af8dfSAndroid Build Coastguard Worker const char *format, ...)
767*d95af8dfSAndroid Build Coastguard Worker {
768*d95af8dfSAndroid Build Coastguard Worker char buf[50];
769*d95af8dfSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, func, line);
770*d95af8dfSAndroid Build Coastguard Worker
771*d95af8dfSAndroid Build Coastguard Worker va_list args;
772*d95af8dfSAndroid Build Coastguard Worker va_start(args, format);
773*d95af8dfSAndroid Build Coastguard Worker #ifdef __ANDROID__
774*d95af8dfSAndroid Build Coastguard Worker int prio = ANDROID_LOG_ERROR;
775*d95af8dfSAndroid Build Coastguard Worker switch (level) {
776*d95af8dfSAndroid Build Coastguard Worker case DRV_LOGV:
777*d95af8dfSAndroid Build Coastguard Worker prio = ANDROID_LOG_VERBOSE;
778*d95af8dfSAndroid Build Coastguard Worker break;
779*d95af8dfSAndroid Build Coastguard Worker case DRV_LOGD:
780*d95af8dfSAndroid Build Coastguard Worker prio = ANDROID_LOG_DEBUG;
781*d95af8dfSAndroid Build Coastguard Worker break;
782*d95af8dfSAndroid Build Coastguard Worker case DRV_LOGI:
783*d95af8dfSAndroid Build Coastguard Worker prio = ANDROID_LOG_INFO;
784*d95af8dfSAndroid Build Coastguard Worker break;
785*d95af8dfSAndroid Build Coastguard Worker case DRV_LOGE:
786*d95af8dfSAndroid Build Coastguard Worker default:
787*d95af8dfSAndroid Build Coastguard Worker break;
788*d95af8dfSAndroid Build Coastguard Worker };
789*d95af8dfSAndroid Build Coastguard Worker __android_log_vprint(prio, buf, format, args);
790*d95af8dfSAndroid Build Coastguard Worker #else
791*d95af8dfSAndroid Build Coastguard Worker fprintf(stderr, "%s ", buf);
792*d95af8dfSAndroid Build Coastguard Worker vfprintf(stderr, format, args);
793*d95af8dfSAndroid Build Coastguard Worker #endif
794*d95af8dfSAndroid Build Coastguard Worker va_end(args);
795*d95af8dfSAndroid Build Coastguard Worker }
796*d95af8dfSAndroid Build Coastguard Worker
drv_resource_info(struct bo * bo,uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)797*d95af8dfSAndroid Build Coastguard Worker int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
798*d95af8dfSAndroid Build Coastguard Worker uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier)
799*d95af8dfSAndroid Build Coastguard Worker {
800*d95af8dfSAndroid Build Coastguard Worker for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
801*d95af8dfSAndroid Build Coastguard Worker strides[plane] = bo->meta.strides[plane];
802*d95af8dfSAndroid Build Coastguard Worker offsets[plane] = bo->meta.offsets[plane];
803*d95af8dfSAndroid Build Coastguard Worker }
804*d95af8dfSAndroid Build Coastguard Worker *format_modifier = bo->meta.format_modifier;
805*d95af8dfSAndroid Build Coastguard Worker
806*d95af8dfSAndroid Build Coastguard Worker if (bo->drv->backend->resource_info)
807*d95af8dfSAndroid Build Coastguard Worker return bo->drv->backend->resource_info(bo, strides, offsets, format_modifier);
808*d95af8dfSAndroid Build Coastguard Worker
809*d95af8dfSAndroid Build Coastguard Worker return 0;
810*d95af8dfSAndroid Build Coastguard Worker }
811*d95af8dfSAndroid Build Coastguard Worker
drv_get_max_texture_2d_size(struct driver * drv)812*d95af8dfSAndroid Build Coastguard Worker uint32_t drv_get_max_texture_2d_size(struct driver *drv)
813*d95af8dfSAndroid Build Coastguard Worker {
814*d95af8dfSAndroid Build Coastguard Worker if (drv->backend->get_max_texture_2d_size)
815*d95af8dfSAndroid Build Coastguard Worker return drv->backend->get_max_texture_2d_size(drv);
816*d95af8dfSAndroid Build Coastguard Worker
817*d95af8dfSAndroid Build Coastguard Worker return UINT32_MAX;
818*d95af8dfSAndroid Build Coastguard Worker }
819