OSDN Git Service

Merge 'aosp/upstream-master' into 'aosp/master' am: 24cb462579 am: 88b0a4235a am...
[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 extern const struct backend backend_evdi;
32 #ifdef DRV_EXYNOS
33 extern const struct backend backend_exynos;
34 #endif
35 #ifdef DRV_I915
36 extern const struct backend backend_i915;
37 #endif
38 #ifdef DRV_MARVELL
39 extern const struct backend backend_marvell;
40 #endif
41 #ifdef DRV_MEDIATEK
42 extern const struct backend backend_mediatek;
43 #endif
44 #ifdef DRV_MESON
45 extern const struct backend backend_meson;
46 #endif
47 #ifdef DRV_MSM
48 extern const struct backend backend_msm;
49 #endif
50 extern const struct backend backend_nouveau;
51 #ifdef DRV_RADEON
52 extern const struct backend backend_radeon;
53 #endif
54 #ifdef DRV_ROCKCHIP
55 extern const struct backend backend_rockchip;
56 #endif
57 #ifdef DRV_TEGRA
58 extern const struct backend backend_tegra;
59 #endif
60 extern const struct backend backend_udl;
61 #ifdef DRV_VC4
62 extern const struct backend backend_vc4;
63 #endif
64 extern const struct backend backend_vgem;
65 extern const struct backend backend_virtio_gpu;
66
67 static const struct backend *drv_get_backend(int fd)
68 {
69         drmVersionPtr drm_version;
70         unsigned int i;
71
72         drm_version = drmGetVersion(fd);
73
74         if (!drm_version)
75                 return NULL;
76
77         const struct backend *backend_list[] = {
78 #ifdef DRV_AMDGPU
79                 &backend_amdgpu,
80 #endif
81                 &backend_evdi,
82 #ifdef DRV_EXYNOS
83                 &backend_exynos,
84 #endif
85 #ifdef DRV_I915
86                 &backend_i915,
87 #endif
88 #ifdef DRV_MARVELL
89                 &backend_marvell,
90 #endif
91 #ifdef DRV_MEDIATEK
92                 &backend_mediatek,
93 #endif
94 #ifdef DRV_MESON
95                 &backend_meson,
96 #endif
97 #ifdef DRV_MSM
98                 &backend_msm,
99 #endif
100                 &backend_nouveau,
101 #ifdef DRV_RADEON
102                 &backend_radeon,
103 #endif
104 #ifdef DRV_ROCKCHIP
105                 &backend_rockchip,
106 #endif
107 #ifdef DRV_TEGRA
108                 &backend_tegra,
109 #endif
110                 &backend_udl,
111 #ifdef DRV_VC4
112                 &backend_vc4,
113 #endif
114                 &backend_vgem,     &backend_virtio_gpu,
115         };
116
117         for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
118                 const struct backend *b = backend_list[i];
119                 // Exactly one of the main create functions must be defined.
120                 assert((b->bo_create != NULL) ^ (b->bo_create_from_metadata != NULL));
121                 // Either both or neither must be implemented.
122                 assert((b->bo_compute_metadata != NULL) == (b->bo_create_from_metadata != NULL));
123                 // Both can't be defined, but it's okay for neither to be (i.e. only bo_create).
124                 assert((b->bo_create_with_modifiers == NULL) ||
125                        (b->bo_create_from_metadata == NULL));
126
127                 if (!strcmp(drm_version->name, b->name)) {
128                         drmFreeVersion(drm_version);
129                         return b;
130                 }
131         }
132
133         drmFreeVersion(drm_version);
134         return NULL;
135 }
136
137 struct driver *drv_create(int fd)
138 {
139         struct driver *drv;
140         int ret;
141
142         drv = (struct driver *)calloc(1, sizeof(*drv));
143
144         if (!drv)
145                 return NULL;
146
147         drv->fd = fd;
148         drv->backend = drv_get_backend(fd);
149
150         if (!drv->backend)
151                 goto free_driver;
152
153         if (pthread_mutex_init(&drv->driver_lock, NULL))
154                 goto free_driver;
155
156         drv->buffer_table = drmHashCreate();
157         if (!drv->buffer_table)
158                 goto free_lock;
159
160         drv->mappings = drv_array_init(sizeof(struct mapping));
161         if (!drv->mappings)
162                 goto free_buffer_table;
163
164         drv->combos = drv_array_init(sizeof(struct combination));
165         if (!drv->combos)
166                 goto free_mappings;
167
168         if (drv->backend->init) {
169                 ret = drv->backend->init(drv);
170                 if (ret) {
171                         drv_array_destroy(drv->combos);
172                         goto free_mappings;
173                 }
174         }
175
176         return drv;
177
178 free_mappings:
179         drv_array_destroy(drv->mappings);
180 free_buffer_table:
181         drmHashDestroy(drv->buffer_table);
182 free_lock:
183         pthread_mutex_destroy(&drv->driver_lock);
184 free_driver:
185         free(drv);
186         return NULL;
187 }
188
189 void drv_destroy(struct driver *drv)
190 {
191         pthread_mutex_lock(&drv->driver_lock);
192
193         if (drv->backend->close)
194                 drv->backend->close(drv);
195
196         drmHashDestroy(drv->buffer_table);
197         drv_array_destroy(drv->mappings);
198         drv_array_destroy(drv->combos);
199
200         pthread_mutex_unlock(&drv->driver_lock);
201         pthread_mutex_destroy(&drv->driver_lock);
202
203         free(drv);
204 }
205
206 int drv_get_fd(struct driver *drv)
207 {
208         return drv->fd;
209 }
210
211 const char *drv_get_name(struct driver *drv)
212 {
213         return drv->backend->name;
214 }
215
216 struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags)
217 {
218         struct combination *curr, *best;
219
220         if (format == DRM_FORMAT_NONE || use_flags == BO_USE_NONE)
221                 return 0;
222
223         best = NULL;
224         uint32_t i;
225         for (i = 0; i < drv_array_size(drv->combos); i++) {
226                 curr = drv_array_at_idx(drv->combos, i);
227                 if ((format == curr->format) && use_flags == (curr->use_flags & use_flags))
228                         if (!best || best->metadata.priority < curr->metadata.priority)
229                                 best = curr;
230         }
231
232         return best;
233 }
234
235 struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
236                       uint64_t use_flags, bool is_test_buffer)
237 {
238
239         struct bo *bo;
240         bo = (struct bo *)calloc(1, sizeof(*bo));
241
242         if (!bo)
243                 return NULL;
244
245         bo->drv = drv;
246         bo->meta.width = width;
247         bo->meta.height = height;
248         bo->meta.format = format;
249         bo->meta.use_flags = use_flags;
250         bo->meta.num_planes = drv_num_planes_from_format(format);
251         bo->is_test_buffer = is_test_buffer;
252
253         if (!bo->meta.num_planes) {
254                 free(bo);
255                 return NULL;
256         }
257
258         return bo;
259 }
260
261 struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
262                          uint64_t use_flags)
263 {
264         int ret;
265         size_t plane;
266         struct bo *bo;
267         bool is_test_alloc;
268
269         is_test_alloc = use_flags & BO_USE_TEST_ALLOC;
270         use_flags &= ~BO_USE_TEST_ALLOC;
271
272         bo = drv_bo_new(drv, width, height, format, use_flags, is_test_alloc);
273
274         if (!bo)
275                 return NULL;
276
277         ret = -EINVAL;
278         if (drv->backend->bo_compute_metadata) {
279                 ret = drv->backend->bo_compute_metadata(bo, width, height, format, use_flags, NULL,
280                                                         0);
281                 if (!is_test_alloc && ret == 0) {
282                         ret = drv->backend->bo_create_from_metadata(bo);
283                         if (ret == 0)
284                                 return bo;
285                 }
286         } else if (!is_test_alloc) {
287                 ret = drv->backend->bo_create(bo, width, height, format, use_flags);
288         }
289
290         if (ret) {
291                 free(bo);
292                 return NULL;
293         }
294
295         pthread_mutex_lock(&drv->driver_lock);
296
297         for (plane = 0; plane < bo->meta.num_planes; plane++) {
298                 if (plane > 0)
299                         assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]);
300
301                 drv_increment_reference_count(drv, bo, plane);
302         }
303
304         pthread_mutex_unlock(&drv->driver_lock);
305
306         return bo;
307 }
308
309 struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
310                                         uint32_t format, const uint64_t *modifiers, uint32_t count)
311 {
312         int ret;
313         size_t plane;
314         struct bo *bo;
315
316         if (!drv->backend->bo_create_with_modifiers && !drv->backend->bo_compute_metadata) {
317                 errno = ENOENT;
318                 return NULL;
319         }
320
321         bo = drv_bo_new(drv, width, height, format, BO_USE_NONE, false);
322
323         if (!bo)
324                 return NULL;
325
326         ret = -EINVAL;
327         if (drv->backend->bo_compute_metadata) {
328                 ret = drv->backend->bo_compute_metadata(bo, width, height, format, BO_USE_NONE,
329                                                         modifiers, count);
330                 if (ret == 0)
331                         ret = drv->backend->bo_create_from_metadata(bo);
332         } else {
333                 ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers,
334                                                              count);
335         }
336
337         if (ret) {
338                 free(bo);
339                 return NULL;
340         }
341
342         pthread_mutex_lock(&drv->driver_lock);
343
344         for (plane = 0; plane < bo->meta.num_planes; plane++) {
345                 if (plane > 0)
346                         assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]);
347
348                 drv_increment_reference_count(drv, bo, plane);
349         }
350
351         pthread_mutex_unlock(&drv->driver_lock);
352
353         return bo;
354 }
355
356 void drv_bo_destroy(struct bo *bo)
357 {
358         int ret;
359         size_t plane;
360         uintptr_t total = 0;
361         struct driver *drv = bo->drv;
362
363         if (!bo->is_test_buffer) {
364                 pthread_mutex_lock(&drv->driver_lock);
365
366                 for (plane = 0; plane < bo->meta.num_planes; plane++)
367                         drv_decrement_reference_count(drv, bo, plane);
368
369                 for (plane = 0; plane < bo->meta.num_planes; plane++)
370                         total += drv_get_reference_count(drv, bo, plane);
371
372                 pthread_mutex_unlock(&drv->driver_lock);
373
374                 if (total == 0) {
375                         ret = drv_mapping_destroy(bo);
376                         assert(ret == 0);
377                         bo->drv->backend->bo_destroy(bo);
378                 }
379         }
380
381         free(bo);
382 }
383
384 struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
385 {
386         int ret;
387         size_t plane;
388         struct bo *bo;
389         off_t seek_end;
390
391         bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags, false);
392
393         if (!bo)
394                 return NULL;
395
396         ret = drv->backend->bo_import(bo, data);
397         if (ret) {
398                 free(bo);
399                 return NULL;
400         }
401
402         for (plane = 0; plane < bo->meta.num_planes; plane++) {
403                 pthread_mutex_lock(&bo->drv->driver_lock);
404                 drv_increment_reference_count(bo->drv, bo, plane);
405                 pthread_mutex_unlock(&bo->drv->driver_lock);
406         }
407
408         for (plane = 0; plane < bo->meta.num_planes; plane++) {
409                 bo->meta.strides[plane] = data->strides[plane];
410                 bo->meta.offsets[plane] = data->offsets[plane];
411                 bo->meta.format_modifiers[plane] = data->format_modifiers[plane];
412
413                 seek_end = lseek(data->fds[plane], 0, SEEK_END);
414                 if (seek_end == (off_t)(-1)) {
415                         drv_log("lseek() failed with %s\n", strerror(errno));
416                         goto destroy_bo;
417                 }
418
419                 lseek(data->fds[plane], 0, SEEK_SET);
420                 if (plane == bo->meta.num_planes - 1 || data->offsets[plane + 1] == 0)
421                         bo->meta.sizes[plane] = seek_end - data->offsets[plane];
422                 else
423                         bo->meta.sizes[plane] = data->offsets[plane + 1] - data->offsets[plane];
424
425                 if ((int64_t)bo->meta.offsets[plane] + bo->meta.sizes[plane] > seek_end) {
426                         drv_log("buffer size is too large.\n");
427                         goto destroy_bo;
428                 }
429
430                 bo->meta.total_size += bo->meta.sizes[plane];
431         }
432
433         return bo;
434
435 destroy_bo:
436         drv_bo_destroy(bo);
437         return NULL;
438 }
439
440 void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
441                  struct mapping **map_data, size_t plane)
442 {
443         uint32_t i;
444         uint8_t *addr;
445         struct mapping mapping;
446
447         assert(rect->width >= 0);
448         assert(rect->height >= 0);
449         assert(rect->x + rect->width <= drv_bo_get_width(bo));
450         assert(rect->y + rect->height <= drv_bo_get_height(bo));
451         assert(BO_MAP_READ_WRITE & map_flags);
452         /* No CPU access for protected buffers. */
453         assert(!(bo->meta.use_flags & BO_USE_PROTECTED));
454
455         if (bo->is_test_buffer) {
456                 return MAP_FAILED;
457         }
458
459         memset(&mapping, 0, sizeof(mapping));
460         mapping.rect = *rect;
461         mapping.refcount = 1;
462
463         pthread_mutex_lock(&bo->drv->driver_lock);
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                 if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
472                     rect->width != prior->rect.width || rect->height != prior->rect.height)
473                         continue;
474
475                 prior->refcount++;
476                 *map_data = prior;
477                 goto exact_match;
478         }
479
480         for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
481                 struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
482                 if (prior->vma->handle != bo->handles[plane].u32 ||
483                     prior->vma->map_flags != map_flags)
484                         continue;
485
486                 prior->vma->refcount++;
487                 mapping.vma = prior->vma;
488                 goto success;
489         }
490
491         mapping.vma = calloc(1, sizeof(*mapping.vma));
492         memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides));
493         addr = bo->drv->backend->bo_map(bo, mapping.vma, plane, map_flags);
494         if (addr == MAP_FAILED) {
495                 *map_data = NULL;
496                 free(mapping.vma);
497                 pthread_mutex_unlock(&bo->drv->driver_lock);
498                 return MAP_FAILED;
499         }
500
501         mapping.vma->refcount = 1;
502         mapping.vma->addr = addr;
503         mapping.vma->handle = bo->handles[plane].u32;
504         mapping.vma->map_flags = map_flags;
505
506 success:
507         *map_data = drv_array_append(bo->drv->mappings, &mapping);
508 exact_match:
509         drv_bo_invalidate(bo, *map_data);
510         addr = (uint8_t *)((*map_data)->vma->addr);
511         addr += drv_bo_get_plane_offset(bo, plane);
512         pthread_mutex_unlock(&bo->drv->driver_lock);
513         return (void *)addr;
514 }
515
516 int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
517 {
518         uint32_t i;
519         int ret = 0;
520
521         pthread_mutex_lock(&bo->drv->driver_lock);
522
523         if (--mapping->refcount)
524                 goto out;
525
526         if (!--mapping->vma->refcount) {
527                 ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
528                 free(mapping->vma);
529         }
530
531         for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
532                 if (mapping == (struct mapping *)drv_array_at_idx(bo->drv->mappings, i)) {
533                         drv_array_remove(bo->drv->mappings, i);
534                         break;
535                 }
536         }
537
538 out:
539         pthread_mutex_unlock(&bo->drv->driver_lock);
540         return ret;
541 }
542
543 int drv_bo_invalidate(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_invalidate)
553                 ret = bo->drv->backend->bo_invalidate(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 uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
649 {
650         if (drv->backend->resolve_format)
651                 return drv->backend->resolve_format(drv, format, use_flags);
652
653         return format;
654 }
655
656 uint32_t drv_num_buffers_per_bo(struct bo *bo)
657 {
658         uint32_t count = 0;
659         size_t plane, p;
660
661         if (bo->is_test_buffer) {
662                 return 0;
663         }
664
665         for (plane = 0; plane < bo->meta.num_planes; plane++) {
666                 for (p = 0; p < plane; p++)
667                         if (bo->handles[p].u32 == bo->handles[plane].u32)
668                                 break;
669                 if (p == plane)
670                         count++;
671         }
672
673         return count;
674 }
675
676 void drv_log_prefix(const char *prefix, const char *file, int line, const char *format, ...)
677 {
678         char buf[50];
679         snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line);
680
681         va_list args;
682         va_start(args, format);
683 #ifdef __ANDROID__
684         __android_log_vprint(ANDROID_LOG_ERROR, buf, format, args);
685 #else
686         fprintf(stderr, "%s ", buf);
687         vfprintf(stderr, format, args);
688 #endif
689         va_end(args);
690 }