exynos_fimg2d_test.c revision d8807b2f
1/* 2 * Copyright (C) 2013 Samsung Electronics Co.Ltd 3 * Authors: 4 * Inki Dae <inki.dae@samsung.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 * 11 */ 12 13#ifdef HAVE_CONFIG_H 14#include "config.h" 15#endif 16 17#include <stdlib.h> 18#include <stdio.h> 19#include <string.h> 20#include <errno.h> 21#include <time.h> 22#include <unistd.h> 23 24#include <sys/mman.h> 25#include <linux/stddef.h> 26 27#include <xf86drm.h> 28#include <xf86drmMode.h> 29#include <libkms.h> 30#include <drm_fourcc.h> 31 32#include "exynos_drm.h" 33#include "exynos_drmif.h" 34#include "exynos_fimg2d.h" 35 36#define DRM_MODULE_NAME "exynos" 37 38static unsigned int screen_width, screen_height; 39 40struct connector { 41 uint32_t id; 42 char mode_str[64]; 43 drmModeModeInfo *mode; 44 drmModeEncoder *encoder; 45 int crtc; 46}; 47 48static void connector_find_mode(int fd, struct connector *c, 49 drmModeRes *resources) 50{ 51 drmModeConnector *connector; 52 int i, j; 53 54 /* First, find the connector & mode */ 55 c->mode = NULL; 56 for (i = 0; i < resources->count_connectors; i++) { 57 connector = drmModeGetConnector(fd, resources->connectors[i]); 58 59 if (!connector) { 60 fprintf(stderr, "could not get connector %i: %s\n", 61 resources->connectors[i], strerror(errno)); 62 continue; 63 } 64 65 if (!connector->count_modes) { 66 drmModeFreeConnector(connector); 67 continue; 68 } 69 70 if (connector->connector_id != c->id) { 71 drmModeFreeConnector(connector); 72 continue; 73 } 74 75 for (j = 0; j < connector->count_modes; j++) { 76 c->mode = &connector->modes[j]; 77 if (!strcmp(c->mode->name, c->mode_str)) 78 break; 79 } 80 81 /* Found it, break out */ 82 if (c->mode) 83 break; 84 85 drmModeFreeConnector(connector); 86 } 87 88 if (!c->mode) { 89 fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str); 90 return; 91 } 92 93 /* Now get the encoder */ 94 for (i = 0; i < resources->count_encoders; i++) { 95 c->encoder = drmModeGetEncoder(fd, resources->encoders[i]); 96 97 if (!c->encoder) { 98 fprintf(stderr, "could not get encoder %i: %s\n", 99 resources->encoders[i], strerror(errno)); 100 continue; 101 } 102 103 if (c->encoder->encoder_id == connector->encoder_id) 104 break; 105 106 drmModeFreeEncoder(c->encoder); 107 } 108 109 if (c->crtc == -1) 110 c->crtc = c->encoder->crtc_id; 111} 112 113static int drm_set_crtc(struct exynos_device *dev, struct connector *c, 114 unsigned int fb_id) 115{ 116 int ret; 117 118 ret = drmModeSetCrtc(dev->fd, c->crtc, 119 fb_id, 0, 0, &c->id, 1, c->mode); 120 if (ret) 121 drmMsg("failed to set mode: %s\n", strerror(errno)); 122 123 return ret; 124} 125 126static struct exynos_bo *exynos_create_buffer(struct exynos_device *dev, 127 unsigned long size, 128 unsigned int flags) 129{ 130 struct exynos_bo *bo; 131 132 bo = exynos_bo_create(dev, size, flags); 133 if (!bo) 134 return bo; 135 136 if (!exynos_bo_map(bo)) { 137 exynos_bo_destroy(bo); 138 return NULL; 139 } 140 141 return bo; 142} 143 144/* Allocate buffer and fill it with checkerboard pattern, where the tiles * 145 * have a random color. The caller has to free the buffer. */ 146static void *create_checkerboard_pattern(unsigned int num_tiles_x, 147 unsigned int num_tiles_y, unsigned int tile_size) 148{ 149 unsigned int *buf; 150 unsigned int x, y, i, j; 151 const unsigned int stride = num_tiles_x * tile_size; 152 153 if (posix_memalign((void*)&buf, 64, num_tiles_y * tile_size * stride * 4) != 0) 154 return NULL; 155 156 for (x = 0; x < num_tiles_x; ++x) { 157 for (y = 0; y < num_tiles_y; ++y) { 158 const unsigned int color = 0xff000000 + (random() & 0xffffff); 159 160 for (i = 0; i < tile_size; ++i) { 161 for (j = 0; j < tile_size; ++j) { 162 buf[x * tile_size + y * stride * tile_size + i + j * stride] = color; 163 } 164 } 165 } 166 } 167 168 return buf; 169} 170 171static void exynos_destroy_buffer(struct exynos_bo *bo) 172{ 173 exynos_bo_destroy(bo); 174} 175 176static void wait_for_user_input(int last) 177{ 178 printf("press <ENTER> to %s\n", last ? "exit test application" : 179 "skip to next test"); 180 181 getchar(); 182} 183 184static int g2d_solid_fill_test(struct exynos_device *dev, struct exynos_bo *dst) 185{ 186 struct g2d_context *ctx; 187 struct g2d_image img = {0}; 188 unsigned int count, img_w, img_h; 189 int ret = 0; 190 191 ctx = g2d_init(dev->fd); 192 if (!ctx) 193 return -EFAULT; 194 195 img.bo[0] = dst->handle; 196 197 printf("solid fill test.\n"); 198 199 srand(time(NULL)); 200 img_w = screen_width; 201 img_h = screen_height; 202 203 for (count = 0; count < 2; count++) { 204 unsigned int x, y, w, h; 205 206 x = rand() % (img_w / 2); 207 y = rand() % (img_h / 2); 208 w = rand() % (img_w - x); 209 h = rand() % (img_h - y); 210 211 img.width = img_w; 212 img.height = img_h; 213 img.stride = img.width * 4; 214 img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 215 img.color = 0xff000000 + (random() & 0xffffff); 216 217 ret = g2d_solid_fill(ctx, &img, x, y, w, h); 218 if (ret < 0) 219 goto err_fini; 220 221 ret = g2d_exec(ctx); 222 if (ret < 0) 223 break; 224 } 225 226err_fini: 227 g2d_fini(ctx); 228 229 return ret; 230} 231 232static int g2d_copy_test(struct exynos_device *dev, struct exynos_bo *src, 233 struct exynos_bo *dst, 234 enum e_g2d_buf_type type) 235{ 236 struct g2d_context *ctx; 237 struct g2d_image src_img = {0}, dst_img = {0}; 238 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h; 239 unsigned long userptr, size; 240 int ret; 241 242 ctx = g2d_init(dev->fd); 243 if (!ctx) 244 return -EFAULT; 245 246 dst_img.bo[0] = dst->handle; 247 248 src_x = 0; 249 src_y = 0; 250 dst_x = 0; 251 dst_y = 0; 252 img_w = screen_width; 253 img_h = screen_height; 254 255 switch (type) { 256 case G2D_IMGBUF_GEM: 257 src_img.bo[0] = src->handle; 258 break; 259 case G2D_IMGBUF_USERPTR: 260 size = img_w * img_h * 4; 261 262 userptr = (unsigned long)malloc(size); 263 if (!userptr) { 264 fprintf(stderr, "failed to allocate userptr.\n"); 265 ret = -EFAULT; 266 goto fail; 267 } 268 269 src_img.user_ptr[0].userptr = userptr; 270 src_img.user_ptr[0].size = size; 271 break; 272 case G2D_IMGBUF_COLOR: 273 default: 274 ret = -EFAULT; 275 goto fail; 276 } 277 278 printf("copy test with %s.\n", 279 type == G2D_IMGBUF_GEM ? "gem" : "userptr"); 280 281 src_img.width = img_w; 282 src_img.height = img_h; 283 src_img.stride = src_img.width * 4; 284 src_img.buf_type = type; 285 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 286 src_img.color = 0xffff0000; 287 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h); 288 if (ret < 0) 289 goto err_free_userptr; 290 291 dst_img.width = img_w; 292 dst_img.height = img_h; 293 dst_img.stride = dst_img.width * 4; 294 dst_img.buf_type = G2D_IMGBUF_GEM; 295 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 296 297 ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y, 298 img_w - 4, img_h - 4); 299 if (ret < 0) 300 goto err_free_userptr; 301 302 g2d_exec(ctx); 303 304err_free_userptr: 305 if (type == G2D_IMGBUF_USERPTR) 306 if (userptr) 307 free((void *)userptr); 308 309fail: 310 g2d_fini(ctx); 311 312 return ret; 313} 314 315static int g2d_move_test(struct exynos_device *dev, 316 struct exynos_bo *tmp, 317 struct exynos_bo *buf, 318 enum e_g2d_buf_type type) 319{ 320 struct g2d_context *ctx; 321 struct g2d_image img = {0}, tmp_img = {0}; 322 unsigned int img_w, img_h, count; 323 int cur_x, cur_y; 324 void *checkerboard; 325 int ret; 326 327 static const struct g2d_step { 328 int x, y; 329 } steps[] = { 330 { 1, 0}, { 0, 1}, 331 {-1, 0}, { 0, -1}, 332 { 1, 1}, {-1, -1}, 333 { 1, -1}, {-1, 1}, 334 { 2, 1}, { 1, 2}, 335 {-2, -1}, {-1, -2}, 336 { 2, -1}, { 1, -2}, 337 {-2, 1}, {-1, 2} 338 }; 339 static const unsigned int num_steps = 340 sizeof(steps) / sizeof(struct g2d_step); 341 342 ctx = g2d_init(dev->fd); 343 if (!ctx) 344 return -EFAULT; 345 346 img.bo[0] = buf->handle; 347 348 /* create pattern of half the screen size */ 349 checkerboard = create_checkerboard_pattern(screen_width / 64, screen_height / 64, 32); 350 if (!checkerboard) { 351 ret = -EFAULT; 352 goto fail; 353 } 354 355 img_w = (screen_width / 64) * 32; 356 img_h = (screen_height / 64) * 32; 357 358 switch (type) { 359 case G2D_IMGBUF_GEM: 360 memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4); 361 tmp_img.bo[0] = tmp->handle; 362 break; 363 case G2D_IMGBUF_USERPTR: 364 tmp_img.user_ptr[0].userptr = (unsigned long)checkerboard; 365 tmp_img.user_ptr[0].size = img_w * img_h * 4; 366 break; 367 case G2D_IMGBUF_COLOR: 368 default: 369 ret = -EFAULT; 370 goto fail; 371 } 372 373 /* solid fill framebuffer with white color */ 374 img.width = screen_width; 375 img.height = screen_height; 376 img.stride = screen_width * 4; 377 img.buf_type = G2D_IMGBUF_GEM; 378 img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 379 img.color = 0xffffffff; 380 381 /* put checkerboard pattern in the center of the framebuffer */ 382 cur_x = (screen_width - img_w) / 2; 383 cur_y = (screen_height - img_h) / 2; 384 tmp_img.width = img_w; 385 tmp_img.height = img_h; 386 tmp_img.stride = img_w * 4; 387 tmp_img.buf_type = type; 388 tmp_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 389 390 ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width, screen_height) || 391 g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y, img_w, img_h); 392 393 if (!ret) 394 ret = g2d_exec(ctx); 395 if (ret < 0) 396 goto fail; 397 398 printf("move test with %s.\n", 399 type == G2D_IMGBUF_GEM ? "gem" : "userptr"); 400 401 srand(time(NULL)); 402 for (count = 0; count < 256; ++count) { 403 const struct g2d_step *s; 404 405 /* select step and validate it */ 406 while (1) { 407 s = &steps[random() % num_steps]; 408 409 if (cur_x + s->x < 0 || cur_y + s->y < 0 || 410 cur_x + img_w + s->x >= screen_width || 411 cur_y + img_h + s->y >= screen_height) 412 continue; 413 else 414 break; 415 } 416 417 ret = g2d_move(ctx, &img, cur_x, cur_y, cur_x + s->x, cur_y + s->y, 418 img_w, img_h); 419 if (!ret) 420 ret = g2d_exec(ctx); 421 422 if (ret < 0) 423 goto fail; 424 425 cur_x += s->x; 426 cur_y += s->y; 427 428 usleep(100000); 429 } 430 431fail: 432 g2d_fini(ctx); 433 434 free(checkerboard); 435 436 return ret; 437} 438 439static int g2d_copy_with_scale_test(struct exynos_device *dev, 440 struct exynos_bo *src, 441 struct exynos_bo *dst, 442 enum e_g2d_buf_type type) 443{ 444 struct g2d_context *ctx; 445 struct g2d_image src_img = {0}, dst_img = {0}; 446 unsigned int src_x, src_y, img_w, img_h; 447 unsigned long userptr, size; 448 int ret; 449 450 ctx = g2d_init(dev->fd); 451 if (!ctx) 452 return -EFAULT; 453 454 dst_img.bo[0] = dst->handle; 455 456 src_x = 0; 457 src_y = 0; 458 img_w = screen_width; 459 img_h = screen_height; 460 461 switch (type) { 462 case G2D_IMGBUF_GEM: 463 src_img.bo[0] = src->handle; 464 break; 465 case G2D_IMGBUF_USERPTR: 466 size = img_w * img_h * 4; 467 468 userptr = (unsigned long)malloc(size); 469 if (!userptr) { 470 fprintf(stderr, "failed to allocate userptr.\n"); 471 ret = -EFAULT; 472 goto fail; 473 } 474 475 src_img.user_ptr[0].userptr = userptr; 476 src_img.user_ptr[0].size = size; 477 break; 478 case G2D_IMGBUF_COLOR: 479 default: 480 ret = -EFAULT; 481 goto fail; 482 } 483 484 printf("copy and scale test with %s.\n", 485 type == G2D_IMGBUF_GEM ? "gem" : "userptr"); 486 487 src_img.width = img_w; 488 src_img.height = img_h; 489 src_img.stride = src_img.width * 4; 490 src_img.buf_type = type; 491 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 492 src_img.color = 0xffffffff; 493 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w , img_h); 494 if (ret < 0) 495 goto err_free_userptr; 496 497 src_img.color = 0xff00ff00; 498 ret = g2d_solid_fill(ctx, &src_img, 5, 5, 100, 100); 499 if (ret < 0) 500 goto err_free_userptr; 501 502 dst_img.width = img_w; 503 dst_img.height = img_h; 504 dst_img.buf_type = G2D_IMGBUF_GEM; 505 dst_img.stride = dst_img.width * 4; 506 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 507 508 ret = g2d_copy_with_scale(ctx, &src_img, &dst_img, 5, 5, 100, 100, 509 100, 100, 200, 200, 0); 510 if (ret < 0) 511 goto err_free_userptr; 512 513 g2d_exec(ctx); 514 515err_free_userptr: 516 if (type == G2D_IMGBUF_USERPTR) 517 if (userptr) 518 free((void *)userptr); 519 520fail: 521 g2d_fini(ctx); 522 523 return ret;; 524} 525 526#if EXYNOS_G2D_USERPTR_TEST 527static int g2d_blend_test(struct exynos_device *dev, 528 struct exynos_bo *src, 529 struct exynos_bo *dst, 530 enum e_g2d_buf_type type) 531{ 532 struct g2d_context *ctx; 533 struct g2d_image src_img = {0}, dst_img = {0}; 534 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h; 535 unsigned long userptr, size; 536 int ret; 537 538 ctx = g2d_init(dev->fd); 539 if (!ctx) 540 return -EFAULT; 541 542 dst_img.bo[0] = dst->handle; 543 544 src_x = 0; 545 src_y = 0; 546 dst_x = 0; 547 dst_y = 0; 548 img_w = screen_width; 549 img_h = screen_height; 550 551 switch (type) { 552 case G2D_IMGBUF_GEM: 553 src_img.bo[0] = src->handle; 554 break; 555 case G2D_IMGBUF_USERPTR: 556 size = img_w * img_h * 4; 557 558 userptr = (unsigned long)malloc(size); 559 if (!userptr) { 560 fprintf(stderr, "failed to allocate userptr.\n"); 561 ret = -EFAULT; 562 goto fail; 563 } 564 565 src_img.user_ptr[0].userptr = userptr; 566 src_img.user_ptr[0].size = size; 567 break; 568 case G2D_IMGBUF_COLOR: 569 default: 570 ret = -EFAULT; 571 goto fail; 572 } 573 574 printf("blend test with %s.\n", 575 type == G2D_IMGBUF_GEM ? "gem" : "userptr"); 576 577 src_img.width = img_w; 578 src_img.height = img_h; 579 src_img.stride = src_img.width * 4; 580 src_img.buf_type = type; 581 src_img.select_mode = G2D_SELECT_MODE_NORMAL; 582 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 583 src_img.color = 0xffffffff; 584 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h); 585 if (ret < 0) 586 goto err_free_userptr; 587 588 src_img.color = 0x770000ff; 589 ret = g2d_solid_fill(ctx, &src_img, 5, 5, 200, 200); 590 if (ret < 0) 591 goto err_free_userptr; 592 593 dst_img.width = img_w; 594 dst_img.height = img_h; 595 dst_img.stride = dst_img.width * 4; 596 dst_img.buf_type = G2D_IMGBUF_GEM; 597 dst_img.select_mode = G2D_SELECT_MODE_NORMAL; 598 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 599 dst_img.color = 0xffffffff; 600 ret = g2d_solid_fill(ctx, &dst_img, dst_x, dst_y, img_w, img_h); 601 if (ret < 0) 602 goto err_free_userptr; 603 604 dst_img.color = 0x77ff0000; 605 ret = g2d_solid_fill(ctx, &dst_img, 105, 105, 200, 200); 606 if (ret < 0) 607 goto err_free_userptr; 608 609 ret = g2d_blend(ctx, &src_img, &dst_img, 5, 5, 105, 105, 200, 200, 610 G2D_OP_OVER); 611 if (ret < 0) 612 goto err_free_userptr; 613 614 g2d_exec(ctx); 615 616err_free_userptr: 617 if (type == G2D_IMGBUF_USERPTR) 618 if (userptr) 619 free((void *)userptr); 620 621fail: 622 g2d_fini(ctx); 623 624 return ret; 625} 626#endif 627 628static int g2d_checkerboard_test(struct exynos_device *dev, 629 struct exynos_bo *src, 630 struct exynos_bo *dst, 631 enum e_g2d_buf_type type) 632{ 633 struct g2d_context *ctx; 634 struct g2d_image src_img = {0}, dst_img = {0}; 635 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h; 636 void *checkerboard = NULL; 637 int ret; 638 639 ctx = g2d_init(dev->fd); 640 if (!ctx) 641 return -EFAULT; 642 643 dst_img.bo[0] = dst->handle; 644 645 src_x = 0; 646 src_y = 0; 647 dst_x = 0; 648 dst_y = 0; 649 650 checkerboard = create_checkerboard_pattern(screen_width / 32, screen_height / 32, 32); 651 if (!checkerboard) { 652 ret = -EFAULT; 653 goto fail; 654 } 655 656 img_w = screen_width - (screen_width % 32); 657 img_h = screen_height - (screen_height % 32); 658 659 switch (type) { 660 case G2D_IMGBUF_GEM: 661 memcpy(src->vaddr, checkerboard, img_w * img_h * 4); 662 src_img.bo[0] = src->handle; 663 break; 664 case G2D_IMGBUF_USERPTR: 665 src_img.user_ptr[0].userptr = (unsigned long)checkerboard; 666 src_img.user_ptr[0].size = img_w * img_h * 4; 667 break; 668 case G2D_IMGBUF_COLOR: 669 default: 670 ret = -EFAULT; 671 goto fail; 672 } 673 674 printf("checkerboard test with %s.\n", 675 type == G2D_IMGBUF_GEM ? "gem" : "userptr"); 676 677 src_img.width = img_w; 678 src_img.height = img_h; 679 src_img.stride = src_img.width * 4; 680 src_img.buf_type = type; 681 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 682 683 dst_img.width = screen_width; 684 dst_img.height = screen_height; 685 dst_img.stride = dst_img.width * 4; 686 dst_img.buf_type = G2D_IMGBUF_GEM; 687 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB; 688 src_img.color = 0xff000000; 689 ret = g2d_solid_fill(ctx, &dst_img, src_x, src_y, screen_width, screen_height); 690 if (ret < 0) 691 goto fail; 692 693 ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y, 694 img_w, img_h); 695 if (ret < 0) 696 goto fail; 697 698 g2d_exec(ctx); 699 700fail: 701 free(checkerboard); 702 g2d_fini(ctx); 703 704 return ret; 705} 706 707static void usage(char *name) 708{ 709 fprintf(stderr, "usage: %s [-s]\n", name); 710 fprintf(stderr, "-s <connector_id>@<crtc_id>:<mode>\n"); 711 exit(0); 712} 713 714extern char *optarg; 715static const char optstr[] = "s:"; 716 717int main(int argc, char **argv) 718{ 719 struct exynos_device *dev; 720 struct exynos_bo *bo, *src; 721 struct connector con; 722 unsigned int fb_id; 723 uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; 724 drmModeRes *resources; 725 int ret, fd, c; 726 727 memset(&con, 0, sizeof(struct connector)); 728 729 if (argc != 3) { 730 usage(argv[0]); 731 return -EINVAL; 732 } 733 734 while ((c = getopt(argc, argv, optstr)) != -1) { 735 switch (c) { 736 case 's': 737 con.crtc = -1; 738 if (sscanf(optarg, "%d:0x%64s", 739 &con.id, 740 con.mode_str) != 2 && 741 sscanf(optarg, "%d@%d:%64s", 742 &con.id, 743 &con.crtc, 744 con.mode_str) != 3) 745 usage(argv[0]); 746 break; 747 default: 748 usage(argv[0]); 749 break; 750 } 751 } 752 753 fd = drmOpen(DRM_MODULE_NAME, NULL); 754 if (fd < 0) { 755 fprintf(stderr, "failed to open.\n"); 756 return fd; 757 } 758 759 dev = exynos_device_create(fd); 760 if (!dev) { 761 ret = -EFAULT; 762 goto err_drm_close; 763 } 764 765 resources = drmModeGetResources(dev->fd); 766 if (!resources) { 767 fprintf(stderr, "drmModeGetResources failed: %s\n", 768 strerror(errno)); 769 ret = -EFAULT; 770 goto err_dev_destory; 771 } 772 773 connector_find_mode(dev->fd, &con, resources); 774 drmModeFreeResources(resources); 775 776 if (!con.mode) { 777 fprintf(stderr, "failed to find usable connector\n"); 778 ret = -EFAULT; 779 goto err_dev_destory; 780 } 781 782 screen_width = con.mode->hdisplay; 783 screen_height = con.mode->vdisplay; 784 785 if (screen_width == 0 || screen_height == 0) { 786 fprintf(stderr, "failed to find sane resolution on connector\n"); 787 ret = -EFAULT; 788 goto err_dev_destory; 789 } 790 791 printf("screen width = %d, screen height = %d\n", screen_width, 792 screen_height); 793 794 bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0); 795 if (!bo) { 796 ret = -EFAULT; 797 goto err_dev_destory; 798 } 799 800 handles[0] = bo->handle; 801 pitches[0] = screen_width * 4; 802 offsets[0] = 0; 803 804 ret = drmModeAddFB2(dev->fd, screen_width, screen_height, 805 DRM_FORMAT_XRGB8888, handles, 806 pitches, offsets, &fb_id, 0); 807 if (ret < 0) 808 goto err_destroy_buffer; 809 810 memset(bo->vaddr, 0xff, screen_width * screen_height * 4); 811 812 ret = drm_set_crtc(dev, &con, fb_id); 813 if (ret < 0) 814 goto err_rm_fb; 815 816 ret = g2d_solid_fill_test(dev, bo); 817 if (ret < 0) { 818 fprintf(stderr, "failed to solid fill operation.\n"); 819 goto err_rm_fb; 820 } 821 822 wait_for_user_input(0); 823 824 src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0); 825 if (!src) { 826 ret = -EFAULT; 827 goto err_rm_fb; 828 } 829 830 ret = g2d_copy_test(dev, src, bo, G2D_IMGBUF_GEM); 831 if (ret < 0) { 832 fprintf(stderr, "failed to test copy operation.\n"); 833 goto err_free_src; 834 } 835 836 wait_for_user_input(0); 837 838 ret = g2d_move_test(dev, src, bo, G2D_IMGBUF_GEM); 839 if (ret < 0) { 840 fprintf(stderr, "failed to test move operation.\n"); 841 goto err_free_src; 842 } 843 844 wait_for_user_input(0); 845 846 ret = g2d_copy_with_scale_test(dev, src, bo, G2D_IMGBUF_GEM); 847 if (ret < 0) { 848 fprintf(stderr, "failed to test copy and scale operation.\n"); 849 goto err_free_src; 850 } 851 852 wait_for_user_input(0); 853 854 ret = g2d_checkerboard_test(dev, src, bo, G2D_IMGBUF_GEM); 855 if (ret < 0) { 856 fprintf(stderr, "failed to issue checkerboard test.\n"); 857 goto err_free_src; 858 } 859 860 wait_for_user_input(1); 861 862 /* 863 * The blend test uses the userptr functionality of exynos-drm, which 864 * is currently not safe to use. If the kernel hasn't been build with 865 * exynos-iommu support, then the blend test is going to produce (kernel) 866 * memory corruption, eventually leading to a system crash. 867 * 868 * Disable the test for now, until the kernel code has been sanitized. 869 */ 870#if EXYNOS_G2D_USERPTR_TEST 871 ret = g2d_blend_test(dev, src, bo, G2D_IMGBUF_USERPTR); 872 if (ret < 0) 873 fprintf(stderr, "failed to test blend operation.\n"); 874 875 getchar(); 876#endif 877 878err_free_src: 879 if (src) 880 exynos_destroy_buffer(src); 881 882err_rm_fb: 883 drmModeRmFB(dev->fd, fb_id); 884 885err_destroy_buffer: 886 exynos_destroy_buffer(bo); 887 888err_dev_destory: 889 exynos_device_destroy(dev); 890 891err_drm_close: 892 drmClose(fd); 893 894 return ret; 895} 896