OSDN Git Service

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