OSDN Git Service

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