OSDN Git Service

freedreno: rework internal ring->emit_reloc_ring()
[android-x86/external-libdrm.git] / tests / exynos / exynos_fimg2d_perf.c
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 }