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