1 /* 2 * Copyright 2014 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 7 #define _GNU_SOURCE 8 #include <assert.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <linux/dma-buf.h> 12 #include <stdbool.h> 13 #include <stddef.h> 14 #include <stdint.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <sys/ioctl.h> 19 #include <sys/mman.h> 20 #include <sys/types.h> 21 #include <sys/stat.h> 22 #include <unistd.h> 23 #include <xf86drm.h> 24 #include <xf86drmMode.h> 25 26 #include <gbm.h> 27 28 #define CHECK(cond) do {\ 29 if (!(cond)) {\ 30 printf("CHECK failed in %s() %s:%d\n", __func__, __FILE__, __LINE__);\ 31 return 0;\ 32 }\ 33 } while(0) 34 35 #define HANDLE_EINTR(x) \ 36 ({ \ 37 int eintr_wrapper_counter = 0; \ 38 int eintr_wrapper_result; \ 39 do { \ 40 eintr_wrapper_result = (x); \ 41 } while (eintr_wrapper_result == -1 && errno == EINTR && \ 42 eintr_wrapper_counter++ < 100); \ 43 eintr_wrapper_result; \ 44 }) 45 46 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A))) 47 48 #define ENODRM -1 49 #define ENODISPLAY -2 50 51 static int fd; 52 static struct gbm_device *gbm; 53 54 static const uint32_t format_list[] = { 55 GBM_FORMAT_C8, 56 GBM_FORMAT_RGB332, 57 GBM_FORMAT_BGR233, 58 GBM_FORMAT_XRGB4444, 59 GBM_FORMAT_XBGR4444, 60 GBM_FORMAT_RGBX4444, 61 GBM_FORMAT_BGRX4444, 62 GBM_FORMAT_ARGB4444, 63 GBM_FORMAT_ABGR4444, 64 GBM_FORMAT_RGBA4444, 65 GBM_FORMAT_BGRA4444, 66 GBM_FORMAT_XRGB1555, 67 GBM_FORMAT_XBGR1555, 68 GBM_FORMAT_RGBX5551, 69 GBM_FORMAT_BGRX5551, 70 GBM_FORMAT_ARGB1555, 71 GBM_FORMAT_ABGR1555, 72 GBM_FORMAT_RGBA5551, 73 GBM_FORMAT_BGRA5551, 74 GBM_FORMAT_RGB565, 75 GBM_FORMAT_BGR565, 76 GBM_FORMAT_RGB888, 77 GBM_FORMAT_BGR888, 78 GBM_FORMAT_XRGB8888, 79 GBM_FORMAT_XBGR8888, 80 GBM_FORMAT_RGBX8888, 81 GBM_FORMAT_BGRX8888, 82 GBM_FORMAT_ARGB8888, 83 GBM_FORMAT_ABGR8888, 84 GBM_FORMAT_RGBA8888, 85 GBM_FORMAT_BGRA8888, 86 GBM_FORMAT_XRGB2101010, 87 GBM_FORMAT_XBGR2101010, 88 GBM_FORMAT_RGBX1010102, 89 GBM_FORMAT_BGRX1010102, 90 GBM_FORMAT_ARGB2101010, 91 GBM_FORMAT_ABGR2101010, 92 GBM_FORMAT_RGBA1010102, 93 GBM_FORMAT_BGRA1010102, 94 GBM_FORMAT_YUYV, 95 GBM_FORMAT_YVYU, 96 GBM_FORMAT_UYVY, 97 GBM_FORMAT_VYUY, 98 GBM_FORMAT_AYUV, 99 GBM_FORMAT_NV12, 100 GBM_FORMAT_YVU420, 101 }; 102 103 struct plane_info { 104 uint32_t bits_per_pixel; 105 uint32_t subsample_rate; 106 }; 107 108 #define MAX_PLANES 3 109 struct format_info { 110 uint32_t pixel_format; 111 int num_planes; 112 struct plane_info planes[MAX_PLANES]; 113 }; 114 115 /* Bits per pixel for each. */ 116 static const struct format_info format_info_list[] = { 117 {GBM_FORMAT_C8, 1, {{8, 1}}}, 118 {GBM_FORMAT_RGB332, 1, {{8, 1}}}, 119 {GBM_FORMAT_BGR233, 1, {{8, 1}}}, 120 {GBM_FORMAT_XRGB4444, 1, {{16, 1}}}, 121 {GBM_FORMAT_XBGR4444, 1, {{16, 1}}}, 122 {GBM_FORMAT_RGBX4444, 1, {{16, 1}}}, 123 {GBM_FORMAT_BGRX4444, 1, {{16, 1}}}, 124 {GBM_FORMAT_ARGB4444, 1, {{16, 1}}}, 125 {GBM_FORMAT_ABGR4444, 1, {{16, 1}}}, 126 {GBM_FORMAT_RGBA4444, 1, {{16, 1}}}, 127 {GBM_FORMAT_BGRA4444, 1, {{16, 1}}}, 128 {GBM_FORMAT_XRGB1555, 1, {{16, 1}}}, 129 {GBM_FORMAT_XBGR1555, 1, {{16, 1}}}, 130 {GBM_FORMAT_RGBX5551, 1, {{16, 1}}}, 131 {GBM_FORMAT_BGRX5551, 1, {{16, 1}}}, 132 {GBM_FORMAT_ARGB1555, 1, {{16, 1}}}, 133 {GBM_FORMAT_ABGR1555, 1, {{16, 1}}}, 134 {GBM_FORMAT_RGBA5551, 1, {{16, 1}}}, 135 {GBM_FORMAT_BGRA5551, 1, {{16, 1}}}, 136 {GBM_FORMAT_RGB565, 1, {{16, 1}}}, 137 {GBM_FORMAT_BGR565, 1, {{16, 1}}}, 138 {GBM_FORMAT_RGB888, 1, {{24, 1}}}, 139 {GBM_FORMAT_BGR888, 1, {{24, 1}}}, 140 {GBM_FORMAT_XRGB8888, 1, {{32, 1}}}, 141 {GBM_FORMAT_XBGR8888, 1, {{32, 1}}}, 142 {GBM_FORMAT_RGBX8888, 1, {{32, 1}}}, 143 {GBM_FORMAT_BGRX8888, 1, {{32, 1}}}, 144 {GBM_FORMAT_ARGB8888, 1, {{32, 1}}}, 145 {GBM_FORMAT_ABGR8888, 1, {{32, 1}}}, 146 {GBM_FORMAT_RGBA8888, 1, {{32, 1}}}, 147 {GBM_FORMAT_BGRA8888, 1, {{32, 1}}}, 148 {GBM_FORMAT_XRGB2101010, 1, {{32, 1}}}, 149 {GBM_FORMAT_XBGR2101010, 1, {{32, 1}}}, 150 {GBM_FORMAT_RGBX1010102, 1, {{32, 1}}}, 151 {GBM_FORMAT_BGRX1010102, 1, {{32, 1}}}, 152 {GBM_FORMAT_ARGB2101010, 1, {{32, 1}}}, 153 {GBM_FORMAT_ABGR2101010, 1, {{32, 1}}}, 154 {GBM_FORMAT_RGBA1010102, 1, {{32, 1}}}, 155 {GBM_FORMAT_BGRA1010102, 1, {{32, 1}}}, 156 {GBM_FORMAT_YUYV, 1, {{16, 1}}}, 157 {GBM_FORMAT_YVYU, 1, {{16, 1}}}, 158 {GBM_FORMAT_UYVY, 1, {{16, 1}}}, 159 {GBM_FORMAT_VYUY, 1, {{16, 1}}}, 160 {GBM_FORMAT_AYUV, 1, {{32, 1}}}, 161 {GBM_FORMAT_NV12, 2, {{8, 1}, {16, 2}}}, 162 {GBM_FORMAT_YVU420, 3, {{8, 1}, {8, 2}, {8,2}}}, 163 }; 164 165 static const uint32_t usage_list[] = { 166 GBM_BO_USE_SCANOUT, 167 GBM_BO_USE_CURSOR_64X64, 168 GBM_BO_USE_RENDERING, 169 GBM_BO_USE_LINEAR, 170 GBM_BO_USE_SW_READ_OFTEN, 171 GBM_BO_USE_SW_READ_RARELY, 172 GBM_BO_USE_SW_WRITE_OFTEN, 173 GBM_BO_USE_SW_WRITE_RARELY, 174 }; 175 176 static const uint32_t buffer_list[] = { 177 GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY, 178 GBM_BO_USE_RENDERING | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY, 179 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY, 180 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING, 181 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING, 182 183 GBM_BO_USE_RENDERING | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY | 184 GBM_BO_USE_TEXTURING, 185 186 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY | 187 GBM_BO_USE_SW_WRITE_RARELY, 188 189 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_SW_READ_RARELY | 190 GBM_BO_USE_SW_WRITE_RARELY | GBM_BO_USE_TEXTURING, 191 }; 192 193 static int check_bo(struct gbm_bo *bo) 194 { 195 uint32_t format; 196 size_t num_planes, plane; 197 int fd; 198 int i; 199 200 CHECK(bo); 201 CHECK(gbm_bo_get_width(bo) >= 0); 202 CHECK(gbm_bo_get_height(bo) >= 0); 203 CHECK(gbm_bo_get_stride(bo) >= gbm_bo_get_width(bo)); 204 205 format = gbm_bo_get_format(bo); 206 for (i = 0; i < ARRAY_SIZE(format_list); i++) 207 if (format_list[i] == format) 208 break; 209 CHECK(i < ARRAY_SIZE(format_list)); 210 211 num_planes = gbm_bo_get_num_planes(bo); 212 if (format == GBM_FORMAT_NV12) 213 CHECK(num_planes == 2); 214 else if (format == GBM_FORMAT_YVU420) 215 CHECK(num_planes == 3); 216 else 217 CHECK(num_planes == 1); 218 219 CHECK(gbm_bo_get_plane_handle(bo, 0).u32 == gbm_bo_get_handle(bo).u32); 220 221 CHECK(gbm_bo_get_plane_offset(bo, 0) == 0); 222 CHECK(gbm_bo_get_plane_size(bo, 0) >= 223 gbm_bo_get_width(bo) * gbm_bo_get_height(bo)); 224 CHECK(gbm_bo_get_plane_stride(bo, 0) == gbm_bo_get_stride(bo)); 225 226 for (plane = 0; plane < num_planes; plane++) { 227 CHECK(gbm_bo_get_plane_handle(bo, plane).u32); 228 229 fd = gbm_bo_get_plane_fd(bo, plane); 230 CHECK(fd > 0); 231 close(fd); 232 233 gbm_bo_get_plane_offset(bo, plane); 234 CHECK(gbm_bo_get_plane_size(bo, plane)); 235 CHECK(gbm_bo_get_plane_stride(bo, plane)); 236 } 237 238 return 1; 239 } 240 241 static drmModeConnector *find_first_connected_connector(int fd, 242 drmModeRes *resources) 243 { 244 int i; 245 for (i = 0; i < resources->count_connectors; i++) { 246 drmModeConnector *connector; 247 248 connector = drmModeGetConnector(fd, resources->connectors[i]); 249 if (connector) { 250 if ((connector->count_modes > 0) && 251 (connector->connection == DRM_MODE_CONNECTED)) 252 return connector; 253 254 drmModeFreeConnector(connector); 255 } 256 } 257 return NULL; 258 } 259 260 static int drm_open() 261 { 262 int fd; 263 unsigned i; 264 bool has_drm_device = false; 265 266 for (i = 0; i < DRM_MAX_MINOR; i++) { 267 char* dev_name; 268 drmModeRes *res = NULL; 269 int ret; 270 271 ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i); 272 if (ret < 0) 273 continue; 274 275 fd = open(dev_name, O_RDWR, 0); 276 free(dev_name); 277 if (fd < 0) 278 continue; 279 280 res = drmModeGetResources(fd); 281 if (!res) { 282 drmClose(fd); 283 continue; 284 } 285 286 if (res->count_crtcs > 0 && res->count_connectors > 0) { 287 has_drm_device = true; 288 if (find_first_connected_connector(fd, res)) { 289 drmModeFreeResources(res); 290 return fd; 291 } 292 } 293 294 drmClose(fd); 295 drmModeFreeResources(res); 296 } 297 298 if (has_drm_device) 299 return ENODISPLAY; 300 else 301 return ENODRM; 302 } 303 304 static int drm_open_vgem() 305 { 306 const char g_sys_card_path_format[] = 307 "/sys/bus/platform/devices/vgem/drm/card%d"; 308 const char g_dev_card_path_format[] = 309 "/dev/dri/card%d"; 310 char *name; 311 int i, fd; 312 313 for (i = 0; i < 16; i++) { 314 struct stat _stat; 315 int ret; 316 ret = asprintf(&name, g_sys_card_path_format, i); 317 assert(ret != -1); 318 319 if (stat(name, &_stat) == -1) { 320 free(name); 321 continue; 322 } 323 324 free(name); 325 ret = asprintf(&name, g_dev_card_path_format, i); 326 assert(ret != -1); 327 328 fd = open(name, O_RDWR); 329 free(name); 330 if (fd == -1) { 331 return -1; 332 } 333 return fd; 334 } 335 return -1; 336 } 337 338 static int create_vgem_bo(int fd, size_t size, uint32_t * handle) 339 { 340 struct drm_mode_create_dumb create; 341 int ret; 342 343 memset(&create, 0, sizeof(create)); 344 create.height = size; 345 create.width = 1; 346 create.bpp = 8; 347 348 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); 349 if (ret) 350 return ret; 351 352 assert(create.size >= size); 353 354 *handle = create.handle; 355 356 return 0; 357 } 358 359 /* 360 * Tests initialization. 361 */ 362 static int test_init() 363 { 364 fd = drm_open(); 365 if (fd == ENODISPLAY) 366 return ENODISPLAY; 367 CHECK(fd >= 0); 368 369 gbm = gbm_create_device(fd); 370 371 CHECK(gbm_device_get_fd(gbm) == fd); 372 373 const char* backend_name = gbm_device_get_backend_name(gbm); 374 375 CHECK(backend_name); 376 377 return 1; 378 } 379 380 /* 381 * Tests reinitialization. 382 */ 383 static int test_reinit() 384 { 385 gbm_device_destroy(gbm); 386 close(fd); 387 388 fd = drm_open(); 389 CHECK(fd >= 0); 390 391 gbm = gbm_create_device(fd); 392 393 CHECK(gbm_device_get_fd(gbm) == fd); 394 395 struct gbm_bo *bo; 396 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 397 CHECK(check_bo(bo)); 398 gbm_bo_destroy(bo); 399 400 return 1; 401 } 402 403 /* 404 * Tests repeated alloc/free. 405 */ 406 static int test_alloc_free() 407 { 408 int i; 409 for(i = 0; i < 1000; i++) { 410 struct gbm_bo *bo; 411 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 412 CHECK(check_bo(bo)); 413 gbm_bo_destroy(bo); 414 } 415 return 1; 416 } 417 418 /* 419 * Tests that we can allocate different buffer dimensions. 420 */ 421 static int test_alloc_free_sizes() 422 { 423 int i; 424 for(i = 1; i < 1920; i++) { 425 struct gbm_bo *bo; 426 bo = gbm_bo_create(gbm, i, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 427 CHECK(check_bo(bo)); 428 gbm_bo_destroy(bo); 429 } 430 431 for(i = 1; i < 1920; i++) { 432 struct gbm_bo *bo; 433 bo = gbm_bo_create(gbm, i, 1, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 434 CHECK(check_bo(bo)); 435 gbm_bo_destroy(bo); 436 } 437 438 for(i = 1; i < 1920; i++) { 439 struct gbm_bo *bo; 440 bo = gbm_bo_create(gbm, 1, i, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 441 CHECK(check_bo(bo)); 442 gbm_bo_destroy(bo); 443 } 444 445 return 1; 446 } 447 448 /* 449 * Tests that we can allocate different buffer formats. 450 */ 451 static int test_alloc_free_formats() 452 { 453 int i; 454 455 for(i = 0; i < ARRAY_SIZE(format_list); i++) { 456 uint32_t format = format_list[i]; 457 if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) { 458 struct gbm_bo *bo; 459 bo = gbm_bo_create(gbm, 1024, 1024, format, GBM_BO_USE_RENDERING); 460 CHECK(check_bo(bo)); 461 gbm_bo_destroy(bo); 462 } 463 } 464 465 return 1; 466 } 467 468 /* 469 * Tests that we find at least one working format for each usage. 470 */ 471 static int test_alloc_free_usage() 472 { 473 int i, j; 474 475 for(i = 0; i < ARRAY_SIZE(usage_list); i++) { 476 uint32_t usage = usage_list[i]; 477 int found = 0; 478 for(j = 0; j < ARRAY_SIZE(format_list); j++) { 479 uint32_t format = format_list[j]; 480 if (gbm_device_is_format_supported(gbm, format, usage)) { 481 struct gbm_bo *bo; 482 if (usage == GBM_BO_USE_CURSOR_64X64) 483 bo = gbm_bo_create(gbm, 64, 64, format, usage); 484 else 485 bo = gbm_bo_create(gbm, 1024, 1024, format, usage); 486 CHECK(check_bo(bo)); 487 found = 1; 488 gbm_bo_destroy(bo); 489 } 490 } 491 CHECK(found); 492 } 493 494 return 1; 495 } 496 497 /* 498 * Tests user data. 499 */ 500 static int been_there1; 501 static int been_there2; 502 503 void destroy_data1(struct gbm_bo *bo, void *data) 504 { 505 been_there1 = 1; 506 } 507 508 void destroy_data2(struct gbm_bo *bo, void *data) 509 { 510 been_there2 = 1; 511 } 512 513 static int test_user_data() 514 { 515 struct gbm_bo *bo1, *bo2; 516 char *data1, *data2; 517 518 been_there1 = 0; 519 been_there2 = 0; 520 521 bo1 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 522 bo2 = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 523 data1 = (char*)malloc(1); 524 data2 = (char*)malloc(1); 525 CHECK(data1); 526 CHECK(data2); 527 528 gbm_bo_set_user_data(bo1, data1, destroy_data1); 529 gbm_bo_set_user_data(bo2, data2, destroy_data2); 530 531 CHECK((char*)gbm_bo_get_user_data(bo1) == data1); 532 CHECK((char*)gbm_bo_get_user_data(bo2) == data2); 533 534 gbm_bo_destroy(bo1); 535 CHECK(been_there1 == 1); 536 537 gbm_bo_set_user_data(bo2, NULL, NULL); 538 gbm_bo_destroy(bo2); 539 CHECK(been_there2 == 0); 540 541 free(data1); 542 free(data2); 543 544 return 1; 545 } 546 547 /* 548 * Tests destruction. 549 */ 550 static int test_destroy() 551 { 552 gbm_device_destroy(gbm); 553 close(fd); 554 555 return 1; 556 } 557 558 /* 559 * Tests prime export. 560 */ 561 static int test_export() 562 { 563 struct gbm_bo *bo; 564 int prime_fd; 565 566 bo = gbm_bo_create(gbm, 1024, 1024, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 567 CHECK(check_bo(bo)); 568 569 prime_fd = gbm_bo_get_fd(bo); 570 CHECK(prime_fd > 0); 571 close(prime_fd); 572 573 gbm_bo_destroy(bo); 574 575 return 1; 576 } 577 578 /* 579 * Tests prime import using VGEM sharing buffer. 580 */ 581 static int test_import_vgem() 582 { 583 struct gbm_import_fd_data fd_data; 584 int vgem_fd = drm_open_vgem(); 585 struct drm_prime_handle prime_handle; 586 struct gbm_bo *bo; 587 const int width = 123; 588 const int height = 456; 589 const int bytes_per_pixel = 4; 590 const int size = width * height * bytes_per_pixel; 591 592 if (vgem_fd <= 0) 593 return 1; 594 595 CHECK(create_vgem_bo(vgem_fd, size, &prime_handle.handle) == 0); 596 prime_handle.flags = DRM_CLOEXEC; 597 CHECK(drmIoctl(vgem_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle) == 0); 598 599 fd_data.fd = prime_handle.fd; 600 fd_data.width = width; 601 fd_data.height = height; 602 fd_data.stride = width * bytes_per_pixel; 603 fd_data.format = GBM_FORMAT_XRGB8888; 604 605 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING); 606 CHECK(check_bo(bo)); 607 gbm_bo_destroy(bo); 608 close(prime_handle.fd); 609 610 close(vgem_fd); 611 612 return 1; 613 } 614 615 /* 616 * Tests prime import using dma-buf API. 617 */ 618 static int test_import_dmabuf() 619 { 620 struct gbm_import_fd_data fd_data; 621 struct gbm_bo *bo1, *bo2; 622 const int width = 123; 623 const int height = 456; 624 int prime_fd; 625 626 bo1 = gbm_bo_create(gbm, width, height, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); 627 CHECK(check_bo(bo1)); 628 629 prime_fd = gbm_bo_get_fd(bo1); 630 CHECK(prime_fd >= 0); 631 632 fd_data.fd = prime_fd; 633 fd_data.width = width; 634 fd_data.height = height; 635 fd_data.stride = gbm_bo_get_stride(bo1); 636 fd_data.format = GBM_FORMAT_XRGB8888; 637 638 gbm_bo_destroy(bo1); 639 640 bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &fd_data, GBM_BO_USE_RENDERING); 641 CHECK(check_bo(bo2)); 642 CHECK(fd_data.width == gbm_bo_get_width(bo2)); 643 CHECK(fd_data.height == gbm_bo_get_height(bo2)); 644 CHECK(fd_data.stride == gbm_bo_get_stride(bo2)); 645 646 gbm_bo_destroy(bo2); 647 close(prime_fd); 648 649 return 1; 650 } 651 652 653 /* 654 * Tests GBM_BO_IMPORT_FD_PLANAR entry point. 655 */ 656 static int test_import_planar() 657 { 658 struct gbm_import_fd_planar_data fd_data; 659 struct gbm_bo *bo1, *bo2; 660 const int width = 567; 661 const int height = 891; 662 size_t num_planes, p; 663 int i; 664 665 for (i = 0; i < ARRAY_SIZE(format_list); i++) { 666 uint32_t format = format_list[i]; 667 if (gbm_device_is_format_supported(gbm, format, GBM_BO_USE_RENDERING)) { 668 bo1 = gbm_bo_create(gbm, width, height, format, GBM_BO_USE_RENDERING); 669 CHECK(check_bo(bo1)); 670 671 num_planes = gbm_bo_get_num_planes(bo1); 672 for (p = 0; p < num_planes; p++) { 673 fd_data.fds[p] = gbm_bo_get_plane_fd(bo1, p); 674 CHECK(fd_data.fds[p] >= 0); 675 676 fd_data.strides[p] = gbm_bo_get_plane_stride(bo1, p); 677 fd_data.offsets[p] = gbm_bo_get_plane_offset(bo1, p); 678 fd_data.format_modifiers[p] = 679 gbm_bo_get_plane_format_modifier(bo1, p); 680 } 681 682 fd_data.width = width; 683 fd_data.height = height; 684 fd_data.format = format; 685 686 gbm_bo_destroy(bo1); 687 688 bo2 = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_PLANAR, &fd_data, 689 GBM_BO_USE_RENDERING); 690 691 CHECK(check_bo(bo2)); 692 CHECK(fd_data.width == gbm_bo_get_width(bo2)); 693 CHECK(fd_data.height == gbm_bo_get_height(bo2)); 694 695 for (p = 0; p < num_planes; p++) { 696 CHECK(fd_data.strides[p] == gbm_bo_get_plane_stride(bo2, p)); 697 CHECK(fd_data.offsets[p] == gbm_bo_get_plane_offset(bo2, p)); 698 CHECK(fd_data.format_modifiers[p] == 699 gbm_bo_get_plane_format_modifier(bo2, p)); 700 } 701 702 gbm_bo_destroy(bo2); 703 704 for (p = 0; p < num_planes; p++) 705 close(fd_data.fds[p]); 706 } 707 } 708 709 return 1; 710 } 711 712 static int test_gem_map() 713 { 714 uint32_t *pixel, pixel_size; 715 struct gbm_bo *bo; 716 void *map_data, *addr; 717 718 uint32_t stride = 0; 719 const int width = 666; 720 const int height = 777; 721 722 addr = map_data = NULL; 723 724 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, 725 GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY); 726 CHECK(check_bo(bo)); 727 728 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride, 729 &map_data, 0); 730 731 CHECK(addr != MAP_FAILED); 732 CHECK(map_data); 733 CHECK(stride > 0); 734 735 pixel = (uint32_t *)addr; 736 pixel_size = sizeof(*pixel); 737 738 pixel[(height / 2) * (stride / pixel_size) + width / 2] = 0xABBAABBA; 739 gbm_bo_unmap(bo, map_data); 740 741 /* Re-map and verify written previously data. */ 742 stride = 0; 743 addr = map_data = NULL; 744 745 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ_WRITE, &stride, 746 &map_data, 0); 747 748 CHECK(addr != MAP_FAILED); 749 CHECK(map_data); 750 CHECK(stride > 0); 751 752 pixel = (uint32_t *)addr; 753 CHECK(pixel[(height / 2) * (stride / pixel_size) + width / 2] == 0xABBAABBA); 754 755 gbm_bo_unmap(bo, map_data); 756 gbm_bo_destroy(bo); 757 758 return 1; 759 } 760 761 static int test_dmabuf_map() 762 { 763 uint32_t *pixel; 764 struct gbm_bo *bo; 765 void *addr, *map_data; 766 const int width = 666; 767 const int height = 777; 768 int x, y, ret, prime_fd; 769 struct dma_buf_sync sync_end = { 0 }; 770 struct dma_buf_sync sync_start = { 0 }; 771 uint32_t pixel_size, stride, stride_pixels, length; 772 773 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, GBM_BO_USE_LINEAR); 774 CHECK(check_bo(bo)); 775 776 prime_fd = gbm_bo_get_fd(bo); 777 CHECK(prime_fd > 0); 778 779 stride = gbm_bo_get_stride(bo); 780 length = gbm_bo_get_plane_size(bo, 0); 781 CHECK(stride > 0); 782 CHECK(length > 0); 783 784 addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0); 785 CHECK(addr != MAP_FAILED); 786 787 pixel = (uint32_t *)addr; 788 pixel_size = sizeof(*pixel); 789 stride_pixels = stride / pixel_size; 790 791 sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE; 792 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start)); 793 CHECK(ret == 0); 794 795 for (y = 0; y < height; ++y) 796 for (x = 0; x < width; ++x) 797 pixel[y * stride_pixels + x] = ((y << 16) | x); 798 799 sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE; 800 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end)); 801 CHECK(ret == 0); 802 803 ret = munmap(addr, length); 804 CHECK(ret == 0); 805 806 ret = close(prime_fd); 807 CHECK(ret == 0); 808 809 prime_fd = gbm_bo_get_fd(bo); 810 CHECK(prime_fd > 0); 811 812 addr = mmap(NULL, length, (PROT_READ | PROT_WRITE), MAP_SHARED, prime_fd, 0); 813 CHECK(addr != MAP_FAILED); 814 815 pixel = (uint32_t *)addr; 816 817 memset(&sync_start, 0, sizeof(sync_start)); 818 memset(&sync_end, 0, sizeof(sync_end)); 819 820 sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ; 821 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_start)); 822 CHECK(ret == 0); 823 824 for (y = 0; y < height; ++y) 825 for (x = 0; x < width; ++x) 826 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x)); 827 828 sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ; 829 ret = HANDLE_EINTR(ioctl(prime_fd, DMA_BUF_IOCTL_SYNC, &sync_end)); 830 CHECK(ret == 0); 831 832 ret = munmap(addr, length); 833 CHECK(ret == 0); 834 835 ret = close(prime_fd); 836 CHECK(ret == 0); 837 838 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride, 839 &map_data, 0); 840 841 CHECK(addr != MAP_FAILED); 842 CHECK(map_data); 843 CHECK(stride > 0); 844 845 pixel = (uint32_t *)addr; 846 847 for (y = 0; y < height; ++y) 848 for (x = 0; x < width; ++x) 849 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x)); 850 851 gbm_bo_unmap(bo, map_data); 852 gbm_bo_destroy(bo); 853 854 return 1; 855 } 856 857 static int test_gem_map_tiling(enum gbm_bo_flags buffer_create_flag) 858 { 859 uint32_t *pixel, pixel_size; 860 struct gbm_bo *bo; 861 void *map_data, *addr; 862 863 uint32_t stride = 0; 864 uint32_t stride_pixels = 0; 865 const int width = 666; 866 const int height = 777; 867 int x, y; 868 869 addr = map_data = NULL; 870 871 bo = gbm_bo_create(gbm, width, height, GBM_FORMAT_ARGB8888, buffer_create_flag); 872 CHECK(check_bo(bo)); 873 874 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_WRITE, &stride, 875 &map_data, 0); 876 877 CHECK(addr != MAP_FAILED); 878 CHECK(map_data); 879 CHECK(stride > 0); 880 881 pixel = (uint32_t *)addr; 882 pixel_size = sizeof(*pixel); 883 stride_pixels = stride / pixel_size; 884 885 for (y = 0; y < height; ++y) 886 for (x = 0; x < width; ++x) 887 pixel[y * stride_pixels + x] = ((y << 16) | x); 888 889 gbm_bo_unmap(bo, map_data); 890 891 /* Re-map and verify written previously data. */ 892 stride = 0; 893 addr = map_data = NULL; 894 895 addr = gbm_bo_map(bo, 0, 0, width, height, GBM_BO_TRANSFER_READ, &stride, 896 &map_data, 0); 897 898 CHECK(addr != MAP_FAILED); 899 CHECK(map_data); 900 CHECK(stride > 0); 901 902 pixel = (uint32_t *)addr; 903 pixel_size = sizeof(*pixel); 904 stride_pixels = stride / pixel_size; 905 906 for (y = 0; y < height; ++y) 907 for (x = 0; x < width; ++x) 908 CHECK(pixel[y * stride_pixels + x] == ((y << 16) | x)); 909 910 gbm_bo_unmap(bo, map_data); 911 gbm_bo_destroy(bo); 912 913 return 1; 914 } 915 916 917 static int test_gem_map_format(int format_index, 918 enum gbm_bo_flags buffer_create_flag) 919 { 920 uint8_t *pixel; 921 struct gbm_bo *bo; 922 void *map_data, *addr; 923 uint32_t x, y, p, w, h, b, planes, bytes_per_pixel, idx; 924 uint32_t stride = 0; 925 const int width = 333; 926 const int height = 444; 927 const uint32_t pixel_format = format_info_list[format_index].pixel_format; 928 929 addr = map_data = NULL; 930 if (!gbm_device_is_format_supported(gbm, pixel_format, buffer_create_flag)) 931 return 1; 932 933 bo = gbm_bo_create(gbm, width, height, pixel_format, buffer_create_flag); 934 CHECK(check_bo(bo)); 935 planes = gbm_bo_get_num_planes(bo); 936 CHECK(planes == format_info_list[format_index].num_planes); 937 938 for (p = 0; p < planes; ++p) { 939 w = width / format_info_list[format_index].planes[p].subsample_rate; 940 h = height / format_info_list[format_index].planes[p].subsample_rate; 941 addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_WRITE, &stride, 942 &map_data, p); 943 944 CHECK(addr != MAP_FAILED); 945 CHECK(map_data); 946 CHECK(stride > 0); 947 948 pixel = (uint8_t *)addr; 949 bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8; 950 for (y = 0; y < h; ++y) { 951 for (x = 0; x < w; ++x) { 952 idx = y * stride + x * bytes_per_pixel; 953 for (b = 0; b < bytes_per_pixel; ++b) 954 pixel[idx + b] = y ^ x ^ b; 955 } 956 } 957 gbm_bo_unmap(bo, map_data); 958 stride = 0; 959 addr = map_data = NULL; 960 } 961 962 /* Re-map and verify written previously data. */ 963 for (p = 0; p < planes; ++p) { 964 w = width / format_info_list[format_index].planes[p].subsample_rate; 965 h = height / format_info_list[format_index].planes[p].subsample_rate; 966 addr = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_READ, &stride, 967 &map_data, p); 968 969 CHECK(addr != MAP_FAILED); 970 CHECK(map_data); 971 CHECK(stride > 0); 972 973 pixel = (uint8_t *)addr; 974 bytes_per_pixel = format_info_list[format_index].planes[p].bits_per_pixel / 8; 975 for (y = 0; y < h; ++y) { 976 for (x = 0; x < w; ++x) { 977 idx = y * stride + x * bytes_per_pixel; 978 for (b = 0; b < bytes_per_pixel; ++b) 979 CHECK(pixel[idx + b] == (uint8_t)(y ^ x ^ b)); 980 } 981 } 982 gbm_bo_unmap(bo, map_data); 983 stride = 0; 984 addr = map_data = NULL; 985 } 986 987 gbm_bo_destroy(bo); 988 return 1; 989 } 990 991 992 int main(int argc, char *argv[]) 993 { 994 int result, i, j; 995 996 result = test_init(); 997 if (result == ENODISPLAY) { 998 printf("[ PASSED ] graphics_Gbm test no connected display found\n"); 999 return EXIT_SUCCESS; 1000 } else if (!result) { 1001 printf("[ FAILED ] graphics_Gbm test initialization failed\n"); 1002 return EXIT_FAILURE; 1003 } 1004 1005 result &= test_reinit(); 1006 result &= test_alloc_free(); 1007 result &= test_alloc_free_sizes(); 1008 result &= test_alloc_free_formats(); 1009 result &= test_alloc_free_usage(); 1010 result &= test_user_data(); 1011 result &= test_export(); 1012 result &= test_import_vgem(); 1013 result &= test_import_dmabuf(); 1014 result &= test_import_planar(); 1015 result &= test_gem_map(); 1016 1017 // TODO(crbug.com/752669) 1018 if (strcmp(gbm_device_get_backend_name(gbm), "tegra")) { 1019 for (i = 0; i < ARRAY_SIZE(buffer_list); ++i) { 1020 result &= test_gem_map_tiling(buffer_list[i]); 1021 for (j = 0; j < ARRAY_SIZE(format_info_list); ++j) 1022 result &= test_gem_map_format(j, buffer_list[i]); 1023 } 1024 1025 result &= test_dmabuf_map(); 1026 } 1027 result &= test_destroy(); 1028 1029 if (!result) { 1030 printf("[ FAILED ] graphics_Gbm test failed\n"); 1031 return EXIT_FAILURE; 1032 } else { 1033 printf("[ PASSED ] graphics_Gbm test success\n"); 1034 return EXIT_SUCCESS; 1035 } 1036 } 1037