OSDN Git Service

minigbm: remove gma500
[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 <sys/types.h>
16 #include <unistd.h>
17 #include <xf86drm.h>
18
19 #include "drv_priv.h"
20 #include "helpers.h"
21 #include "util.h"
22
23 #ifdef DRV_AMDGPU
24 extern const struct backend backend_amdgpu;
25 #endif
26 #ifdef DRV_AMLOGIC
27 extern const struct backend backend_amlogic;
28 #endif
29 extern const struct backend backend_evdi;
30 #ifdef DRV_EXYNOS
31 extern const struct backend backend_exynos;
32 #endif
33 #ifdef DRV_I915
34 extern const struct backend backend_i915;
35 #endif
36 #ifdef DRV_MARVELL
37 extern const struct backend backend_marvell;
38 #endif
39 #ifdef DRV_MEDIATEK
40 extern const struct backend backend_mediatek;
41 #endif
42 extern const struct backend backend_nouveau;
43 #ifdef DRV_RADEON
44 extern const struct backend backend_radeon;
45 #endif
46 #ifdef DRV_ROCKCHIP
47 extern const struct backend backend_rockchip;
48 #endif
49 #ifdef DRV_TEGRA
50 extern const struct backend backend_tegra;
51 #endif
52 extern const struct backend backend_udl;
53 #ifdef DRV_VC4
54 extern const struct backend backend_vc4;
55 #endif
56 extern const struct backend backend_vgem;
57 extern const struct backend backend_virtio_gpu;
58
59 static const struct backend *drv_get_backend(int fd)
60 {
61         drmVersionPtr drm_version;
62         unsigned int i;
63
64         drm_version = drmGetVersion(fd);
65
66         if (!drm_version)
67                 return NULL;
68
69         const struct backend *backend_list[] = {
70 #ifdef DRV_AMDGPU
71                 &backend_amdgpu,
72 #endif
73 #ifdef DRV_AMLOGIC
74                 &backend_amlogic,
75 #endif
76                 &backend_evdi,
77 #ifdef DRV_EXYNOS
78                 &backend_exynos,
79 #endif
80 #ifdef DRV_I915
81                 &backend_i915,
82 #endif
83 #ifdef DRV_MARVELL
84                 &backend_marvell,
85 #endif
86 #ifdef DRV_MEDIATEK
87                 &backend_mediatek,
88 #endif
89                 &backend_nouveau,
90 #ifdef DRV_RADEON
91                 &backend_radeon,
92 #endif
93 #ifdef DRV_ROCKCHIP
94                 &backend_rockchip,
95 #endif
96 #ifdef DRV_TEGRA
97                 &backend_tegra,
98 #endif
99                 &backend_udl,
100 #ifdef DRV_VC4
101                 &backend_vc4,
102 #endif
103                 &backend_vgem,     &backend_virtio_gpu,
104         };
105
106         for (i = 0; i < ARRAY_SIZE(backend_list); i++)
107                 if (!strcmp(drm_version->name, backend_list[i]->name)) {
108                         drmFreeVersion(drm_version);
109                         return backend_list[i];
110                 }
111
112         drmFreeVersion(drm_version);
113         return NULL;
114 }
115
116 struct driver *drv_create(int fd)
117 {
118         struct driver *drv;
119         int ret;
120
121         drv = (struct driver *)calloc(1, sizeof(*drv));
122
123         if (!drv)
124                 return NULL;
125
126         drv->fd = fd;
127         drv->backend = drv_get_backend(fd);
128
129         if (!drv->backend)
130                 goto free_driver;
131
132         if (pthread_mutex_init(&drv->driver_lock, NULL))
133                 goto free_driver;
134
135         drv->buffer_table = drmHashCreate();
136         if (!drv->buffer_table)
137                 goto free_lock;
138
139         drv->mappings = drv_array_init(sizeof(struct mapping));
140         if (!drv->mappings)
141                 goto free_buffer_table;
142
143         drv->combos = drv_array_init(sizeof(struct combination));
144         if (!drv->combos)
145                 goto free_mappings;
146
147         if (drv->backend->init) {
148                 ret = drv->backend->init(drv);
149                 if (ret) {
150                         drv_array_destroy(drv->combos);
151                         goto free_mappings;
152                 }
153         }
154
155         return drv;
156
157 free_mappings:
158         drv_array_destroy(drv->mappings);
159 free_buffer_table:
160         drmHashDestroy(drv->buffer_table);
161 free_lock:
162         pthread_mutex_destroy(&drv->driver_lock);
163 free_driver:
164         free(drv);
165         return NULL;
166 }
167
168 void drv_destroy(struct driver *drv)
169 {
170         pthread_mutex_lock(&drv->driver_lock);
171
172         if (drv->backend->close)
173                 drv->backend->close(drv);
174
175         drmHashDestroy(drv->buffer_table);
176         drv_array_destroy(drv->mappings);
177         drv_array_destroy(drv->combos);
178
179         pthread_mutex_unlock(&drv->driver_lock);
180         pthread_mutex_destroy(&drv->driver_lock);
181
182         free(drv);
183 }
184
185 int drv_get_fd(struct driver *drv)
186 {
187         return drv->fd;
188 }
189
190 const char *drv_get_name(struct driver *drv)
191 {
192         return drv->backend->name;
193 }
194
195 struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags)
196 {
197         struct combination *curr, *best;
198
199         if (format == DRM_FORMAT_NONE || use_flags == BO_USE_NONE)
200                 return 0;
201
202         best = NULL;
203         uint32_t i;
204         for (i = 0; i < drv_array_size(drv->combos); i++) {
205                 curr = drv_array_at_idx(drv->combos, i);
206                 if ((format == curr->format) && use_flags == (curr->use_flags & use_flags))
207                         if (!best || best->metadata.priority < curr->metadata.priority)
208                                 best = curr;
209         }
210
211         return best;
212 }
213
214 struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
215                       uint64_t use_flags)
216 {
217
218         struct bo *bo;
219         bo = (struct bo *)calloc(1, sizeof(*bo));
220
221         if (!bo)
222                 return NULL;
223
224         bo->drv = drv;
225         bo->width = width;
226         bo->height = height;
227         bo->format = format;
228         bo->use_flags = use_flags;
229         bo->num_planes = drv_num_planes_from_format(format);
230
231         if (!bo->num_planes) {
232                 free(bo);
233                 return NULL;
234         }
235
236         return bo;
237 }
238
239 struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
240                          uint64_t use_flags)
241 {
242         int ret;
243         size_t plane;
244         struct bo *bo;
245
246         bo = drv_bo_new(drv, width, height, format, use_flags);
247
248         if (!bo)
249                 return NULL;
250
251         ret = drv->backend->bo_create(bo, width, height, format, use_flags);
252
253         if (ret) {
254                 free(bo);
255                 return NULL;
256         }
257
258         pthread_mutex_lock(&drv->driver_lock);
259
260         for (plane = 0; plane < bo->num_planes; plane++) {
261                 if (plane > 0)
262                         assert(bo->offsets[plane] >= bo->offsets[plane - 1]);
263
264                 drv_increment_reference_count(drv, bo, plane);
265         }
266
267         pthread_mutex_unlock(&drv->driver_lock);
268
269         return bo;
270 }
271
272 struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
273                                         uint32_t format, const uint64_t *modifiers, uint32_t count)
274 {
275         int ret;
276         size_t plane;
277         struct bo *bo;
278
279         if (!drv->backend->bo_create_with_modifiers) {
280                 errno = ENOENT;
281                 return NULL;
282         }
283
284         bo = drv_bo_new(drv, width, height, format, BO_USE_NONE);
285
286         if (!bo)
287                 return NULL;
288
289         ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count);
290
291         if (ret) {
292                 free(bo);
293                 return NULL;
294         }
295
296         pthread_mutex_lock(&drv->driver_lock);
297
298         for (plane = 0; plane < bo->num_planes; plane++) {
299                 if (plane > 0)
300                         assert(bo->offsets[plane] >= bo->offsets[plane - 1]);
301
302                 drv_increment_reference_count(drv, bo, plane);
303         }
304
305         pthread_mutex_unlock(&drv->driver_lock);
306
307         return bo;
308 }
309
310 void drv_bo_destroy(struct bo *bo)
311 {
312         size_t plane;
313         uintptr_t total = 0;
314         struct driver *drv = bo->drv;
315
316         pthread_mutex_lock(&drv->driver_lock);
317
318         for (plane = 0; plane < bo->num_planes; plane++)
319                 drv_decrement_reference_count(drv, bo, plane);
320
321         for (plane = 0; plane < bo->num_planes; plane++)
322                 total += drv_get_reference_count(drv, bo, plane);
323
324         pthread_mutex_unlock(&drv->driver_lock);
325
326         if (total == 0) {
327                 assert(drv_mapping_destroy(bo) == 0);
328                 bo->drv->backend->bo_destroy(bo);
329         }
330
331         free(bo);
332 }
333
334 struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
335 {
336         int ret;
337         size_t plane;
338         struct bo *bo;
339         off_t seek_end;
340
341         bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags);
342
343         if (!bo)
344                 return NULL;
345
346         ret = drv->backend->bo_import(bo, data);
347         if (ret) {
348                 free(bo);
349                 return NULL;
350         }
351
352         for (plane = 0; plane < bo->num_planes; plane++) {
353                 bo->strides[plane] = data->strides[plane];
354                 bo->offsets[plane] = data->offsets[plane];
355                 bo->format_modifiers[plane] = data->format_modifiers[plane];
356
357                 seek_end = lseek(data->fds[plane], 0, SEEK_END);
358                 if (seek_end == (off_t)(-1)) {
359                         fprintf(stderr, "drv: lseek() failed with %s\n", strerror(errno));
360                         goto destroy_bo;
361                 }
362
363                 lseek(data->fds[plane], 0, SEEK_SET);
364                 if (plane == bo->num_planes - 1 || data->offsets[plane + 1] == 0)
365                         bo->sizes[plane] = seek_end - data->offsets[plane];
366                 else
367                         bo->sizes[plane] = data->offsets[plane + 1] - data->offsets[plane];
368
369                 if ((int64_t)bo->offsets[plane] + bo->sizes[plane] > seek_end) {
370                         fprintf(stderr, "drv: buffer size is too large.\n");
371                         goto destroy_bo;
372                 }
373
374                 bo->total_size += bo->sizes[plane];
375         }
376
377         return bo;
378
379 destroy_bo:
380         drv_bo_destroy(bo);
381         return NULL;
382 }
383
384 void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
385                  struct mapping **map_data, size_t plane)
386 {
387         uint32_t i;
388         uint8_t *addr;
389         struct mapping mapping;
390
391         assert(rect->width >= 0);
392         assert(rect->height >= 0);
393         assert(rect->x + rect->width <= drv_bo_get_width(bo));
394         assert(rect->y + rect->height <= drv_bo_get_height(bo));
395         assert(BO_MAP_READ_WRITE & map_flags);
396         /* No CPU access for protected buffers. */
397         assert(!(bo->use_flags & BO_USE_PROTECTED));
398
399         memset(&mapping, 0, sizeof(mapping));
400         mapping.rect = *rect;
401         mapping.refcount = 1;
402
403         pthread_mutex_lock(&bo->drv->driver_lock);
404
405         for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
406                 struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
407                 if (prior->vma->handle != bo->handles[plane].u32 ||
408                     prior->vma->map_flags != map_flags)
409                         continue;
410
411                 if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
412                     rect->width != prior->rect.width || rect->height != prior->rect.height)
413                         continue;
414
415                 prior->refcount++;
416                 *map_data = prior;
417                 goto exact_match;
418         }
419
420         for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
421                 struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
422                 if (prior->vma->handle != bo->handles[plane].u32 ||
423                     prior->vma->map_flags != map_flags)
424                         continue;
425
426                 prior->vma->refcount++;
427                 mapping.vma = prior->vma;
428                 goto success;
429         }
430
431         mapping.vma = calloc(1, sizeof(*mapping.vma));
432         addr = bo->drv->backend->bo_map(bo, mapping.vma, plane, map_flags);
433         if (addr == MAP_FAILED) {
434                 *map_data = NULL;
435                 free(mapping.vma);
436                 pthread_mutex_unlock(&bo->drv->driver_lock);
437                 return MAP_FAILED;
438         }
439
440         mapping.vma->refcount = 1;
441         mapping.vma->addr = addr;
442         mapping.vma->handle = bo->handles[plane].u32;
443         mapping.vma->map_flags = map_flags;
444
445 success:
446         *map_data = drv_array_append(bo->drv->mappings, &mapping);
447 exact_match:
448         drv_bo_invalidate(bo, *map_data);
449         addr = (uint8_t *)((*map_data)->vma->addr);
450         addr += drv_bo_get_plane_offset(bo, plane);
451         pthread_mutex_unlock(&bo->drv->driver_lock);
452         return (void *)addr;
453 }
454
455 int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
456 {
457         uint32_t i;
458         int ret = drv_bo_flush(bo, mapping);
459         if (ret)
460                 return ret;
461
462         pthread_mutex_lock(&bo->drv->driver_lock);
463
464         if (--mapping->refcount)
465                 goto out;
466
467         if (!--mapping->vma->refcount) {
468                 ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
469                 free(mapping->vma);
470         }
471
472         for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
473                 if (mapping == (struct mapping *)drv_array_at_idx(bo->drv->mappings, i)) {
474                         drv_array_remove(bo->drv->mappings, i);
475                         break;
476                 }
477         }
478
479 out:
480         pthread_mutex_unlock(&bo->drv->driver_lock);
481         return ret;
482 }
483
484 int drv_bo_invalidate(struct bo *bo, struct mapping *mapping)
485 {
486         int ret = 0;
487
488         assert(mapping);
489         assert(mapping->vma);
490         assert(mapping->refcount > 0);
491         assert(mapping->vma->refcount > 0);
492
493         if (bo->drv->backend->bo_invalidate)
494                 ret = bo->drv->backend->bo_invalidate(bo, mapping);
495
496         return ret;
497 }
498
499 int drv_bo_flush(struct bo *bo, struct mapping *mapping)
500 {
501         int ret = 0;
502
503         assert(mapping);
504         assert(mapping->vma);
505         assert(mapping->refcount > 0);
506         assert(mapping->vma->refcount > 0);
507         assert(!(bo->use_flags & BO_USE_PROTECTED));
508
509         if (bo->drv->backend->bo_flush)
510                 ret = bo->drv->backend->bo_flush(bo, mapping);
511
512         return ret;
513 }
514
515 uint32_t drv_bo_get_width(struct bo *bo)
516 {
517         return bo->width;
518 }
519
520 uint32_t drv_bo_get_height(struct bo *bo)
521 {
522         return bo->height;
523 }
524
525 uint32_t drv_bo_get_stride_or_tiling(struct bo *bo)
526 {
527         return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0);
528 }
529
530 size_t drv_bo_get_num_planes(struct bo *bo)
531 {
532         return bo->num_planes;
533 }
534
535 union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
536 {
537         return bo->handles[plane];
538 }
539
540 #ifndef DRM_RDWR
541 #define DRM_RDWR O_RDWR
542 #endif
543
544 int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
545 {
546
547         int ret, fd;
548         assert(plane < bo->num_planes);
549
550         ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
551
552         return (ret) ? ret : fd;
553 }
554
555 uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
556 {
557         assert(plane < bo->num_planes);
558         return bo->offsets[plane];
559 }
560
561 uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane)
562 {
563         assert(plane < bo->num_planes);
564         return bo->sizes[plane];
565 }
566
567 uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane)
568 {
569         assert(plane < bo->num_planes);
570         return bo->strides[plane];
571 }
572
573 uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
574 {
575         assert(plane < bo->num_planes);
576         return bo->format_modifiers[plane];
577 }
578
579 uint32_t drv_bo_get_format(struct bo *bo)
580 {
581         return bo->format;
582 }
583
584 uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
585 {
586         if (drv->backend->resolve_format)
587                 return drv->backend->resolve_format(format, use_flags);
588
589         return format;
590 }
591
592 size_t drv_num_planes_from_format(uint32_t format)
593 {
594         switch (format) {
595         case DRM_FORMAT_ABGR1555:
596         case DRM_FORMAT_ABGR2101010:
597         case DRM_FORMAT_ABGR4444:
598         case DRM_FORMAT_ABGR8888:
599         case DRM_FORMAT_ARGB1555:
600         case DRM_FORMAT_ARGB2101010:
601         case DRM_FORMAT_ARGB4444:
602         case DRM_FORMAT_ARGB8888:
603         case DRM_FORMAT_AYUV:
604         case DRM_FORMAT_BGR233:
605         case DRM_FORMAT_BGR565:
606         case DRM_FORMAT_BGR888:
607         case DRM_FORMAT_BGRA1010102:
608         case DRM_FORMAT_BGRA4444:
609         case DRM_FORMAT_BGRA5551:
610         case DRM_FORMAT_BGRA8888:
611         case DRM_FORMAT_BGRX1010102:
612         case DRM_FORMAT_BGRX4444:
613         case DRM_FORMAT_BGRX5551:
614         case DRM_FORMAT_BGRX8888:
615         case DRM_FORMAT_C8:
616         case DRM_FORMAT_GR88:
617         case DRM_FORMAT_R8:
618         case DRM_FORMAT_RG88:
619         case DRM_FORMAT_RGB332:
620         case DRM_FORMAT_RGB565:
621         case DRM_FORMAT_RGB888:
622         case DRM_FORMAT_RGBA1010102:
623         case DRM_FORMAT_RGBA4444:
624         case DRM_FORMAT_RGBA5551:
625         case DRM_FORMAT_RGBA8888:
626         case DRM_FORMAT_RGBX1010102:
627         case DRM_FORMAT_RGBX4444:
628         case DRM_FORMAT_RGBX5551:
629         case DRM_FORMAT_RGBX8888:
630         case DRM_FORMAT_UYVY:
631         case DRM_FORMAT_VYUY:
632         case DRM_FORMAT_XBGR1555:
633         case DRM_FORMAT_XBGR2101010:
634         case DRM_FORMAT_XBGR4444:
635         case DRM_FORMAT_XBGR8888:
636         case DRM_FORMAT_XRGB1555:
637         case DRM_FORMAT_XRGB2101010:
638         case DRM_FORMAT_XRGB4444:
639         case DRM_FORMAT_XRGB8888:
640         case DRM_FORMAT_YUYV:
641         case DRM_FORMAT_YVYU:
642                 return 1;
643         case DRM_FORMAT_NV12:
644         case DRM_FORMAT_NV21:
645                 return 2;
646         case DRM_FORMAT_YVU420:
647         case DRM_FORMAT_YVU420_ANDROID:
648                 return 3;
649         }
650
651         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
652         return 0;
653 }
654
655 uint32_t drv_num_buffers_per_bo(struct bo *bo)
656 {
657         uint32_t count = 0;
658         size_t plane, p;
659
660         for (plane = 0; plane < bo->num_planes; plane++) {
661                 for (p = 0; p < plane; p++)
662                         if (bo->handles[p].u32 == bo->handles[plane].u32)
663                                 break;
664                 if (p == plane)
665                         count++;
666         }
667
668         return count;
669 }