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