OSDN Git Service

minigbm: cros_gralloc: support GRALLOC_MODULE_API_VERSION_0_3
[android-x86/external-minigbm.git] / drv.c
1 /*
2  * Copyright 2016 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 #include <assert.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <pthread.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/mman.h>
15 #include <xf86drm.h>
16
17 #include "drv_priv.h"
18 #include "helpers.h"
19 #include "util.h"
20
21 #ifdef DRV_AMDGPU
22 extern struct backend backend_amdgpu;
23 #endif
24 extern struct backend backend_cirrus;
25 extern struct backend backend_evdi;
26 #ifdef DRV_EXYNOS
27 extern struct backend backend_exynos;
28 #endif
29 extern struct backend backend_gma500;
30 #ifdef DRV_I915
31 extern struct backend backend_i915;
32 #endif
33 #ifdef DRV_MARVELL
34 extern struct backend backend_marvell;
35 #endif
36 #ifdef DRV_MEDIATEK
37 extern struct backend backend_mediatek;
38 #endif
39 extern struct backend backend_nouveau;
40 #ifdef DRV_ROCKCHIP
41 extern struct backend backend_rockchip;
42 #endif
43 #ifdef DRV_TEGRA
44 extern struct backend backend_tegra;
45 #endif
46 extern struct backend backend_udl;
47 #ifdef DRV_VC4
48 extern struct backend backend_vc4;
49 #endif
50 extern struct backend backend_vgem;
51 extern struct backend backend_virtio_gpu;
52
53 static struct backend *drv_get_backend(int fd)
54 {
55         drmVersionPtr drm_version;
56         unsigned int i;
57
58         drm_version = drmGetVersion(fd);
59
60         if (!drm_version)
61                 return NULL;
62
63         struct backend *backend_list[] = {
64 #ifdef DRV_AMDGPU
65                 &backend_amdgpu,
66 #endif
67                 &backend_cirrus,   &backend_evdi,
68 #ifdef DRV_EXYNOS
69                 &backend_exynos,
70 #endif
71                 &backend_gma500,
72 #ifdef DRV_I915
73                 &backend_i915,
74 #endif
75 #ifdef DRV_MARVELL
76                 &backend_marvell,
77 #endif
78 #ifdef DRV_MEDIATEK
79                 &backend_mediatek,
80 #endif
81                 &backend_nouveau,
82 #ifdef DRV_ROCKCHIP
83                 &backend_rockchip,
84 #endif
85 #ifdef DRV_TEGRA
86                 &backend_tegra,
87 #endif
88                 &backend_udl,
89 #ifdef DRV_VC4
90                 &backend_vc4,
91 #endif
92                 &backend_vgem,     &backend_virtio_gpu,
93         };
94
95         for (i = 0; i < ARRAY_SIZE(backend_list); i++)
96                 if (!strcmp(drm_version->name, backend_list[i]->name)) {
97                         drmFreeVersion(drm_version);
98                         return backend_list[i];
99                 }
100
101         drmFreeVersion(drm_version);
102         return NULL;
103 }
104
105 struct driver *drv_create(int fd)
106 {
107         struct driver *drv;
108         int ret;
109
110         drv = (struct driver *)calloc(1, sizeof(*drv));
111
112         if (!drv)
113                 return NULL;
114
115         drv->fd = fd;
116         drv->backend = drv_get_backend(fd);
117
118         if (!drv->backend)
119                 goto free_driver;
120
121         if (pthread_mutex_init(&drv->driver_lock, NULL))
122                 goto free_driver;
123
124         drv->buffer_table = drmHashCreate();
125         if (!drv->buffer_table)
126                 goto free_lock;
127
128         drv->map_table = drmHashCreate();
129         if (!drv->map_table)
130                 goto free_buffer_table;
131
132         /* Start with a power of 2 number of allocations. */
133         drv->backend->combos.allocations = 2;
134         drv->backend->combos.size = 0;
135         drv->backend->combos.data =
136             calloc(drv->backend->combos.allocations, sizeof(struct combination));
137         if (!drv->backend->combos.data)
138                 goto free_map_table;
139
140         if (drv->backend->init) {
141                 ret = drv->backend->init(drv);
142                 if (ret) {
143                         free(drv->backend->combos.data);
144                         goto free_map_table;
145                 }
146         }
147
148         return drv;
149
150 free_map_table:
151         drmHashDestroy(drv->map_table);
152 free_buffer_table:
153         drmHashDestroy(drv->buffer_table);
154 free_lock:
155         pthread_mutex_destroy(&drv->driver_lock);
156 free_driver:
157         free(drv);
158         return NULL;
159 }
160
161 void drv_destroy(struct driver *drv)
162 {
163         pthread_mutex_lock(&drv->driver_lock);
164
165         if (drv->backend->close)
166                 drv->backend->close(drv);
167
168         drmHashDestroy(drv->buffer_table);
169         drmHashDestroy(drv->map_table);
170
171         free(drv->backend->combos.data);
172
173         pthread_mutex_unlock(&drv->driver_lock);
174         pthread_mutex_destroy(&drv->driver_lock);
175
176         free(drv);
177 }
178
179 int drv_get_fd(struct driver *drv)
180 {
181         return drv->fd;
182 }
183
184 const char *drv_get_name(struct driver *drv)
185 {
186         return drv->backend->name;
187 }
188
189 struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t usage)
190 {
191         struct combination *curr, *best;
192
193         if (format == DRM_FORMAT_NONE || usage == BO_USE_NONE)
194                 return 0;
195
196         best = NULL;
197         uint32_t i;
198         for (i = 0; i < drv->backend->combos.size; i++) {
199                 curr = &drv->backend->combos.data[i];
200                 if ((format == curr->format) && usage == (curr->usage & usage))
201                         if (!best || best->metadata.priority < curr->metadata.priority)
202                                 best = curr;
203         }
204
205         return best;
206 }
207
208 struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format)
209 {
210
211         struct bo *bo;
212         bo = (struct bo *)calloc(1, sizeof(*bo));
213
214         if (!bo)
215                 return NULL;
216
217         bo->drv = drv;
218         bo->width = width;
219         bo->height = height;
220         bo->format = format;
221         bo->num_planes = drv_num_planes_from_format(format);
222
223         if (!bo->num_planes) {
224                 free(bo);
225                 return NULL;
226         }
227
228         return bo;
229 }
230
231 struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
232                          uint64_t flags)
233 {
234         int ret;
235         size_t plane;
236         struct bo *bo;
237
238         bo = drv_bo_new(drv, width, height, format);
239
240         if (!bo)
241                 return NULL;
242
243         ret = drv->backend->bo_create(bo, width, height, format, flags);
244
245         if (ret) {
246                 free(bo);
247                 return NULL;
248         }
249
250         pthread_mutex_lock(&drv->driver_lock);
251
252         for (plane = 0; plane < bo->num_planes; plane++)
253                 drv_increment_reference_count(drv, bo, plane);
254
255         pthread_mutex_unlock(&drv->driver_lock);
256
257         return bo;
258 }
259
260 struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
261                                         uint32_t format, const uint64_t *modifiers, uint32_t count)
262 {
263         int ret;
264         size_t plane;
265         struct bo *bo;
266
267         if (!drv->backend->bo_create_with_modifiers) {
268                 errno = ENOENT;
269                 return NULL;
270         }
271
272         bo = drv_bo_new(drv, width, height, format);
273
274         if (!bo)
275                 return NULL;
276
277         ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count);
278
279         if (ret) {
280                 free(bo);
281                 return NULL;
282         }
283
284         pthread_mutex_lock(&drv->driver_lock);
285
286         for (plane = 0; plane < bo->num_planes; plane++)
287                 drv_increment_reference_count(drv, bo, plane);
288
289         pthread_mutex_unlock(&drv->driver_lock);
290
291         return bo;
292 }
293
294 void drv_bo_destroy(struct bo *bo)
295 {
296         size_t plane;
297         uintptr_t total = 0;
298         struct driver *drv = bo->drv;
299
300         pthread_mutex_lock(&drv->driver_lock);
301
302         for (plane = 0; plane < bo->num_planes; plane++)
303                 drv_decrement_reference_count(drv, bo, plane);
304
305         for (plane = 0; plane < bo->num_planes; plane++)
306                 total += drv_get_reference_count(drv, bo, plane);
307
308         pthread_mutex_unlock(&drv->driver_lock);
309
310         if (total == 0)
311                 bo->drv->backend->bo_destroy(bo);
312
313         free(bo);
314 }
315
316 struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
317 {
318         int ret;
319         size_t plane;
320         struct bo *bo;
321
322         bo = drv_bo_new(drv, data->width, data->height, data->format);
323
324         if (!bo)
325                 return NULL;
326
327         ret = drv->backend->bo_import(bo, data);
328         if (ret) {
329                 free(bo);
330                 return NULL;
331         }
332
333         for (plane = 0; plane < bo->num_planes; plane++) {
334                 bo->strides[plane] = data->strides[plane];
335                 bo->offsets[plane] = data->offsets[plane];
336                 bo->sizes[plane] = data->sizes[plane];
337                 bo->format_modifiers[plane] = data->format_modifiers[plane];
338                 bo->total_size += data->sizes[plane];
339         }
340
341         return bo;
342 }
343
344 void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
345                  uint32_t flags, struct map_info **map_data, size_t plane)
346 {
347         void *ptr;
348         uint8_t *addr;
349         size_t offset;
350         struct map_info *data;
351         int prot;
352
353         assert(width > 0);
354         assert(height > 0);
355         assert(x + width <= drv_bo_get_width(bo));
356         assert(y + height <= drv_bo_get_height(bo));
357         assert(BO_TRANSFER_READ_WRITE & flags);
358
359         pthread_mutex_lock(&bo->drv->driver_lock);
360
361         if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) {
362                 data = (struct map_info *)ptr;
363                 data->refcount++;
364                 goto success;
365         }
366
367         data = calloc(1, sizeof(*data));
368         prot = BO_TRANSFER_WRITE & flags ? PROT_WRITE | PROT_READ : PROT_READ;
369         addr = bo->drv->backend->bo_map(bo, data, plane, prot);
370         if (addr == MAP_FAILED) {
371                 *map_data = NULL;
372                 free(data);
373                 pthread_mutex_unlock(&bo->drv->driver_lock);
374                 return MAP_FAILED;
375         }
376
377         data->refcount = 1;
378         data->addr = addr;
379         data->handle = bo->handles[plane].u32;
380         drmHashInsert(bo->drv->map_table, bo->handles[plane].u32, (void *)data);
381
382 success:
383         *map_data = data;
384         offset = drv_bo_get_plane_stride(bo, plane) * y;
385         offset += drv_stride_from_format(bo->format, x, plane);
386         addr = (uint8_t *)data->addr;
387         addr += drv_bo_get_plane_offset(bo, plane) + offset;
388         pthread_mutex_unlock(&bo->drv->driver_lock);
389
390         return (void *)addr;
391 }
392
393 int drv_bo_unmap(struct bo *bo, struct map_info *data)
394 {
395         int ret = 0;
396
397         assert(data);
398         assert(data->refcount >= 0);
399
400         pthread_mutex_lock(&bo->drv->driver_lock);
401
402         if (!--data->refcount) {
403                 if (bo->drv->backend->bo_unmap)
404                         ret = bo->drv->backend->bo_unmap(bo, data);
405                 else
406                         ret = munmap(data->addr, data->length);
407                 drmHashDelete(bo->drv->map_table, data->handle);
408                 free(data);
409         }
410
411         pthread_mutex_unlock(&bo->drv->driver_lock);
412
413         return ret;
414 }
415
416 uint32_t drv_bo_get_width(struct bo *bo)
417 {
418         return bo->width;
419 }
420
421 uint32_t drv_bo_get_height(struct bo *bo)
422 {
423         return bo->height;
424 }
425
426 uint32_t drv_bo_get_stride_or_tiling(struct bo *bo)
427 {
428         return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0);
429 }
430
431 size_t drv_bo_get_num_planes(struct bo *bo)
432 {
433         return bo->num_planes;
434 }
435
436 union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
437 {
438         return bo->handles[plane];
439 }
440
441 #ifndef DRM_RDWR
442 #define DRM_RDWR O_RDWR
443 #endif
444
445 int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
446 {
447
448         int ret, fd;
449         assert(plane < bo->num_planes);
450
451         ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
452
453         return (ret) ? ret : fd;
454 }
455
456 uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
457 {
458         assert(plane < bo->num_planes);
459         return bo->offsets[plane];
460 }
461
462 uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane)
463 {
464         assert(plane < bo->num_planes);
465         return bo->sizes[plane];
466 }
467
468 uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane)
469 {
470         assert(plane < bo->num_planes);
471         return bo->strides[plane];
472 }
473
474 uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
475 {
476         assert(plane < bo->num_planes);
477         return bo->format_modifiers[plane];
478 }
479
480 uint32_t drv_bo_get_format(struct bo *bo)
481 {
482         return bo->format;
483 }
484
485 uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage)
486 {
487         if (drv->backend->resolve_format)
488                 return drv->backend->resolve_format(format, usage);
489
490         return format;
491 }
492
493 size_t drv_num_planes_from_format(uint32_t format)
494 {
495         switch (format) {
496         case DRM_FORMAT_ABGR1555:
497         case DRM_FORMAT_ABGR2101010:
498         case DRM_FORMAT_ABGR4444:
499         case DRM_FORMAT_ABGR8888:
500         case DRM_FORMAT_ARGB1555:
501         case DRM_FORMAT_ARGB2101010:
502         case DRM_FORMAT_ARGB4444:
503         case DRM_FORMAT_ARGB8888:
504         case DRM_FORMAT_AYUV:
505         case DRM_FORMAT_BGR233:
506         case DRM_FORMAT_BGR565:
507         case DRM_FORMAT_BGR888:
508         case DRM_FORMAT_BGRA1010102:
509         case DRM_FORMAT_BGRA4444:
510         case DRM_FORMAT_BGRA5551:
511         case DRM_FORMAT_BGRA8888:
512         case DRM_FORMAT_BGRX1010102:
513         case DRM_FORMAT_BGRX4444:
514         case DRM_FORMAT_BGRX5551:
515         case DRM_FORMAT_BGRX8888:
516         case DRM_FORMAT_C8:
517         case DRM_FORMAT_GR88:
518         case DRM_FORMAT_R8:
519         case DRM_FORMAT_RG88:
520         case DRM_FORMAT_RGB332:
521         case DRM_FORMAT_RGB565:
522         case DRM_FORMAT_RGB888:
523         case DRM_FORMAT_RGBA1010102:
524         case DRM_FORMAT_RGBA4444:
525         case DRM_FORMAT_RGBA5551:
526         case DRM_FORMAT_RGBA8888:
527         case DRM_FORMAT_RGBX1010102:
528         case DRM_FORMAT_RGBX4444:
529         case DRM_FORMAT_RGBX5551:
530         case DRM_FORMAT_RGBX8888:
531         case DRM_FORMAT_UYVY:
532         case DRM_FORMAT_VYUY:
533         case DRM_FORMAT_XBGR1555:
534         case DRM_FORMAT_XBGR2101010:
535         case DRM_FORMAT_XBGR4444:
536         case DRM_FORMAT_XBGR8888:
537         case DRM_FORMAT_XRGB1555:
538         case DRM_FORMAT_XRGB2101010:
539         case DRM_FORMAT_XRGB4444:
540         case DRM_FORMAT_XRGB8888:
541         case DRM_FORMAT_YUYV:
542         case DRM_FORMAT_YVYU:
543                 return 1;
544         case DRM_FORMAT_NV12:
545         case DRM_FORMAT_NV21:
546                 return 2;
547         case DRM_FORMAT_YVU420:
548         case DRM_FORMAT_YVU420_ANDROID:
549                 return 3;
550         }
551
552         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
553         return 0;
554 }
555
556 uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane)
557 {
558         assert(plane < drv_num_planes_from_format(format));
559         uint32_t vertical_subsampling;
560
561         switch (format) {
562         case DRM_FORMAT_NV12:
563         case DRM_FORMAT_YVU420:
564         case DRM_FORMAT_YVU420_ANDROID:
565                 vertical_subsampling = (plane == 0) ? 1 : 2;
566                 break;
567         default:
568                 vertical_subsampling = 1;
569         }
570
571         return stride * DIV_ROUND_UP(height, vertical_subsampling);
572 }
573
574 uint32_t drv_num_buffers_per_bo(struct bo *bo)
575 {
576         uint32_t count = 0;
577         size_t plane, p;
578
579         for (plane = 0; plane < bo->num_planes; plane++) {
580                 for (p = 0; p < plane; p++)
581                         if (bo->handles[p].u32 == bo->handles[plane].u32)
582                                 break;
583                 if (p == plane)
584                         count++;
585         }
586
587         return count;
588 }