OSDN Git Service

rockchip: Add support for AFBC buffers
[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         struct drm_prime_handle prime_handle;
319
320         bo = drv_bo_new(drv, data->width, data->height, data->format);
321
322         if (!bo)
323                 return NULL;
324
325         for (plane = 0; plane < bo->num_planes; plane++) {
326
327                 memset(&prime_handle, 0, sizeof(prime_handle));
328                 prime_handle.fd = data->fds[plane];
329
330                 ret = drmIoctl(drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE,
331                                &prime_handle);
332
333                 if (ret) {
334                         fprintf(stderr, "drv: DRM_IOCTL_PRIME_FD_TO_HANDLE failed "
335                                 "(fd=%u)\n", prime_handle.fd);
336
337                         if (plane > 0) {
338                                 bo->num_planes = plane;
339                                 drv_bo_destroy(bo);
340                         } else {
341                                 free(bo);
342                         }
343
344                         return NULL;
345                 }
346
347                 bo->handles[plane].u32 = prime_handle.handle;
348                 bo->strides[plane] = data->strides[plane];
349                 bo->offsets[plane] = data->offsets[plane];
350                 bo->sizes[plane] = data->sizes[plane];
351                 bo->format_modifiers[plane] = data->format_modifiers[plane];
352                 bo->total_size += data->sizes[plane];
353
354                 pthread_mutex_lock(&drv->driver_lock);
355                 drv_increment_reference_count(drv, bo, plane);
356                 pthread_mutex_unlock(&drv->driver_lock);
357         }
358
359         return bo;
360 }
361
362 void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width,
363                  uint32_t height, uint32_t flags, void **map_data, size_t plane)
364 {
365         void *ptr;
366         uint8_t *addr;
367         size_t offset;
368         struct map_info *data;
369
370         assert(width > 0);
371         assert(height > 0);
372         assert(x + width <= drv_bo_get_width(bo));
373         assert(y + height <= drv_bo_get_height(bo));
374
375         pthread_mutex_lock(&bo->drv->driver_lock);
376
377         if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) {
378                 data = (struct map_info *) ptr;
379                 data->refcount++;
380                 goto success;
381         }
382
383         data = calloc(1, sizeof(*data));
384         addr = bo->drv->backend->bo_map(bo, data, plane);
385         if (addr == MAP_FAILED) {
386                 *map_data = NULL;
387                 free(data);
388                 pthread_mutex_unlock(&bo->drv->driver_lock);
389                 return MAP_FAILED;
390         }
391
392         data->refcount = 1;
393         data->addr = addr;
394         data->handle = bo->handles[plane].u32;
395         drmHashInsert(bo->drv->buffer_table, bo->handles[plane].u32,
396                       (void *) data);
397
398 success:
399         *map_data = (void *) data;
400         offset = drv_bo_get_plane_stride(bo, plane) * y;
401         offset += drv_stride_from_format(bo->format, x, plane);
402         addr = (uint8_t *) data->addr;
403         addr += drv_bo_get_plane_offset(bo, plane) + offset;
404         pthread_mutex_unlock(&bo->drv->driver_lock);
405
406         return (void *) addr;
407 }
408
409 int drv_bo_unmap(struct bo *bo, void *map_data)
410 {
411         struct map_info *data = map_data;
412         int ret = 0;
413
414         assert(data);
415         assert(data->refcount >= 0);
416
417         pthread_mutex_lock(&bo->drv->driver_lock);
418
419         if (!--data->refcount) {
420                 if (bo->drv->backend->bo_unmap)
421                         ret = bo->drv->backend->bo_unmap(bo, data);
422                 else
423                         ret = munmap(data->addr, data->length);
424                 drmHashDelete(bo->drv->map_table, data->handle);
425                 free(data);
426         }
427
428         pthread_mutex_unlock(&bo->drv->driver_lock);
429
430         return ret;
431 }
432
433 uint32_t drv_bo_get_width(struct bo *bo)
434 {
435         return bo->width;
436 }
437
438 uint32_t drv_bo_get_height(struct bo *bo)
439 {
440         return bo->height;
441 }
442
443 uint32_t drv_bo_get_stride_or_tiling(struct bo *bo)
444 {
445         return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0);
446 }
447
448 size_t drv_bo_get_num_planes(struct bo *bo)
449 {
450         return bo->num_planes;
451 }
452
453 union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
454 {
455         return bo->handles[plane];
456 }
457
458 #ifndef DRM_RDWR
459 #define DRM_RDWR O_RDWR
460 #endif
461
462 int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
463 {
464
465         int ret, fd;
466         assert(plane < bo->num_planes);
467
468         ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32,
469                                  DRM_CLOEXEC | DRM_RDWR, &fd);
470
471         return (ret) ? ret : fd;
472
473 }
474
475 uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
476 {
477         assert(plane < bo->num_planes);
478         return bo->offsets[plane];
479 }
480
481 uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane)
482 {
483         assert(plane < bo->num_planes);
484         return bo->sizes[plane];
485 }
486
487 uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane)
488 {
489         assert(plane < bo->num_planes);
490         return bo->strides[plane];
491 }
492
493 uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
494 {
495         assert(plane < bo->num_planes);
496         return bo->format_modifiers[plane];
497 }
498
499 uint32_t drv_bo_get_format(struct bo *bo)
500 {
501         return bo->format;
502 }
503
504 uint32_t drv_resolve_format(struct driver *drv, uint32_t format)
505 {
506         if (drv->backend->resolve_format)
507                 return drv->backend->resolve_format(format);
508
509         return format;
510 }
511
512 /*
513  * This function returns the stride for a given format, width and plane.
514  */
515 int drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
516 {
517         int stride = width * DIV_ROUND_UP(drv_bpp_from_format(format, plane),
518                                           8);
519
520         /*
521          * Only downsample for certain multiplanar formats which have horizontal
522          * subsampling for chroma planes.  Only formats supported by our drivers
523          * are listed here -- add more as needed.
524          */
525         if (plane != 0) {
526                 switch (format) {
527                 case DRM_FORMAT_NV12:
528                 case DRM_FORMAT_YVU420:
529                         stride = stride / 2;
530                         break;
531                 }
532         }
533
534         return stride;
535 }
536
537 size_t drv_num_planes_from_format(uint32_t format)
538 {
539         switch (format) {
540         case DRM_FORMAT_ABGR1555:
541         case DRM_FORMAT_ABGR2101010:
542         case DRM_FORMAT_ABGR4444:
543         case DRM_FORMAT_ABGR8888:
544         case DRM_FORMAT_ARGB1555:
545         case DRM_FORMAT_ARGB2101010:
546         case DRM_FORMAT_ARGB4444:
547         case DRM_FORMAT_ARGB8888:
548         case DRM_FORMAT_AYUV:
549         case DRM_FORMAT_BGR233:
550         case DRM_FORMAT_BGR565:
551         case DRM_FORMAT_BGR888:
552         case DRM_FORMAT_BGRA1010102:
553         case DRM_FORMAT_BGRA4444:
554         case DRM_FORMAT_BGRA5551:
555         case DRM_FORMAT_BGRA8888:
556         case DRM_FORMAT_BGRX1010102:
557         case DRM_FORMAT_BGRX4444:
558         case DRM_FORMAT_BGRX5551:
559         case DRM_FORMAT_BGRX8888:
560         case DRM_FORMAT_C8:
561         case DRM_FORMAT_GR88:
562         case DRM_FORMAT_R8:
563         case DRM_FORMAT_RG88:
564         case DRM_FORMAT_RGB332:
565         case DRM_FORMAT_RGB565:
566         case DRM_FORMAT_RGB888:
567         case DRM_FORMAT_RGBA1010102:
568         case DRM_FORMAT_RGBA4444:
569         case DRM_FORMAT_RGBA5551:
570         case DRM_FORMAT_RGBA8888:
571         case DRM_FORMAT_RGBX1010102:
572         case DRM_FORMAT_RGBX4444:
573         case DRM_FORMAT_RGBX5551:
574         case DRM_FORMAT_RGBX8888:
575         case DRM_FORMAT_UYVY:
576         case DRM_FORMAT_VYUY:
577         case DRM_FORMAT_XBGR1555:
578         case DRM_FORMAT_XBGR2101010:
579         case DRM_FORMAT_XBGR4444:
580         case DRM_FORMAT_XBGR8888:
581         case DRM_FORMAT_XRGB1555:
582         case DRM_FORMAT_XRGB2101010:
583         case DRM_FORMAT_XRGB4444:
584         case DRM_FORMAT_XRGB8888:
585         case DRM_FORMAT_YUYV:
586         case DRM_FORMAT_YVYU:
587                 return 1;
588         case DRM_FORMAT_NV12:
589                 return 2;
590         case DRM_FORMAT_YVU420:
591                 return 3;
592         }
593
594         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
595         return 0;
596 }
597
598 uint32_t drv_size_from_format(uint32_t format, uint32_t stride,
599                               uint32_t height, size_t plane)
600 {
601         assert(plane < drv_num_planes_from_format(format));
602         uint32_t vertical_subsampling;
603
604         switch (format) {
605         case DRM_FORMAT_NV12:
606         case DRM_FORMAT_YVU420:
607                 vertical_subsampling = (plane == 0) ? 1 : 2;
608                 break;
609         default:
610                 vertical_subsampling = 1;
611         }
612
613         return stride * DIV_ROUND_UP(height, vertical_subsampling);
614 }
615
616 uint32_t drv_num_buffers_per_bo(struct bo *bo)
617 {
618         uint32_t count = 0;
619         size_t plane, p;
620
621         for (plane = 0; plane < bo->num_planes; plane++) {
622                 for (p = 0; p < plane; p++)
623                         if (bo->handles[p].u32 == bo->handles[plane].u32)
624                                 break;
625                 if (p == plane)
626                         count++;
627         }
628
629         return count;
630 }