OSDN Git Service

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