mmx: add x8f8g8b8 fetcher
[profile/ivi/pixman.git] / test / lowlevel-blt-bench.c
1 /*
2  * Copyright © 2009 Nokia Corporation
3  * Copyright © 2010 Movial Creative Technologies Oy
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "utils.h"
29
30 #define SOLID_FLAG 1
31 #define CA_FLAG    2
32
33 #define L1CACHE_SIZE (8 * 1024)
34 #define L2CACHE_SIZE (128 * 1024)
35
36 #define WIDTH  1920
37 #define HEIGHT 1080
38 #define BUFSIZE (WIDTH * HEIGHT * 4)
39 #define XWIDTH 256
40 #define XHEIGHT 256
41 #define TILEWIDTH 32
42 #define TINYWIDTH 8
43
44 #define EXCLUDE_OVERHEAD 1
45
46 uint32_t *dst;
47 uint32_t *src;
48 uint32_t *mask;
49
50 double bandwidth = 0;
51
52 double
53 bench_memcpy ()
54 {
55     int64_t n = 0, total;
56     double  t1, t2;
57     int     x = 0;
58
59     t1 = gettime ();
60     while (1)
61     {
62         memcpy (dst, src, BUFSIZE - 64);
63         memcpy (src, dst, BUFSIZE - 64);
64         n += 4 * (BUFSIZE - 64);
65         t2 = gettime ();
66         if (t2 - t1 > 0.5)
67             break;
68     }
69     n = total = n * 5;
70     t1 = gettime ();
71     while (n > 0)
72     {
73         if (++x >= 64)
74             x = 0;
75         memcpy ((char *)dst + 1, (char *)src + x, BUFSIZE - 64);
76         memcpy ((char *)src + 1, (char *)dst + x, BUFSIZE - 64);
77         n -= 4 * (BUFSIZE - 64);
78     }
79     t2 = gettime ();
80     return (double)total / (t2 - t1);
81 }
82
83 static void
84 pixman_image_composite_wrapper (pixman_implementation_t *impl,
85                                 pixman_composite_info_t *info)
86 {
87     pixman_image_composite (info->op,
88                             info->src_image, info->mask_image, info->dest_image,
89                             info->src_x, info->src_y,
90                             info->mask_x, info->mask_y,
91                             info->dest_x, info->dest_y,
92                             info->width, info->height);
93 }
94
95 static void
96 pixman_image_composite_empty (pixman_implementation_t *impl,
97                               pixman_composite_info_t *info)
98 {
99     pixman_image_composite (info->op,
100                             info->src_image, info->mask_image, info->dest_image,
101                             0, 0, 0, 0, 0, 0, 1, 1);
102 }
103
104 static inline void
105 call_func (pixman_composite_func_t func,
106            pixman_op_t             op,
107            pixman_image_t *        src_image,
108            pixman_image_t *        mask_image,
109            pixman_image_t *        dest_image,
110            int32_t                 src_x,
111            int32_t                 src_y,
112            int32_t                 mask_x,
113            int32_t                 mask_y,
114            int32_t                 dest_x,
115            int32_t                 dest_y,
116            int32_t                 width,
117            int32_t                 height)
118 {
119     pixman_composite_info_t info;
120
121     info.op = op;
122     info.src_image = src_image;
123     info.mask_image = mask_image;
124     info.dest_image = dest_image;
125     info.src_x = src_x;
126     info.src_y = src_y;
127     info.mask_x = mask_x;
128     info.mask_y = mask_y;
129     info.dest_x = dest_x;
130     info.dest_y = dest_y;
131     info.width = width;
132     info.height = height;
133
134     func (0, &info);
135 }
136
137 void
138 noinline
139 bench_L  (pixman_op_t              op,
140           pixman_image_t *         src_img,
141           pixman_image_t *         mask_img,
142           pixman_image_t *         dst_img,
143           int64_t                  n,
144           pixman_composite_func_t  func,
145           int                      width,
146           int                      lines_count)
147 {
148     int64_t      i, j;
149     int          x = 0;
150     int          q = 0;
151     volatile int qx;
152
153     for (i = 0; i < n; i++)
154     {
155         /* touch destination buffer to fetch it into L1 cache */
156         for (j = 0; j < width + 64; j += 16) {
157             q += dst[j];
158             q += src[j];
159         }
160         if (++x >= 64)
161             x = 0;
162         call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 63 - x, 0, width, lines_count);
163     }
164     qx = q;
165 }
166
167 void
168 noinline
169 bench_M (pixman_op_t              op,
170          pixman_image_t *         src_img,
171          pixman_image_t *         mask_img,
172          pixman_image_t *         dst_img,
173          int64_t                  n,
174          pixman_composite_func_t  func)
175 {
176     int64_t i;
177     int     x = 0;
178
179     for (i = 0; i < n; i++)
180     {
181         if (++x >= 64)
182             x = 0;
183         call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 1, 0, WIDTH - 64, HEIGHT);
184     }
185 }
186
187 double
188 noinline
189 bench_HT (pixman_op_t              op,
190           pixman_image_t *         src_img,
191           pixman_image_t *         mask_img,
192           pixman_image_t *         dst_img,
193           int64_t                  n,
194           pixman_composite_func_t  func)
195 {
196     double  pix_cnt = 0;
197     int     x = 0;
198     int     y = 0;
199     int64_t i;
200
201     srand (0);
202     for (i = 0; i < n; i++)
203     {
204         int w = (rand () % (TILEWIDTH * 2)) + 1;
205         int h = (rand () % (TILEWIDTH * 2)) + 1;
206         if (x + w > WIDTH)
207         {
208             x = 0;
209             y += TILEWIDTH * 2;
210         }
211         if (y + h > HEIGHT)
212         {
213             y = 0;
214         }
215         call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
216         x += w;
217         pix_cnt += w * h;
218     }
219     return pix_cnt;
220 }
221
222 double
223 noinline
224 bench_VT (pixman_op_t              op,
225           pixman_image_t *         src_img,
226           pixman_image_t *         mask_img,
227           pixman_image_t *         dst_img,
228           int64_t                  n,
229           pixman_composite_func_t  func)
230 {
231     double  pix_cnt = 0;
232     int     x = 0;
233     int     y = 0;
234     int64_t i;
235
236     srand (0);
237     for (i = 0; i < n; i++)
238     {
239         int w = (rand () % (TILEWIDTH * 2)) + 1;
240         int h = (rand () % (TILEWIDTH * 2)) + 1;
241         if (y + h > HEIGHT)
242         {
243             y = 0;
244             x += TILEWIDTH * 2;
245         }
246         if (x + w > WIDTH)
247         {
248             x = 0;
249         }
250         call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
251         y += h;
252         pix_cnt += w * h;
253     }
254     return pix_cnt;
255 }
256
257 double
258 noinline
259 bench_R (pixman_op_t              op,
260          pixman_image_t *         src_img,
261          pixman_image_t *         mask_img,
262          pixman_image_t *         dst_img,
263          int64_t                  n,
264          pixman_composite_func_t  func,
265          int                      maxw,
266          int                      maxh)
267 {
268     double  pix_cnt = 0;
269     int64_t i;
270
271     if (maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2)
272     {
273         printf("error: maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2\n");
274         return 0;
275     }
276
277     srand (0);
278     for (i = 0; i < n; i++)
279     {
280         int w = (rand () % (TILEWIDTH * 2)) + 1;
281         int h = (rand () % (TILEWIDTH * 2)) + 1;
282         int sx = rand () % (maxw - TILEWIDTH * 2);
283         int sy = rand () % (maxh - TILEWIDTH * 2);
284         int dx = rand () % (maxw - TILEWIDTH * 2);
285         int dy = rand () % (maxh - TILEWIDTH * 2);
286         call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
287         pix_cnt += w * h;
288     }
289     return pix_cnt;
290 }
291
292 double
293 noinline
294 bench_RT (pixman_op_t              op,
295           pixman_image_t *         src_img,
296           pixman_image_t *         mask_img,
297           pixman_image_t *         dst_img,
298           int64_t                  n,
299           pixman_composite_func_t  func,
300           int                      maxw,
301           int                      maxh)
302 {
303     double  pix_cnt = 0;
304     int64_t i;
305
306     if (maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2)
307     {
308         printf("error: maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2\n");
309         return 0;
310     }
311
312     srand (0);
313     for (i = 0; i < n; i++)
314     {
315         int w = (rand () % (TINYWIDTH * 2)) + 1;
316         int h = (rand () % (TINYWIDTH * 2)) + 1;
317         int sx = rand () % (maxw - TINYWIDTH * 2);
318         int sy = rand () % (maxh - TINYWIDTH * 2);
319         int dx = rand () % (maxw - TINYWIDTH * 2);
320         int dy = rand () % (maxh - TINYWIDTH * 2);
321         call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
322         pix_cnt += w * h;
323     }
324     return pix_cnt;
325 }
326
327 void
328 bench_composite (char * testname,
329                  int    src_fmt,
330                  int    src_flags,
331                  int    op,
332                  int    mask_fmt,
333                  int    mask_flags,
334                  int    dst_fmt,
335                  double npix)
336 {
337     pixman_image_t *                src_img;
338     pixman_image_t *                dst_img;
339     pixman_image_t *                mask_img;
340     pixman_image_t *                xsrc_img;
341     pixman_image_t *                xdst_img;
342     pixman_image_t *                xmask_img;
343     double                          t1, t2, t3, pix_cnt;
344     int64_t                         n, l1test_width, nlines;
345     double                             bytes_per_pix = 0;
346
347     pixman_composite_func_t func = pixman_image_composite_wrapper;
348
349     if (!(src_flags & SOLID_FLAG))
350     {
351         bytes_per_pix += (src_fmt >> 24) / 8.0;
352         src_img = pixman_image_create_bits (src_fmt,
353                                             WIDTH, HEIGHT,
354                                             src,
355                                             WIDTH * 4);
356         xsrc_img = pixman_image_create_bits (src_fmt,
357                                              XWIDTH, XHEIGHT,
358                                              src,
359                                              XWIDTH * 4);
360     }
361     else
362     {
363         src_img = pixman_image_create_bits (src_fmt,
364                                             1, 1,
365                                             src,
366                                             4);
367         xsrc_img = pixman_image_create_bits (src_fmt,
368                                              1, 1,
369                                              src,
370                                              4);
371         pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
372         pixman_image_set_repeat (xsrc_img, PIXMAN_REPEAT_NORMAL);
373     }
374
375     bytes_per_pix += (dst_fmt >> 24) / 8.0;
376     dst_img = pixman_image_create_bits (dst_fmt,
377                                         WIDTH, HEIGHT,
378                                         dst,
379                                         WIDTH * 4);
380
381     mask_img = NULL;
382     xmask_img = NULL;
383     if (!(mask_flags & SOLID_FLAG) && mask_fmt != PIXMAN_null)
384     {
385         bytes_per_pix += (mask_fmt >> 24) / ((op == PIXMAN_OP_SRC) ? 8.0 : 4.0);
386         mask_img = pixman_image_create_bits (mask_fmt,
387                                              WIDTH, HEIGHT,
388                                              mask,
389                                              WIDTH * 4);
390         xmask_img = pixman_image_create_bits (mask_fmt,
391                                              XWIDTH, XHEIGHT,
392                                              mask,
393                                              XWIDTH * 4);
394     }
395     else if (mask_fmt != PIXMAN_null)
396     {
397         mask_img = pixman_image_create_bits (mask_fmt,
398                                              1, 1,
399                                              mask,
400                                              4);
401         xmask_img = pixman_image_create_bits (mask_fmt,
402                                              1, 1,
403                                              mask,
404                                              4 * 4);
405        pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
406        pixman_image_set_repeat (xmask_img, PIXMAN_REPEAT_NORMAL);
407     }
408     if ((mask_flags & CA_FLAG) && mask_fmt != PIXMAN_null)
409     {
410        pixman_image_set_component_alpha (mask_img, 1);
411     }
412     xdst_img = pixman_image_create_bits (dst_fmt,
413                                          XWIDTH, XHEIGHT,
414                                          dst,
415                                          XWIDTH * 4);
416
417
418     printf ("%24s %c", testname, func != pixman_image_composite_wrapper ?
419             '-' : '=');
420
421     memcpy (src, dst, BUFSIZE);
422     memcpy (dst, src, BUFSIZE);
423
424     l1test_width = L1CACHE_SIZE / 8 - 64;
425     if (l1test_width < 1)
426         l1test_width = 1;
427     if (l1test_width > WIDTH - 64)
428         l1test_width = WIDTH - 64;
429     n = 1 + npix / (l1test_width * 8);
430     t1 = gettime ();
431 #if EXCLUDE_OVERHEAD
432     bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, 1);
433 #endif
434     t2 = gettime ();
435     bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, 1);
436     t3 = gettime ();
437     printf ("  L1:%7.2f", (double)n * l1test_width * 1 /
438             ((t3 - t2) - (t2 - t1)) / 1000000.);
439     fflush (stdout);
440
441     memcpy (src, dst, BUFSIZE);
442     memcpy (dst, src, BUFSIZE);
443
444     nlines = (L2CACHE_SIZE / l1test_width) /
445         ((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8);
446     if (nlines < 1)
447         nlines = 1;
448     n = 1 + npix / (l1test_width * nlines);
449     t1 = gettime ();
450 #if EXCLUDE_OVERHEAD
451     bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, nlines);
452 #endif
453     t2 = gettime ();
454     bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, nlines);
455     t3 = gettime ();
456     printf ("  L2:%7.2f", (double)n * l1test_width * nlines /
457             ((t3 - t2) - (t2 - t1)) / 1000000.);
458     fflush (stdout);
459
460     memcpy (src, dst, BUFSIZE);
461     memcpy (dst, src, BUFSIZE);
462
463     n = 1 + npix / (WIDTH * HEIGHT);
464     t1 = gettime ();
465 #if EXCLUDE_OVERHEAD
466     bench_M (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
467 #endif
468     t2 = gettime ();
469     bench_M (op, src_img, mask_img, dst_img, n, func);
470     t3 = gettime ();
471     printf ("  M:%6.2f (%6.2f%%)",
472         ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1))) / 1000000.,
473         ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) );
474     fflush (stdout);
475
476     memcpy (src, dst, BUFSIZE);
477     memcpy (dst, src, BUFSIZE);
478
479     n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
480     t1 = gettime ();
481 #if EXCLUDE_OVERHEAD
482     pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
483 #endif
484     t2 = gettime ();
485     pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, func);
486     t3 = gettime ();
487     printf ("  HT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
488     fflush (stdout);
489
490     memcpy (src, dst, BUFSIZE);
491     memcpy (dst, src, BUFSIZE);
492
493     n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
494     t1 = gettime ();
495 #if EXCLUDE_OVERHEAD
496     pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
497 #endif
498     t2 = gettime ();
499     pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, func);
500     t3 = gettime ();
501     printf ("  VT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
502     fflush (stdout);
503
504     memcpy (src, dst, BUFSIZE);
505     memcpy (dst, src, BUFSIZE);
506
507     n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
508     t1 = gettime ();
509 #if EXCLUDE_OVERHEAD
510     pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
511 #endif
512     t2 = gettime ();
513     pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
514     t3 = gettime ();
515     printf ("  R:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
516     fflush (stdout);
517
518     memcpy (src, dst, BUFSIZE);
519     memcpy (dst, src, BUFSIZE);
520
521     n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH);
522     t1 = gettime ();
523 #if EXCLUDE_OVERHEAD
524     pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
525 #endif
526     t2 = gettime ();
527     pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
528     t3 = gettime ();
529     printf ("  RT:%6.2f (%4.0fKops/s)\n", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000., (double) n / ((t3 - t2) * 1000));
530
531     if (mask_img) {
532         pixman_image_unref (mask_img);
533         pixman_image_unref (xmask_img);
534     }
535     pixman_image_unref (src_img);
536     pixman_image_unref (dst_img);
537     pixman_image_unref (xsrc_img);
538     pixman_image_unref (xdst_img);
539 }
540
541 #define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE)
542
543 struct
544 {
545     char *testname;
546     int   src_fmt;
547     int   src_flags;
548     int   op;
549     int   mask_fmt;
550     int   mask_flags;
551     int   dst_fmt;
552 }
553 tests_tbl[] =
554 {
555     { "add_8_8_8",             PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
556     { "add_n_8_8",             PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
557     { "add_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
558     { "add_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
559     { "add_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
560     { "add_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
561     { "add_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
562     { "add_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
563     { "add_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
564     { "add_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
565     { "add_n_8",               PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
566     { "add_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
567     { "add_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
568     { "add_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
569     { "add_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
570     { "add_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
571     { "add_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
572     { "add_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
573     { "add_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
574     { "add_8_8",               PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
575     { "add_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
576     { "add_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
577     { "add_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
578     { "add_8888_1555",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
579     { "add_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
580     { "add_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
581     { "add_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
582     { "add_1555_1555",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
583     { "add_0565_2x10",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
584     { "add_2a10_2a10",         PIXMAN_a2r10g10b10, 0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
585     { "in_n_8_8",              PIXMAN_a8r8g8b8,    1, PIXMAN_OP_IN,      PIXMAN_a8,       0, PIXMAN_a8 },
586     { "in_8_8",                PIXMAN_a8,          0, PIXMAN_OP_IN,      PIXMAN_null,     0, PIXMAN_a8 },
587     { "src_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
588     { "src_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
589     { "src_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
590     { "src_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
591     { "src_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
592     { "src_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
593     { "src_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
594     { "src_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
595     { "src_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
596     { "src_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
597     { "src_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
598     { "src_8888_2x10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
599     { "src_8888_2a10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
600     { "src_0888_0565",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
601     { "src_0888_8888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
602     { "src_0888_x888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
603     { "src_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
604     { "src_x888_8888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
605     { "src_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
606     { "src_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
607     { "src_1555_0565",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
608     { "src_0565_1555",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
609     { "src_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
610     { "src_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
611     { "src_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
612     { "src_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
613     { "src_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
614     { "src_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
615     { "src_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
616     { "src_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
617     { "src_8888_8_0565",       PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
618     { "src_0888_8_0565",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
619     { "src_0888_8_8888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
620     { "src_0888_8_x888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
621     { "src_x888_8_x888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
622     { "src_x888_8_8888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
623     { "src_0565_8_0565",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
624     { "src_1555_8_0565",       PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
625     { "src_0565_8_1555",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
626     { "over_n_x888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
627     { "over_n_8888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
628     { "over_n_0565",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
629     { "over_n_1555",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
630     { "over_8888_0565",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
631     { "over_8888_8888",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
632     { "over_8888_x888",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
633     { "over_x888_8_0565",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_r5g6b5 },
634     { "over_x888_8_8888",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
635     { "over_n_8_0565",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_r5g6b5 },
636     { "over_n_8_1555",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
637     { "over_n_8_4444",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
638     { "over_n_8_2222",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
639     { "over_n_8_x888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
640     { "over_n_8_8888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
641     { "over_n_8_2x10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
642     { "over_n_8_2a10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
643     { "over_n_8888_8888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
644     { "over_n_8888_x888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
645     { "over_n_8888_0565_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
646     { "over_n_8888_1555_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
647     { "over_n_8888_4444_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a4r4g4b4 },
648     { "over_n_8888_2222_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r2g2b2 },
649     { "over_n_8888_2x10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x2r10g10b10 },
650     { "over_n_8888_2a10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r10g10b10 },
651     { "over_8888_n_8888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a8r8g8b8 },
652     { "over_8888_n_x888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_x8r8g8b8 },
653     { "over_8888_n_0565",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_r5g6b5 },
654     { "over_8888_n_1555",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a1r5g5b5 },
655     { "over_x888_n_8888",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a8r8g8b8 },
656     { "outrev_n_8_0565",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_r5g6b5 },
657     { "outrev_n_8_1555",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
658     { "outrev_n_8_x888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
659     { "outrev_n_8_8888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
660     { "outrev_n_8888_0565_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
661     { "outrev_n_8888_1555_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
662     { "outrev_n_8888_x888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
663     { "outrev_n_8888_8888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
664 };
665
666 int
667 main (int argc, char *argv[])
668 {
669     double x;
670     int i;
671     char *pattern = argc > 1 ? argv[1] : "all";
672
673     src = aligned_malloc (4096, BUFSIZE * 3);
674     memset (src, 0xCC, BUFSIZE * 3);
675     dst = src + (BUFSIZE / 4);
676     mask = dst + (BUFSIZE / 4);
677
678     printf ("Benchmark for a set of most commonly used functions\n");
679     printf ("---\n");
680     printf ("All results are presented in millions of pixels per second\n");
681     printf ("L1  - small Xx1 rectangle (fitting L1 cache), always blitted at the same\n");
682     printf ("      memory location with small drift in horizontal direction\n");
683     printf ("L2  - small XxY rectangle (fitting L2 cache), always blitted at the same\n");
684     printf ("      memory location with small drift in horizontal direction\n");
685     printf ("M   - large %dx%d rectangle, always blitted at the same\n",
686             WIDTH - 64, HEIGHT);
687     printf ("      memory location with small drift in horizontal direction\n");
688     printf ("HT  - random rectangles with %dx%d average size are copied from\n",
689             TILEWIDTH, TILEWIDTH);
690     printf ("      one %dx%d buffer to another, traversing from left to right\n",
691             WIDTH, HEIGHT);
692     printf ("      and from top to bottom\n");
693     printf ("VT  - random rectangles with %dx%d average size are copied from\n",
694             TILEWIDTH, TILEWIDTH);
695     printf ("      one %dx%d buffer to another, traversing from top to bottom\n",
696             WIDTH, HEIGHT);
697     printf ("      and from left to right\n");
698     printf ("R   - random rectangles with %dx%d average size are copied from\n",
699             TILEWIDTH, TILEWIDTH);
700     printf ("      random locations of one %dx%d buffer to another\n",
701             WIDTH, HEIGHT);
702     printf ("RT  - as R, but %dx%d average sized rectangles are copied\n",
703             TINYWIDTH, TINYWIDTH);
704     printf ("---\n");
705     bandwidth = x = bench_memcpy ();
706     printf ("reference memcpy speed = %.1fMB/s (%.1fMP/s for 32bpp fills)\n",
707             x / 1000000., x / 4000000);
708     printf ("---\n");
709
710     for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++)
711     {
712         if (strcmp (pattern, "all") == 0 || strstr (tests_tbl[i].testname, pattern))
713         {
714             bench_composite (tests_tbl[i].testname,
715                              tests_tbl[i].src_fmt,
716                              tests_tbl[i].src_flags,
717                              tests_tbl[i].op,
718                              tests_tbl[i].mask_fmt,
719                              tests_tbl[i].mask_flags,
720                              tests_tbl[i].dst_fmt,
721                              bandwidth/8);
722         }
723     }
724
725     free (src);
726     return 0;
727 }