exynos_fimg2d_test.c 20 KB

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