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