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 if (!strcmp(drm_version->name, backend_list[i]->name)) { 119 drmFreeVersion(drm_version); 120 return backend_list[i]; 121 } 122 123 drmFreeVersion(drm_version); 124 return NULL; 125 } 126 127 struct driver *drv_create(int fd) 128 { 129 struct driver *drv; 130 int ret; 131 132 drv = (struct driver *)calloc(1, sizeof(*drv)); 133 134 if (!drv) 135 return NULL; 136 137 drv->fd = fd; 138 drv->backend = drv_get_backend(fd); 139 140 if (!drv->backend) 141 goto free_driver; 142 143 if (pthread_mutex_init(&drv->driver_lock, NULL)) 144 goto free_driver; 145 146 drv->buffer_table = drmHashCreate(); 147 if (!drv->buffer_table) 148 goto free_lock; 149 150 drv->mappings = drv_array_init(sizeof(struct mapping)); 151 if (!drv->mappings) 152 goto free_buffer_table; 153 154 drv->combos = drv_array_init(sizeof(struct combination)); 155 if (!drv->combos) 156 goto free_mappings; 157 158 if (drv->backend->init) { 159 ret = drv->backend->init(drv); 160 if (ret) { 161 drv_array_destroy(drv->combos); 162 goto free_mappings; 163 } 164 } 165 166 return drv; 167 168 free_mappings: 169 drv_array_destroy(drv->mappings); 170 free_buffer_table: 171 drmHashDestroy(drv->buffer_table); 172 free_lock: 173 pthread_mutex_destroy(&drv->driver_lock); 174 free_driver: 175 free(drv); 176 return NULL; 177 } 178 179 void drv_destroy(struct driver *drv) 180 { 181 pthread_mutex_lock(&drv->driver_lock); 182 183 if (drv->backend->close) 184 drv->backend->close(drv); 185 186 drmHashDestroy(drv->buffer_table); 187 drv_array_destroy(drv->mappings); 188 drv_array_destroy(drv->combos); 189 190 pthread_mutex_unlock(&drv->driver_lock); 191 pthread_mutex_destroy(&drv->driver_lock); 192 193 free(drv); 194 } 195 196 int drv_get_fd(struct driver *drv) 197 { 198 return drv->fd; 199 } 200 201 const char *drv_get_name(struct driver *drv) 202 { 203 return drv->backend->name; 204 } 205 206 struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags) 207 { 208 struct combination *curr, *best; 209 210 if (format == DRM_FORMAT_NONE || use_flags == BO_USE_NONE) 211 return 0; 212 213 best = NULL; 214 uint32_t i; 215 for (i = 0; i < drv_array_size(drv->combos); i++) { 216 curr = drv_array_at_idx(drv->combos, i); 217 if ((format == curr->format) && use_flags == (curr->use_flags & use_flags)) 218 if (!best || best->metadata.priority < curr->metadata.priority) 219 best = curr; 220 } 221 222 return best; 223 } 224 225 struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, 226 uint64_t use_flags) 227 { 228 229 struct bo *bo; 230 bo = (struct bo *)calloc(1, sizeof(*bo)); 231 232 if (!bo) 233 return NULL; 234 235 bo->drv = drv; 236 bo->width = width; 237 bo->height = height; 238 bo->format = format; 239 bo->use_flags = use_flags; 240 bo->num_planes = drv_num_planes_from_format(format); 241 242 if (!bo->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 257 bo = drv_bo_new(drv, width, height, format, use_flags); 258 259 if (!bo) 260 return NULL; 261 262 ret = drv->backend->bo_create(bo, width, height, format, use_flags); 263 264 if (ret) { 265 free(bo); 266 return NULL; 267 } 268 269 pthread_mutex_lock(&drv->driver_lock); 270 271 for (plane = 0; plane < bo->num_planes; plane++) { 272 if (plane > 0) 273 assert(bo->offsets[plane] >= bo->offsets[plane - 1]); 274 275 drv_increment_reference_count(drv, bo, plane); 276 } 277 278 pthread_mutex_unlock(&drv->driver_lock); 279 280 return bo; 281 } 282 283 struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height, 284 uint32_t format, const uint64_t *modifiers, uint32_t count) 285 { 286 int ret; 287 size_t plane; 288 struct bo *bo; 289 290 if (!drv->backend->bo_create_with_modifiers) { 291 errno = ENOENT; 292 return NULL; 293 } 294 295 bo = drv_bo_new(drv, width, height, format, BO_USE_NONE); 296 297 if (!bo) 298 return NULL; 299 300 ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count); 301 302 if (ret) { 303 free(bo); 304 return NULL; 305 } 306 307 pthread_mutex_lock(&drv->driver_lock); 308 309 for (plane = 0; plane < bo->num_planes; plane++) { 310 if (plane > 0) 311 assert(bo->offsets[plane] >= bo->offsets[plane - 1]); 312 313 drv_increment_reference_count(drv, bo, plane); 314 } 315 316 pthread_mutex_unlock(&drv->driver_lock); 317 318 return bo; 319 } 320 321 void drv_bo_destroy(struct bo *bo) 322 { 323 size_t plane; 324 uintptr_t total = 0; 325 struct driver *drv = bo->drv; 326 327 pthread_mutex_lock(&drv->driver_lock); 328 329 for (plane = 0; plane < bo->num_planes; plane++) 330 drv_decrement_reference_count(drv, bo, plane); 331 332 for (plane = 0; plane < bo->num_planes; plane++) 333 total += drv_get_reference_count(drv, bo, plane); 334 335 pthread_mutex_unlock(&drv->driver_lock); 336 337 if (total == 0) { 338 assert(drv_mapping_destroy(bo) == 0); 339 bo->drv->backend->bo_destroy(bo); 340 } 341 342 free(bo); 343 } 344 345 struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) 346 { 347 int ret; 348 size_t plane; 349 struct bo *bo; 350 off_t seek_end; 351 352 bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags); 353 354 if (!bo) 355 return NULL; 356 357 ret = drv->backend->bo_import(bo, data); 358 if (ret) { 359 free(bo); 360 return NULL; 361 } 362 363 for (plane = 0; plane < bo->num_planes; plane++) { 364 bo->strides[plane] = data->strides[plane]; 365 bo->offsets[plane] = data->offsets[plane]; 366 bo->format_modifiers[plane] = data->format_modifiers[plane]; 367 368 seek_end = lseek(data->fds[plane], 0, SEEK_END); 369 if (seek_end == (off_t)(-1)) { 370 drv_log("lseek() failed with %s\n", strerror(errno)); 371 goto destroy_bo; 372 } 373 374 lseek(data->fds[plane], 0, SEEK_SET); 375 if (plane == bo->num_planes - 1 || data->offsets[plane + 1] == 0) 376 bo->sizes[plane] = seek_end - data->offsets[plane]; 377 else 378 bo->sizes[plane] = data->offsets[plane + 1] - data->offsets[plane]; 379 380 if ((int64_t)bo->offsets[plane] + bo->sizes[plane] > seek_end) { 381 drv_log("buffer size is too large.\n"); 382 goto destroy_bo; 383 } 384 385 bo->total_size += bo->sizes[plane]; 386 } 387 388 return bo; 389 390 destroy_bo: 391 drv_bo_destroy(bo); 392 return NULL; 393 } 394 395 void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags, 396 struct mapping **map_data, size_t plane) 397 { 398 uint32_t i; 399 uint8_t *addr; 400 struct mapping mapping; 401 402 assert(rect->width >= 0); 403 assert(rect->height >= 0); 404 assert(rect->x + rect->width <= drv_bo_get_width(bo)); 405 assert(rect->y + rect->height <= drv_bo_get_height(bo)); 406 assert(BO_MAP_READ_WRITE & map_flags); 407 /* No CPU access for protected buffers. */ 408 assert(!(bo->use_flags & BO_USE_PROTECTED)); 409 410 memset(&mapping, 0, sizeof(mapping)); 411 mapping.rect = *rect; 412 mapping.refcount = 1; 413 414 pthread_mutex_lock(&bo->drv->driver_lock); 415 416 for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { 417 struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i); 418 if (prior->vma->handle != bo->handles[plane].u32 || 419 prior->vma->map_flags != map_flags) 420 continue; 421 422 if (rect->x != prior->rect.x || rect->y != prior->rect.y || 423 rect->width != prior->rect.width || rect->height != prior->rect.height) 424 continue; 425 426 prior->refcount++; 427 *map_data = prior; 428 goto exact_match; 429 } 430 431 for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { 432 struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i); 433 if (prior->vma->handle != bo->handles[plane].u32 || 434 prior->vma->map_flags != map_flags) 435 continue; 436 437 prior->vma->refcount++; 438 mapping.vma = prior->vma; 439 goto success; 440 } 441 442 mapping.vma = calloc(1, sizeof(*mapping.vma)); 443 memcpy(mapping.vma->map_strides, bo->strides, sizeof(mapping.vma->map_strides)); 444 addr = bo->drv->backend->bo_map(bo, mapping.vma, plane, map_flags); 445 if (addr == MAP_FAILED) { 446 *map_data = NULL; 447 free(mapping.vma); 448 pthread_mutex_unlock(&bo->drv->driver_lock); 449 return MAP_FAILED; 450 } 451 452 mapping.vma->refcount = 1; 453 mapping.vma->addr = addr; 454 mapping.vma->handle = bo->handles[plane].u32; 455 mapping.vma->map_flags = map_flags; 456 457 success: 458 *map_data = drv_array_append(bo->drv->mappings, &mapping); 459 exact_match: 460 drv_bo_invalidate(bo, *map_data); 461 addr = (uint8_t *)((*map_data)->vma->addr); 462 addr += drv_bo_get_plane_offset(bo, plane); 463 pthread_mutex_unlock(&bo->drv->driver_lock); 464 return (void *)addr; 465 } 466 467 int drv_bo_unmap(struct bo *bo, struct mapping *mapping) 468 { 469 uint32_t i; 470 int ret = 0; 471 472 pthread_mutex_lock(&bo->drv->driver_lock); 473 474 if (--mapping->refcount) 475 goto out; 476 477 if (!--mapping->vma->refcount) { 478 ret = bo->drv->backend->bo_unmap(bo, mapping->vma); 479 free(mapping->vma); 480 } 481 482 for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { 483 if (mapping == (struct mapping *)drv_array_at_idx(bo->drv->mappings, i)) { 484 drv_array_remove(bo->drv->mappings, i); 485 break; 486 } 487 } 488 489 out: 490 pthread_mutex_unlock(&bo->drv->driver_lock); 491 return ret; 492 } 493 494 int drv_bo_invalidate(struct bo *bo, struct mapping *mapping) 495 { 496 int ret = 0; 497 498 assert(mapping); 499 assert(mapping->vma); 500 assert(mapping->refcount > 0); 501 assert(mapping->vma->refcount > 0); 502 503 if (bo->drv->backend->bo_invalidate) 504 ret = bo->drv->backend->bo_invalidate(bo, mapping); 505 506 return ret; 507 } 508 509 int drv_bo_flush_or_unmap(struct bo *bo, struct mapping *mapping) 510 { 511 int ret = 0; 512 513 assert(mapping); 514 assert(mapping->vma); 515 assert(mapping->refcount > 0); 516 assert(mapping->vma->refcount > 0); 517 assert(!(bo->use_flags & BO_USE_PROTECTED)); 518 519 if (bo->drv->backend->bo_flush) 520 ret = bo->drv->backend->bo_flush(bo, mapping); 521 else 522 ret = drv_bo_unmap(bo, mapping); 523 524 return ret; 525 } 526 527 uint32_t drv_bo_get_width(struct bo *bo) 528 { 529 return bo->width; 530 } 531 532 uint32_t drv_bo_get_height(struct bo *bo) 533 { 534 return bo->height; 535 } 536 537 uint32_t drv_bo_get_stride_or_tiling(struct bo *bo) 538 { 539 return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0); 540 } 541 542 size_t drv_bo_get_num_planes(struct bo *bo) 543 { 544 return bo->num_planes; 545 } 546 547 union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane) 548 { 549 return bo->handles[plane]; 550 } 551 552 #ifndef DRM_RDWR 553 #define DRM_RDWR O_RDWR 554 #endif 555 556 int drv_bo_get_plane_fd(struct bo *bo, size_t plane) 557 { 558 559 int ret, fd; 560 assert(plane < bo->num_planes); 561 562 ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd); 563 564 // Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping anyways 565 if (ret) 566 ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC, &fd); 567 568 return (ret) ? ret : fd; 569 } 570 571 uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane) 572 { 573 assert(plane < bo->num_planes); 574 return bo->offsets[plane]; 575 } 576 577 uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane) 578 { 579 assert(plane < bo->num_planes); 580 return bo->sizes[plane]; 581 } 582 583 uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane) 584 { 585 assert(plane < bo->num_planes); 586 return bo->strides[plane]; 587 } 588 589 uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane) 590 { 591 assert(plane < bo->num_planes); 592 return bo->format_modifiers[plane]; 593 } 594 595 uint32_t drv_bo_get_format(struct bo *bo) 596 { 597 return bo->format; 598 } 599 600 uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) 601 { 602 if (drv->backend->resolve_format) 603 return drv->backend->resolve_format(format, use_flags); 604 605 return format; 606 } 607 608 uint32_t drv_num_buffers_per_bo(struct bo *bo) 609 { 610 uint32_t count = 0; 611 size_t plane, p; 612 613 for (plane = 0; plane < bo->num_planes; plane++) { 614 for (p = 0; p < plane; p++) 615 if (bo->handles[p].u32 == bo->handles[plane].u32) 616 break; 617 if (p == plane) 618 count++; 619 } 620 621 return count; 622 } 623 624 void drv_log_prefix(const char *prefix, const char *file, int line, const char *format, ...) 625 { 626 char buf[50]; 627 snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line); 628 629 va_list args; 630 va_start(args, format); 631 #ifdef __ANDROID__ 632 __android_log_vprint(ANDROID_LOG_ERROR, buf, format, args); 633 #else 634 fprintf(stderr, "%s ", buf); 635 vfprintf(stderr, format, args); 636 #endif 637 va_end(args); 638 } 639