Home | History | Annotate | Download | only in exynos
      1 /*
      2  * Copyright (C) 2015 - Tobias Jakobi
      3  *
      4  * This is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published
      6  * by the Free Software Foundation, either version 2 of the License,
      7  * or (at your option) any later version.
      8  *
      9  * It is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  * You should have received a copy of the GNU General Public License
     14  * along with it. If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <time.h>
     20 #include <getopt.h>
     21 #include <errno.h>
     22 
     23 #include <xf86drm.h>
     24 
     25 #include "exynos_drm.h"
     26 #include "exynos_drmif.h"
     27 #include "exynos_fimg2d.h"
     28 
     29 static int output_mathematica = 0;
     30 
     31 static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
     32 			unsigned buf_width, unsigned buf_height, unsigned iterations)
     33 {
     34 	struct timespec tspec = { 0 };
     35 	struct g2d_image img = { 0 };
     36 
     37 	unsigned long long g2d_time;
     38 	unsigned i;
     39 	int ret = 0;
     40 
     41 	img.width = buf_width;
     42 	img.height = buf_height;
     43 	img.stride = buf_width * 4;
     44 	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
     45 	img.buf_type = G2D_IMGBUF_GEM;
     46 	img.bo[0] = bo->handle;
     47 
     48 	srand(time(NULL));
     49 
     50 	printf("starting simple G2D performance test\n");
     51 	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
     52 		buf_width, buf_height, iterations);
     53 
     54 	if (output_mathematica)
     55 		putchar('{');
     56 
     57 	for (i = 0; i < iterations; ++i) {
     58 		unsigned x, y, w, h;
     59 
     60 		x = rand() % buf_width;
     61 		y = rand() % buf_height;
     62 
     63 		if (x == (buf_width - 1))
     64 			x -= 1;
     65 		if (y == (buf_height - 1))
     66 			y -= 1;
     67 
     68 		w = rand() % (buf_width - x);
     69 		h = rand() % (buf_height - y);
     70 
     71 		if (w == 0) w = 1;
     72 		if (h == 0) h = 1;
     73 
     74 		img.color = rand();
     75 
     76 		ret = g2d_solid_fill(ctx, &img, x, y, w, h);
     77 
     78 		clock_gettime(CLOCK_MONOTONIC, &tspec);
     79 
     80 		if (ret == 0)
     81 			ret = g2d_exec(ctx);
     82 
     83 		if (ret != 0) {
     84 			fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n",
     85 				i, x, y, w, h);
     86 			break;
     87 		} else {
     88 			struct timespec end = { 0 };
     89 			clock_gettime(CLOCK_MONOTONIC, &end);
     90 
     91 			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
     92 			g2d_time += (end.tv_nsec - tspec.tv_nsec);
     93 
     94 			if (output_mathematica) {
     95 				if (i != 0) putchar(',');
     96 				printf("{%u,%llu}", w * h, g2d_time);
     97 			} else {
     98 				printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time);
     99 			}
    100 		}
    101 	}
    102 
    103 	if (output_mathematica)
    104 		printf("}\n");
    105 
    106 	return ret;
    107 }
    108 
    109 static int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx,
    110 			unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch)
    111 {
    112 	struct timespec tspec = { 0 };
    113 	struct g2d_image *images;
    114 
    115 	unsigned long long g2d_time;
    116 	unsigned i, j;
    117 	int ret = 0;
    118 
    119 	images = calloc(batch, sizeof(struct g2d_image));
    120 	if (images == NULL) {
    121 		fprintf(stderr, "error: failed to allocate G2D images.\n");
    122 		return -ENOMEM;
    123 	}
    124 
    125 	for (i = 0; i < batch; ++i) {
    126 		images[i].width = buf_width;
    127 		images[i].height = buf_height;
    128 		images[i].stride = buf_width * 4;
    129 		images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
    130 		images[i].buf_type = G2D_IMGBUF_GEM;
    131 		images[i].bo[0] = bo->handle;
    132 	}
    133 
    134 	srand(time(NULL));
    135 
    136 	printf("starting multi G2D performance test (batch size = %u)\n", batch);
    137 	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
    138 		buf_width, buf_height, iterations);
    139 
    140 	if (output_mathematica)
    141 		putchar('{');
    142 
    143 	for (i = 0; i < iterations; ++i) {
    144 		unsigned num_pixels = 0;
    145 
    146 		for (j = 0; j < batch; ++j) {
    147 			unsigned x, y, w, h;
    148 
    149 			x = rand() % buf_width;
    150 			y = rand() % buf_height;
    151 
    152 			if (x == (buf_width - 1))
    153 				x -= 1;
    154 			if (y == (buf_height - 1))
    155 				y -= 1;
    156 
    157 			w = rand() % (buf_width - x);
    158 			h = rand() % (buf_height - y);
    159 
    160 			if (w == 0) w = 1;
    161 			if (h == 0) h = 1;
    162 
    163 			images[j].color = rand();
    164 
    165 			num_pixels += w * h;
    166 
    167 			ret = g2d_solid_fill(ctx, &images[j], x, y, w, h);
    168 			if (ret != 0)
    169 				break;
    170 		}
    171 
    172 		clock_gettime(CLOCK_MONOTONIC, &tspec);
    173 
    174 		if (ret == 0)
    175 			ret = g2d_exec(ctx);
    176 
    177 		if (ret != 0) {
    178 			fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels);
    179 			break;
    180 		} else {
    181 			struct timespec end = { 0 };
    182 			clock_gettime(CLOCK_MONOTONIC, &end);
    183 
    184 			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
    185 			g2d_time += (end.tv_nsec - tspec.tv_nsec);
    186 
    187 			if (output_mathematica) {
    188 				if (i != 0) putchar(',');
    189 				printf("{%u,%llu}", num_pixels, g2d_time);
    190 			} else {
    191 				printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time);
    192 			}
    193 		}
    194 	}
    195 
    196 	if (output_mathematica)
    197 		printf("}\n");
    198 
    199 	free(images);
    200 
    201 	return ret;
    202 }
    203 
    204 static void usage(const char *name)
    205 {
    206 	fprintf(stderr, "usage: %s [-ibwh]\n\n", name);
    207 
    208 	fprintf(stderr, "\t-i <number of iterations>\n");
    209 	fprintf(stderr, "\t-b <size of a batch> (default = 3)\n\n");
    210 
    211 	fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
    212 	fprintf(stderr, "\t-h <buffer height> (default = 4096)\n\n");
    213 
    214 	fprintf(stderr, "\t-M <enable Mathematica styled output>\n");
    215 
    216 	exit(0);
    217 }
    218 
    219 int main(int argc, char **argv)
    220 {
    221 	int fd, ret, c, parsefail;
    222 
    223 	struct exynos_device *dev;
    224 	struct g2d_context *ctx;
    225 	struct exynos_bo *bo;
    226 
    227 	unsigned int iters = 0, batch = 3;
    228 	unsigned int bufw = 4096, bufh = 4096;
    229 
    230 	ret = 0;
    231 	parsefail = 0;
    232 
    233 	while ((c = getopt(argc, argv, "i:b:w:h:M")) != -1) {
    234 		switch (c) {
    235 		case 'i':
    236 			if (sscanf(optarg, "%u", &iters) != 1)
    237 				parsefail = 1;
    238 			break;
    239 		case 'b':
    240 			if (sscanf(optarg, "%u", &batch) != 1)
    241 				parsefail = 1;
    242 			break;
    243 		case 'w':
    244 			if (sscanf(optarg, "%u", &bufw) != 1)
    245 				parsefail = 1;
    246 			break;
    247 		case 'h':
    248 			if (sscanf(optarg, "%u", &bufh) != 1)
    249 				parsefail = 1;
    250 			break;
    251 		case 'M':
    252 			output_mathematica = 1;
    253 			break;
    254 		default:
    255 			parsefail = 1;
    256 			break;
    257 		}
    258 	}
    259 
    260 	if (parsefail || (argc == 1) || (iters == 0))
    261 		usage(argv[0]);
    262 
    263 	if (bufw < 2 || bufw > 4096 || bufh < 2 || bufh > 4096) {
    264 		fprintf(stderr, "error: buffer width/height should be in the range 2 to 4096.\n");
    265 		ret = -1;
    266 
    267 		goto out;
    268 	}
    269 
    270 	if (bufw == 0 || bufh == 0) {
    271 		fprintf(stderr, "error: buffer width/height should be non-zero.\n");
    272 		ret = -1;
    273 
    274 		goto out;
    275 	}
    276 
    277 	fd = drmOpen("exynos", NULL);
    278 	if (fd < 0) {
    279 		fprintf(stderr, "error: failed to open drm\n");
    280 		ret = -1;
    281 
    282 		goto out;
    283 	}
    284 
    285 	dev = exynos_device_create(fd);
    286 	if (dev == NULL) {
    287 		fprintf(stderr, "error: failed to create device\n");
    288 		ret = -2;
    289 
    290 		goto fail;
    291 	}
    292 
    293 	ctx = g2d_init(fd);
    294 	if (ctx == NULL) {
    295 		fprintf(stderr, "error: failed to init G2D\n");
    296 		ret = -3;
    297 
    298 		goto g2d_fail;
    299 	}
    300 
    301 	bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
    302 	if (bo == NULL) {
    303 		fprintf(stderr, "error: failed to create bo\n");
    304 		ret = -4;
    305 
    306 		goto bo_fail;
    307 	}
    308 
    309 	ret = fimg2d_perf_simple(bo, ctx, bufw, bufh, iters);
    310 
    311 	if (ret == 0)
    312 		ret = fimg2d_perf_multi(bo, ctx, bufw, bufh, iters, batch);
    313 
    314 	exynos_bo_destroy(bo);
    315 
    316 bo_fail:
    317 	g2d_fini(ctx);
    318 
    319 g2d_fail:
    320 	exynos_device_destroy(dev);
    321 
    322 fail:
    323 	drmClose(fd);
    324 
    325 out:
    326 	return ret;
    327 }
    328