1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright (C) 2015 - Tobias Jakobi
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next
12d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13d722e3fbSopenharmony_ci * Software.
14d722e3fbSopenharmony_ci *
15d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18d722e3fbSopenharmony_ci * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
22d722e3fbSopenharmony_ci */
23d722e3fbSopenharmony_ci
24d722e3fbSopenharmony_ci#include <stdlib.h>
25d722e3fbSopenharmony_ci#include <stdio.h>
26d722e3fbSopenharmony_ci#include <time.h>
27d722e3fbSopenharmony_ci#include <getopt.h>
28d722e3fbSopenharmony_ci#include <errno.h>
29d722e3fbSopenharmony_ci
30d722e3fbSopenharmony_ci#include <xf86drm.h>
31d722e3fbSopenharmony_ci
32d722e3fbSopenharmony_ci#include "exynos_drm.h"
33d722e3fbSopenharmony_ci#include "exynos_drmif.h"
34d722e3fbSopenharmony_ci#include "exynos_fimg2d.h"
35d722e3fbSopenharmony_ci
36d722e3fbSopenharmony_cistatic int output_mathematica = 0;
37d722e3fbSopenharmony_ci
38d722e3fbSopenharmony_cistatic int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
39d722e3fbSopenharmony_ci			unsigned buf_width, unsigned buf_height, unsigned iterations)
40d722e3fbSopenharmony_ci{
41d722e3fbSopenharmony_ci	struct timespec tspec = { 0 };
42d722e3fbSopenharmony_ci	struct g2d_image img = { 0 };
43d722e3fbSopenharmony_ci
44d722e3fbSopenharmony_ci	unsigned long long g2d_time;
45d722e3fbSopenharmony_ci	unsigned i;
46d722e3fbSopenharmony_ci	int ret = 0;
47d722e3fbSopenharmony_ci
48d722e3fbSopenharmony_ci	img.width = buf_width;
49d722e3fbSopenharmony_ci	img.height = buf_height;
50d722e3fbSopenharmony_ci	img.stride = buf_width * 4;
51d722e3fbSopenharmony_ci	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
52d722e3fbSopenharmony_ci	img.buf_type = G2D_IMGBUF_GEM;
53d722e3fbSopenharmony_ci	img.bo[0] = bo->handle;
54d722e3fbSopenharmony_ci
55d722e3fbSopenharmony_ci	srand(time(NULL));
56d722e3fbSopenharmony_ci
57d722e3fbSopenharmony_ci	printf("starting simple G2D performance test\n");
58d722e3fbSopenharmony_ci	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
59d722e3fbSopenharmony_ci		buf_width, buf_height, iterations);
60d722e3fbSopenharmony_ci
61d722e3fbSopenharmony_ci	if (output_mathematica)
62d722e3fbSopenharmony_ci		putchar('{');
63d722e3fbSopenharmony_ci
64d722e3fbSopenharmony_ci	for (i = 0; i < iterations; ++i) {
65d722e3fbSopenharmony_ci		unsigned x, y, w, h;
66d722e3fbSopenharmony_ci
67d722e3fbSopenharmony_ci		x = rand() % buf_width;
68d722e3fbSopenharmony_ci		y = rand() % buf_height;
69d722e3fbSopenharmony_ci
70d722e3fbSopenharmony_ci		if (x == (buf_width - 1))
71d722e3fbSopenharmony_ci			x -= 1;
72d722e3fbSopenharmony_ci		if (y == (buf_height - 1))
73d722e3fbSopenharmony_ci			y -= 1;
74d722e3fbSopenharmony_ci
75d722e3fbSopenharmony_ci		w = rand() % (buf_width - x);
76d722e3fbSopenharmony_ci		h = rand() % (buf_height - y);
77d722e3fbSopenharmony_ci
78d722e3fbSopenharmony_ci		if (w == 0) w = 1;
79d722e3fbSopenharmony_ci		if (h == 0) h = 1;
80d722e3fbSopenharmony_ci
81d722e3fbSopenharmony_ci		img.color = rand();
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci		ret = g2d_solid_fill(ctx, &img, x, y, w, h);
84d722e3fbSopenharmony_ci
85d722e3fbSopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &tspec);
86d722e3fbSopenharmony_ci
87d722e3fbSopenharmony_ci		if (ret == 0)
88d722e3fbSopenharmony_ci			ret = g2d_exec(ctx);
89d722e3fbSopenharmony_ci
90d722e3fbSopenharmony_ci		if (ret != 0) {
91d722e3fbSopenharmony_ci			fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n",
92d722e3fbSopenharmony_ci				i, x, y, w, h);
93d722e3fbSopenharmony_ci			break;
94d722e3fbSopenharmony_ci		} else {
95d722e3fbSopenharmony_ci			struct timespec end = { 0 };
96d722e3fbSopenharmony_ci			clock_gettime(CLOCK_MONOTONIC, &end);
97d722e3fbSopenharmony_ci
98d722e3fbSopenharmony_ci			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
99d722e3fbSopenharmony_ci			g2d_time += (end.tv_nsec - tspec.tv_nsec);
100d722e3fbSopenharmony_ci
101d722e3fbSopenharmony_ci			if (output_mathematica) {
102d722e3fbSopenharmony_ci				if (i != 0) putchar(',');
103d722e3fbSopenharmony_ci				printf("{%u,%llu}", w * h, g2d_time);
104d722e3fbSopenharmony_ci			} else {
105d722e3fbSopenharmony_ci				printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time);
106d722e3fbSopenharmony_ci			}
107d722e3fbSopenharmony_ci		}
108d722e3fbSopenharmony_ci	}
109d722e3fbSopenharmony_ci
110d722e3fbSopenharmony_ci	if (output_mathematica)
111d722e3fbSopenharmony_ci		printf("}\n");
112d722e3fbSopenharmony_ci
113d722e3fbSopenharmony_ci	return ret;
114d722e3fbSopenharmony_ci}
115d722e3fbSopenharmony_ci
116d722e3fbSopenharmony_cistatic int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx,
117d722e3fbSopenharmony_ci			unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch)
118d722e3fbSopenharmony_ci{
119d722e3fbSopenharmony_ci	struct timespec tspec = { 0 };
120d722e3fbSopenharmony_ci	struct g2d_image *images;
121d722e3fbSopenharmony_ci
122d722e3fbSopenharmony_ci	unsigned long long g2d_time;
123d722e3fbSopenharmony_ci	unsigned i, j;
124d722e3fbSopenharmony_ci	int ret = 0;
125d722e3fbSopenharmony_ci
126d722e3fbSopenharmony_ci	images = calloc(batch, sizeof(struct g2d_image));
127d722e3fbSopenharmony_ci	if (images == NULL) {
128d722e3fbSopenharmony_ci		fprintf(stderr, "error: failed to allocate G2D images.\n");
129d722e3fbSopenharmony_ci		return -ENOMEM;
130d722e3fbSopenharmony_ci	}
131d722e3fbSopenharmony_ci
132d722e3fbSopenharmony_ci	for (i = 0; i < batch; ++i) {
133d722e3fbSopenharmony_ci		images[i].width = buf_width;
134d722e3fbSopenharmony_ci		images[i].height = buf_height;
135d722e3fbSopenharmony_ci		images[i].stride = buf_width * 4;
136d722e3fbSopenharmony_ci		images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
137d722e3fbSopenharmony_ci		images[i].buf_type = G2D_IMGBUF_GEM;
138d722e3fbSopenharmony_ci		images[i].bo[0] = bo->handle;
139d722e3fbSopenharmony_ci	}
140d722e3fbSopenharmony_ci
141d722e3fbSopenharmony_ci	srand(time(NULL));
142d722e3fbSopenharmony_ci
143d722e3fbSopenharmony_ci	printf("starting multi G2D performance test (batch size = %u)\n", batch);
144d722e3fbSopenharmony_ci	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
145d722e3fbSopenharmony_ci		buf_width, buf_height, iterations);
146d722e3fbSopenharmony_ci
147d722e3fbSopenharmony_ci	if (output_mathematica)
148d722e3fbSopenharmony_ci		putchar('{');
149d722e3fbSopenharmony_ci
150d722e3fbSopenharmony_ci	for (i = 0; i < iterations; ++i) {
151d722e3fbSopenharmony_ci		unsigned num_pixels = 0;
152d722e3fbSopenharmony_ci
153d722e3fbSopenharmony_ci		for (j = 0; j < batch; ++j) {
154d722e3fbSopenharmony_ci			unsigned x, y, w, h;
155d722e3fbSopenharmony_ci
156d722e3fbSopenharmony_ci			x = rand() % buf_width;
157d722e3fbSopenharmony_ci			y = rand() % buf_height;
158d722e3fbSopenharmony_ci
159d722e3fbSopenharmony_ci			if (x == (buf_width - 1))
160d722e3fbSopenharmony_ci				x -= 1;
161d722e3fbSopenharmony_ci			if (y == (buf_height - 1))
162d722e3fbSopenharmony_ci				y -= 1;
163d722e3fbSopenharmony_ci
164d722e3fbSopenharmony_ci			w = rand() % (buf_width - x);
165d722e3fbSopenharmony_ci			h = rand() % (buf_height - y);
166d722e3fbSopenharmony_ci
167d722e3fbSopenharmony_ci			if (w == 0) w = 1;
168d722e3fbSopenharmony_ci			if (h == 0) h = 1;
169d722e3fbSopenharmony_ci
170d722e3fbSopenharmony_ci			images[j].color = rand();
171d722e3fbSopenharmony_ci
172d722e3fbSopenharmony_ci			num_pixels += w * h;
173d722e3fbSopenharmony_ci
174d722e3fbSopenharmony_ci			ret = g2d_solid_fill(ctx, &images[j], x, y, w, h);
175d722e3fbSopenharmony_ci			if (ret != 0)
176d722e3fbSopenharmony_ci				break;
177d722e3fbSopenharmony_ci		}
178d722e3fbSopenharmony_ci
179d722e3fbSopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &tspec);
180d722e3fbSopenharmony_ci
181d722e3fbSopenharmony_ci		if (ret == 0)
182d722e3fbSopenharmony_ci			ret = g2d_exec(ctx);
183d722e3fbSopenharmony_ci
184d722e3fbSopenharmony_ci		if (ret != 0) {
185d722e3fbSopenharmony_ci			fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels);
186d722e3fbSopenharmony_ci			break;
187d722e3fbSopenharmony_ci		} else {
188d722e3fbSopenharmony_ci			struct timespec end = { 0 };
189d722e3fbSopenharmony_ci			clock_gettime(CLOCK_MONOTONIC, &end);
190d722e3fbSopenharmony_ci
191d722e3fbSopenharmony_ci			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
192d722e3fbSopenharmony_ci			g2d_time += (end.tv_nsec - tspec.tv_nsec);
193d722e3fbSopenharmony_ci
194d722e3fbSopenharmony_ci			if (output_mathematica) {
195d722e3fbSopenharmony_ci				if (i != 0) putchar(',');
196d722e3fbSopenharmony_ci				printf("{%u,%llu}", num_pixels, g2d_time);
197d722e3fbSopenharmony_ci			} else {
198d722e3fbSopenharmony_ci				printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time);
199d722e3fbSopenharmony_ci			}
200d722e3fbSopenharmony_ci		}
201d722e3fbSopenharmony_ci	}
202d722e3fbSopenharmony_ci
203d722e3fbSopenharmony_ci	if (output_mathematica)
204d722e3fbSopenharmony_ci		printf("}\n");
205d722e3fbSopenharmony_ci
206d722e3fbSopenharmony_ci	free(images);
207d722e3fbSopenharmony_ci
208d722e3fbSopenharmony_ci	return ret;
209d722e3fbSopenharmony_ci}
210d722e3fbSopenharmony_ci
211d722e3fbSopenharmony_cistatic void usage(const char *name)
212d722e3fbSopenharmony_ci{
213d722e3fbSopenharmony_ci	fprintf(stderr, "usage: %s [-ibwh]\n\n", name);
214d722e3fbSopenharmony_ci
215d722e3fbSopenharmony_ci	fprintf(stderr, "\t-i <number of iterations>\n");
216d722e3fbSopenharmony_ci	fprintf(stderr, "\t-b <size of a batch> (default = 3)\n\n");
217d722e3fbSopenharmony_ci
218d722e3fbSopenharmony_ci	fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
219d722e3fbSopenharmony_ci	fprintf(stderr, "\t-h <buffer height> (default = 4096)\n\n");
220d722e3fbSopenharmony_ci
221d722e3fbSopenharmony_ci	fprintf(stderr, "\t-M <enable Mathematica styled output>\n");
222d722e3fbSopenharmony_ci
223d722e3fbSopenharmony_ci	exit(0);
224d722e3fbSopenharmony_ci}
225d722e3fbSopenharmony_ci
226d722e3fbSopenharmony_ciint main(int argc, char **argv)
227d722e3fbSopenharmony_ci{
228d722e3fbSopenharmony_ci	int fd, ret, c, parsefail;
229d722e3fbSopenharmony_ci
230d722e3fbSopenharmony_ci	struct exynos_device *dev;
231d722e3fbSopenharmony_ci	struct g2d_context *ctx;
232d722e3fbSopenharmony_ci	struct exynos_bo *bo;
233d722e3fbSopenharmony_ci
234d722e3fbSopenharmony_ci	unsigned int iters = 0, batch = 3;
235d722e3fbSopenharmony_ci	unsigned int bufw = 4096, bufh = 4096;
236d722e3fbSopenharmony_ci
237d722e3fbSopenharmony_ci	ret = 0;
238d722e3fbSopenharmony_ci	parsefail = 0;
239d722e3fbSopenharmony_ci
240d722e3fbSopenharmony_ci	while ((c = getopt(argc, argv, "i:b:w:h:M")) != -1) {
241d722e3fbSopenharmony_ci		switch (c) {
242d722e3fbSopenharmony_ci		case 'i':
243d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &iters) != 1)
244d722e3fbSopenharmony_ci				parsefail = 1;
245d722e3fbSopenharmony_ci			break;
246d722e3fbSopenharmony_ci		case 'b':
247d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &batch) != 1)
248d722e3fbSopenharmony_ci				parsefail = 1;
249d722e3fbSopenharmony_ci			break;
250d722e3fbSopenharmony_ci		case 'w':
251d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &bufw) != 1)
252d722e3fbSopenharmony_ci				parsefail = 1;
253d722e3fbSopenharmony_ci			break;
254d722e3fbSopenharmony_ci		case 'h':
255d722e3fbSopenharmony_ci			if (sscanf(optarg, "%u", &bufh) != 1)
256d722e3fbSopenharmony_ci				parsefail = 1;
257d722e3fbSopenharmony_ci			break;
258d722e3fbSopenharmony_ci		case 'M':
259d722e3fbSopenharmony_ci			output_mathematica = 1;
260d722e3fbSopenharmony_ci			break;
261d722e3fbSopenharmony_ci		default:
262d722e3fbSopenharmony_ci			parsefail = 1;
263d722e3fbSopenharmony_ci			break;
264d722e3fbSopenharmony_ci		}
265d722e3fbSopenharmony_ci	}
266d722e3fbSopenharmony_ci
267d722e3fbSopenharmony_ci	if (parsefail || (argc == 1) || (iters == 0))
268d722e3fbSopenharmony_ci		usage(argv[0]);
269d722e3fbSopenharmony_ci
270d722e3fbSopenharmony_ci	if (bufw < 2 || bufw > 4096 || bufh < 2 || bufh > 4096) {
271d722e3fbSopenharmony_ci		fprintf(stderr, "error: buffer width/height should be in the range 2 to 4096.\n");
272d722e3fbSopenharmony_ci		ret = -1;
273d722e3fbSopenharmony_ci
274d722e3fbSopenharmony_ci		goto out;
275d722e3fbSopenharmony_ci	}
276d722e3fbSopenharmony_ci
277d722e3fbSopenharmony_ci	fd = drmOpen("exynos", NULL);
278d722e3fbSopenharmony_ci	if (fd < 0) {
279d722e3fbSopenharmony_ci		fprintf(stderr, "error: failed to open drm\n");
280d722e3fbSopenharmony_ci		ret = -1;
281d722e3fbSopenharmony_ci
282d722e3fbSopenharmony_ci		goto out;
283d722e3fbSopenharmony_ci	}
284d722e3fbSopenharmony_ci
285d722e3fbSopenharmony_ci	dev = exynos_device_create(fd);
286d722e3fbSopenharmony_ci	if (dev == NULL) {
287d722e3fbSopenharmony_ci		fprintf(stderr, "error: failed to create device\n");
288d722e3fbSopenharmony_ci		ret = -2;
289d722e3fbSopenharmony_ci
290d722e3fbSopenharmony_ci		goto fail;
291d722e3fbSopenharmony_ci	}
292d722e3fbSopenharmony_ci
293d722e3fbSopenharmony_ci	ctx = g2d_init(fd);
294d722e3fbSopenharmony_ci	if (ctx == NULL) {
295d722e3fbSopenharmony_ci		fprintf(stderr, "error: failed to init G2D\n");
296d722e3fbSopenharmony_ci		ret = -3;
297d722e3fbSopenharmony_ci
298d722e3fbSopenharmony_ci		goto g2d_fail;
299d722e3fbSopenharmony_ci	}
300d722e3fbSopenharmony_ci
301d722e3fbSopenharmony_ci	bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
302d722e3fbSopenharmony_ci	if (bo == NULL) {
303d722e3fbSopenharmony_ci		fprintf(stderr, "error: failed to create bo\n");
304d722e3fbSopenharmony_ci		ret = -4;
305d722e3fbSopenharmony_ci
306d722e3fbSopenharmony_ci		goto bo_fail;
307d722e3fbSopenharmony_ci	}
308d722e3fbSopenharmony_ci
309d722e3fbSopenharmony_ci	ret = fimg2d_perf_simple(bo, ctx, bufw, bufh, iters);
310d722e3fbSopenharmony_ci
311d722e3fbSopenharmony_ci	if (ret == 0)
312d722e3fbSopenharmony_ci		ret = fimg2d_perf_multi(bo, ctx, bufw, bufh, iters, batch);
313d722e3fbSopenharmony_ci
314d722e3fbSopenharmony_ci	exynos_bo_destroy(bo);
315d722e3fbSopenharmony_ci
316d722e3fbSopenharmony_cibo_fail:
317d722e3fbSopenharmony_ci	g2d_fini(ctx);
318d722e3fbSopenharmony_ci
319d722e3fbSopenharmony_cig2d_fail:
320d722e3fbSopenharmony_ci	exynos_device_destroy(dev);
321d722e3fbSopenharmony_ci
322d722e3fbSopenharmony_cifail:
323d722e3fbSopenharmony_ci	drmClose(fd);
324d722e3fbSopenharmony_ci
325d722e3fbSopenharmony_ciout:
326d722e3fbSopenharmony_ci	return ret;
327d722e3fbSopenharmony_ci}
328