2 * Copyright (C) 2013 Samsung Electronics Co.Ltd
4 * Inki Dae <inki.dae@samsung.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
23 #include <linux/stddef.h>
26 #include <xf86drmMode.h>
28 #include <drm_fourcc.h>
30 #include "exynos_drm.h"
31 #include "exynos_drmif.h"
34 #define DRM_MODULE_NAME "exynos"
35 #define MAX_TEST_CASE 8
37 static unsigned int screen_width, screen_height;
40 * A structure to test fimg2d hw.
42 * @solid_fild: fill given color data to source buffer.
43 * @copy: copy source to destination buffer.
44 * @copy_with_scale: copy source to destination buffer scaling up or
46 * @blend: blend source to destination buffer.
48 struct fimg2d_test_case {
49 int (*solid_fill)(struct exynos_device *dev, struct exynos_bo *dst);
50 int (*copy)(struct exynos_device *dev, struct exynos_bo *src,
51 struct exynos_bo *dst, enum e_g2d_buf_type);
52 int (*copy_with_scale)(struct exynos_device *dev,
53 struct exynos_bo *src, struct exynos_bo *dst,
55 int (*blend)(struct exynos_device *dev,
56 struct exynos_bo *src, struct exynos_bo *dst,
65 drmModeModeInfo *mode;
66 drmModeEncoder *encoder;
70 unsigned int fb_id[2], current_fb_id;
76 static void connector_find_mode(int fd, struct connector *c,
77 drmModeRes *resources)
79 drmModeConnector *connector;
82 /* First, find the connector & mode */
84 for (i = 0; i < resources->count_connectors; i++) {
85 connector = drmModeGetConnector(fd, resources->connectors[i]);
88 fprintf(stderr, "could not get connector %i: %s\n",
89 resources->connectors[i], strerror(errno));
90 drmModeFreeConnector(connector);
94 if (!connector->count_modes) {
95 drmModeFreeConnector(connector);
99 if (connector->connector_id != c->id) {
100 drmModeFreeConnector(connector);
104 for (j = 0; j < connector->count_modes; j++) {
105 c->mode = &connector->modes[j];
106 if (!strcmp(c->mode->name, c->mode_str))
110 /* Found it, break out */
114 drmModeFreeConnector(connector);
118 fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
122 /* Now get the encoder */
123 for (i = 0; i < resources->count_encoders; i++) {
124 c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
127 fprintf(stderr, "could not get encoder %i: %s\n",
128 resources->encoders[i], strerror(errno));
129 drmModeFreeEncoder(c->encoder);
133 if (c->encoder->encoder_id == connector->encoder_id)
136 drmModeFreeEncoder(c->encoder);
140 c->crtc = c->encoder->crtc_id;
143 static int connector_find_plane(int fd, unsigned int *plane_id)
145 drmModePlaneRes *plane_resources;
149 plane_resources = drmModeGetPlaneResources(fd);
150 if (!plane_resources) {
151 fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
156 for (i = 0; i < plane_resources->count_planes; i++) {
159 ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
161 fprintf(stderr, "drmModeGetPlane failed: %s\n",
166 if (ovr->possible_crtcs & (1 << 0))
167 plane_id[i] = ovr->plane_id;
168 drmModeFreePlane(ovr);
174 static int drm_set_crtc(struct exynos_device *dev, struct connector *c,
179 ret = drmModeSetCrtc(dev->fd, c->crtc,
180 fb_id, 0, 0, &c->id, 1, c->mode);
182 drmMsg("failed to set mode: %s\n", strerror(errno));
192 static struct exynos_bo *exynos_create_buffer(struct exynos_device *dev,
196 struct exynos_bo *bo;
198 bo = exynos_bo_create(dev, size, flags);
202 if (!exynos_bo_map(bo)) {
203 exynos_bo_destroy(bo);
210 static void exynos_destroy_buffer(struct exynos_bo *bo)
212 exynos_bo_destroy(bo);
215 static int g2d_solid_fill_test(struct exynos_device *dev, struct exynos_bo *dst)
217 struct g2d_context *ctx;
218 struct g2d_image img;
219 unsigned int count, img_w, img_h;
222 ctx = g2d_init(dev->fd);
226 memset(&img, 0, sizeof(struct g2d_image));
227 img.bo[0] = dst->handle;
229 printf("soild fill test.\n");
232 img_w = screen_width;
233 img_h = screen_height;
235 for (count = 0; count < 2; count++) {
236 unsigned int x, y, w, h;
238 x = rand() % (img_w / 2);
239 y = rand() % (img_h / 2);
240 w = rand() % (img_w - x);
241 h = rand() % (img_h - y);
245 img.stride = img.width * 4;
246 img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
247 img.color = 0xff000000 + (random() & 0xffffff);
249 ret = g2d_solid_fill(ctx, &img, x, y, w, h);
264 static int g2d_copy_test(struct exynos_device *dev, struct exynos_bo *src,
265 struct exynos_bo *dst,
266 enum e_g2d_buf_type type)
268 struct g2d_context *ctx;
269 struct g2d_image src_img, dst_img;
271 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
272 unsigned long userptr, size;
275 ctx = g2d_init(dev->fd);
279 memset(&src_img, 0, sizeof(struct g2d_image));
280 memset(&dst_img, 0, sizeof(struct g2d_image));
281 dst_img.bo[0] = dst->handle;
287 img_w = screen_width;
288 img_h = screen_height;
292 src_img.bo[0] = src->handle;
294 case G2D_IMGBUF_USERPTR:
295 size = img_w * img_h * 4;
297 userptr = (unsigned long)malloc(size);
299 fprintf(stderr, "failed to allocate userptr.\n");
303 src_img.user_ptr[0].userptr = userptr;
304 src_img.user_ptr[0].size = size;
307 type = G2D_IMGBUF_GEM;
311 printf("copy test with %s.\n",
312 type == G2D_IMGBUF_GEM ? "gem" : "userptr");
314 src_img.width = img_w;
315 src_img.height = img_h;
316 src_img.stride = src_img.width * 4;
317 src_img.buf_type = type;
318 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
319 src_img.color = 0xffff0000;
320 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
322 goto err_free_userptr;
324 dst_img.width = img_w;
325 dst_img.height = img_h;
326 dst_img.stride = dst_img.width * 4;
327 dst_img.buf_type = G2D_IMGBUF_GEM;
328 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
330 ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y,
331 img_w - 4, img_h - 4);
333 goto err_free_userptr;
338 if (type == G2D_IMGBUF_USERPTR)
340 free((void *)userptr);
347 static int g2d_copy_with_scale_test(struct exynos_device *dev,
348 struct exynos_bo *src,
349 struct exynos_bo *dst,
350 enum e_g2d_buf_type type)
352 struct g2d_context *ctx;
353 struct g2d_image src_img, dst_img;
355 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
356 unsigned long userptr, size;
359 ctx = g2d_init(dev->fd);
363 memset(&src_img, 0, sizeof(struct g2d_image));
364 memset(&dst_img, 0, sizeof(struct g2d_image));
365 dst_img.bo[0] = dst->handle;
371 img_w = screen_width;
372 img_h = screen_height;
376 src_img.bo[0] = src->handle;
378 case G2D_IMGBUF_USERPTR:
379 size = img_w * img_h * 4;
381 userptr = (unsigned long)malloc(size);
383 fprintf(stderr, "failed to allocate userptr.\n");
387 src_img.user_ptr[0].userptr = userptr;
388 src_img.user_ptr[0].size = size;
391 type = G2D_IMGBUF_GEM;
395 printf("copy and scale test with %s.\n",
396 type == G2D_IMGBUF_GEM ? "gem" : "userptr");
398 src_img.width = img_w;
399 src_img.height = img_h;
400 src_img.stride = src_img.width * 4;
401 src_img.buf_type = type;
402 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
403 src_img.color = 0xffffffff;
404 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w , img_h);
406 goto err_free_userptr;
408 src_img.color = 0xff00ff00;
409 ret = g2d_solid_fill(ctx, &src_img, 5, 5, 100, 100);
411 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;
419 ret = g2d_copy_with_scale(ctx, &src_img, &dst_img, 5, 5, 100, 100,
420 100, 100, 200, 200, 0);
422 goto err_free_userptr;
427 if (type == G2D_IMGBUF_USERPTR)
429 free((void *)userptr);
436 static int g2d_blend_test(struct exynos_device *dev,
437 struct exynos_bo *src,
438 struct exynos_bo *dst,
439 enum e_g2d_buf_type type)
441 struct g2d_context *ctx;
442 struct g2d_image src_img, dst_img;
444 unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
445 unsigned long userptr, size;
448 ctx = g2d_init(dev->fd);
452 memset(&src_img, 0, sizeof(struct g2d_image));
453 memset(&dst_img, 0, sizeof(struct g2d_image));
454 dst_img.bo[0] = dst->handle;
460 img_w = screen_width;
461 img_h = screen_height;
465 src_img.bo[0] = src->handle;
467 case G2D_IMGBUF_USERPTR:
468 size = img_w * img_h * 4;
470 userptr = (unsigned long)malloc(size);
472 fprintf(stderr, "failed to allocate userptr.\n");
476 src_img.user_ptr[0].userptr = userptr;
477 src_img.user_ptr[0].size = size;
480 type = G2D_IMGBUF_GEM;
484 printf("blend test with %s.\n",
485 type == G2D_IMGBUF_GEM ? "gem" : "userptr");
487 src_img.width = img_w;
488 src_img.height = img_h;
489 src_img.stride = src_img.width * 4;
490 src_img.buf_type = type;
491 src_img.select_mode = G2D_SELECT_MODE_NORMAL;
492 src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
493 src_img.color = 0xffffffff;
494 ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
496 goto err_free_userptr;
498 src_img.color = 0x770000ff;
499 ret = g2d_solid_fill(ctx, &src_img, 5, 5, 200, 200);
501 goto err_free_userptr;
503 dst_img.width = img_w;
504 dst_img.height = img_h;
505 dst_img.stride = dst_img.width * 4;
506 dst_img.buf_type = G2D_IMGBUF_GEM;
507 dst_img.select_mode = G2D_SELECT_MODE_NORMAL;
508 dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
509 dst_img.color = 0xffffffff;
510 ret = g2d_solid_fill(ctx, &dst_img, dst_x, dst_y, img_w, img_h);
512 goto err_free_userptr;
514 dst_img.color = 0x77ff0000;
515 ret = g2d_solid_fill(ctx, &dst_img, 105, 105, 200, 200);
517 goto err_free_userptr;
519 ret = g2d_blend(ctx, &src_img, &dst_img, 5, 5, 105, 105, 200, 200,
522 goto err_free_userptr;
527 if (type == G2D_IMGBUF_USERPTR)
529 free((void *)userptr);
536 static struct fimg2d_test_case test_case = {
537 .solid_fill = &g2d_solid_fill_test,
538 .copy = &g2d_copy_test,
539 .copy_with_scale = &g2d_copy_with_scale_test,
540 .blend = &g2d_blend_test,
543 static void usage(char *name)
545 fprintf(stderr, "usage: %s [-s]\n", name);
546 fprintf(stderr, "-s <connector_id>@<crtc_id>:<mode>\n");
551 static const char optstr[] = "s:";
553 int main(int argc, char **argv)
555 struct exynos_device *dev;
556 struct exynos_bo *bo, *src;
557 struct connector con;
558 char *modeset = NULL;
560 uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
561 drmModeRes *resources;
564 memset(&con, 0, sizeof(struct connector));
571 while ((c = getopt(argc, argv, optstr)) != -1) {
574 modeset = strdup(optarg);
576 if (sscanf(optarg, "%d:0x%64s",
578 con.mode_str) != 2 &&
579 sscanf(optarg, "%d@%d:%64s",
591 fd = drmOpen(DRM_MODULE_NAME, NULL);
593 fprintf(stderr, "failed to open.\n");
597 dev = exynos_device_create(fd);
603 resources = drmModeGetResources(dev->fd);
605 fprintf(stderr, "drmModeGetResources failed: %s\n",
611 connector_find_mode(dev->fd, &con, resources);
612 drmModeFreeResources(resources);
614 screen_width = con.mode->hdisplay;
615 screen_height = con.mode->vdisplay;
617 printf("screen width = %d, screen height = %d\n", screen_width,
620 bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
626 handles[0] = bo->handle;
627 pitches[0] = screen_width * 4;
630 ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
631 DRM_FORMAT_RGBA8888, handles,
632 pitches, offsets, &fb_id, 0);
634 goto err_destroy_buffer;
638 memset(bo->vaddr, 0xff, screen_width * screen_height * 4);
640 ret = drm_set_crtc(dev, &con, fb_id);
644 ret = test_case.solid_fill(dev, bo);
646 fprintf(stderr, "failed to solid fill operation.\n");
652 src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
658 ret = test_case.copy(dev, src, bo, G2D_IMGBUF_GEM);
660 fprintf(stderr, "failed to test copy operation.\n");
666 ret = test_case.copy_with_scale(dev, src, bo, G2D_IMGBUF_GEM);
668 fprintf(stderr, "failed to test copy and scale operation.\n");
674 ret = test_case.blend(dev, src, bo, G2D_IMGBUF_USERPTR);
676 fprintf(stderr, "failed to test blend operation.\n");
682 exynos_destroy_buffer(src);
685 drmModeRmFB(fb_id, bo->handle);
688 exynos_destroy_buffer(bo);
692 exynos_device_destroy(dev);