lowlevel-blt-bench.c revision 6ca29ff0
11b18d63aSmrg/*
21b18d63aSmrg * Copyright © 2009 Nokia Corporation
31b18d63aSmrg * Copyright © 2010 Movial Creative Technologies Oy
41b18d63aSmrg *
51b18d63aSmrg * Permission is hereby granted, free of charge, to any person obtaining a
61b18d63aSmrg * copy of this software and associated documentation files (the "Software"),
71b18d63aSmrg * to deal in the Software without restriction, including without limitation
81b18d63aSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
91b18d63aSmrg * and/or sell copies of the Software, and to permit persons to whom the
101b18d63aSmrg * Software is furnished to do so, subject to the following conditions:
111b18d63aSmrg *
121b18d63aSmrg * The above copyright notice and this permission notice (including the next
131b18d63aSmrg * paragraph) shall be included in all copies or substantial portions of the
141b18d63aSmrg * Software.
151b18d63aSmrg *
161b18d63aSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171b18d63aSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181b18d63aSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
191b18d63aSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201b18d63aSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
211b18d63aSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
221b18d63aSmrg * DEALINGS IN THE SOFTWARE.
231b18d63aSmrg */
241b18d63aSmrg
251b18d63aSmrg#include <stdio.h>
261b18d63aSmrg#include <stdlib.h>
271b18d63aSmrg#include <string.h>
281b18d63aSmrg#include "utils.h"
291b18d63aSmrg
301b18d63aSmrg#define SOLID_FLAG 1
311b18d63aSmrg#define CA_FLAG    2
321b18d63aSmrg
331b18d63aSmrg#define L1CACHE_SIZE (8 * 1024)
341b18d63aSmrg#define L2CACHE_SIZE (128 * 1024)
351b18d63aSmrg
36f4f78bb6Smrg/* This is applied to both L1 and L2 tests - alternatively, you could
37f4f78bb6Smrg * parameterise bench_L or split it into two functions. It could be
38f4f78bb6Smrg * read at runtime on some architectures, but it only really matters
39f4f78bb6Smrg * that it's a number that's an integer divisor of both cacheline
40f4f78bb6Smrg * lengths, and further, it only really matters for caches that don't
41f4f78bb6Smrg * do allocate0on-write. */
42f4f78bb6Smrg#define CACHELINE_LENGTH (32) /* bytes */
43f4f78bb6Smrg
441b18d63aSmrg#define WIDTH  1920
451b18d63aSmrg#define HEIGHT 1080
461b18d63aSmrg#define BUFSIZE (WIDTH * HEIGHT * 4)
471b18d63aSmrg#define XWIDTH 256
481b18d63aSmrg#define XHEIGHT 256
491b18d63aSmrg#define TILEWIDTH 32
501b18d63aSmrg#define TINYWIDTH 8
511b18d63aSmrg
521b18d63aSmrg#define EXCLUDE_OVERHEAD 1
531b18d63aSmrg
541b18d63aSmrguint32_t *dst;
551b18d63aSmrguint32_t *src;
561b18d63aSmrguint32_t *mask;
571b18d63aSmrg
586ca29ff0Smrgdouble bandwidth = 0.0;
591b18d63aSmrg
601b18d63aSmrgdouble
611b18d63aSmrgbench_memcpy ()
621b18d63aSmrg{
631b18d63aSmrg    int64_t n = 0, total;
641b18d63aSmrg    double  t1, t2;
651b18d63aSmrg    int     x = 0;
661b18d63aSmrg
671b18d63aSmrg    t1 = gettime ();
681b18d63aSmrg    while (1)
691b18d63aSmrg    {
701b18d63aSmrg	memcpy (dst, src, BUFSIZE - 64);
711b18d63aSmrg	memcpy (src, dst, BUFSIZE - 64);
721b18d63aSmrg	n += 4 * (BUFSIZE - 64);
731b18d63aSmrg	t2 = gettime ();
741b18d63aSmrg	if (t2 - t1 > 0.5)
751b18d63aSmrg	    break;
761b18d63aSmrg    }
771b18d63aSmrg    n = total = n * 5;
781b18d63aSmrg    t1 = gettime ();
791b18d63aSmrg    while (n > 0)
801b18d63aSmrg    {
811b18d63aSmrg	if (++x >= 64)
821b18d63aSmrg	    x = 0;
831b18d63aSmrg	memcpy ((char *)dst + 1, (char *)src + x, BUFSIZE - 64);
841b18d63aSmrg	memcpy ((char *)src + 1, (char *)dst + x, BUFSIZE - 64);
851b18d63aSmrg	n -= 4 * (BUFSIZE - 64);
861b18d63aSmrg    }
871b18d63aSmrg    t2 = gettime ();
881b18d63aSmrg    return (double)total / (t2 - t1);
891b18d63aSmrg}
901b18d63aSmrg
919ad247e8Sjmcneillstatic pixman_bool_t use_scaling = FALSE;
929ad247e8Sjmcneillstatic pixman_filter_t filter = PIXMAN_FILTER_NEAREST;
936ca29ff0Smrgstatic pixman_bool_t use_csv_output = FALSE;
949ad247e8Sjmcneill
959ad247e8Sjmcneill/* nearly 1x scale factor */
969ad247e8Sjmcneillstatic pixman_transform_t m =
979ad247e8Sjmcneill{
989ad247e8Sjmcneill    {
999ad247e8Sjmcneill        { pixman_fixed_1 + 1, 0,              0              },
1009ad247e8Sjmcneill        { 0,                  pixman_fixed_1, 0              },
1019ad247e8Sjmcneill        { 0,                  0,              pixman_fixed_1 }
1029ad247e8Sjmcneill    }
1039ad247e8Sjmcneill};
1049ad247e8Sjmcneill
1051b18d63aSmrgstatic void
1061b18d63aSmrgpixman_image_composite_wrapper (pixman_implementation_t *impl,
1076ba797d6Smrg				pixman_composite_info_t *info)
1081b18d63aSmrg{
1099ad247e8Sjmcneill    if (use_scaling)
1109ad247e8Sjmcneill    {
1119ad247e8Sjmcneill        pixman_image_set_filter (info->src_image, filter, NULL, 0);
1129ad247e8Sjmcneill        pixman_image_set_transform(info->src_image, &m);
1139ad247e8Sjmcneill    }
1146ba797d6Smrg    pixman_image_composite (info->op,
1156ba797d6Smrg			    info->src_image, info->mask_image, info->dest_image,
1166ba797d6Smrg			    info->src_x, info->src_y,
1176ba797d6Smrg			    info->mask_x, info->mask_y,
1186ba797d6Smrg			    info->dest_x, info->dest_y,
1196ba797d6Smrg			    info->width, info->height);
1201b18d63aSmrg}
1211b18d63aSmrg
1221b18d63aSmrgstatic void
1231b18d63aSmrgpixman_image_composite_empty (pixman_implementation_t *impl,
1246ba797d6Smrg			      pixman_composite_info_t *info)
1251b18d63aSmrg{
1269ad247e8Sjmcneill    if (use_scaling)
1279ad247e8Sjmcneill    {
1289ad247e8Sjmcneill        pixman_image_set_filter (info->src_image, filter, NULL, 0);
1299ad247e8Sjmcneill        pixman_image_set_transform(info->src_image, &m);
1309ad247e8Sjmcneill    }
1316ba797d6Smrg    pixman_image_composite (info->op,
1326ba797d6Smrg			    info->src_image, info->mask_image, info->dest_image,
1336ba797d6Smrg			    0, 0, 0, 0, 0, 0, 1, 1);
1346ba797d6Smrg}
1356ba797d6Smrg
1366ba797d6Smrgstatic inline void
1376ba797d6Smrgcall_func (pixman_composite_func_t func,
1386ba797d6Smrg	   pixman_op_t             op,
1396ba797d6Smrg	   pixman_image_t *        src_image,
1406ba797d6Smrg	   pixman_image_t *        mask_image,
1416ba797d6Smrg	   pixman_image_t *        dest_image,
1426ba797d6Smrg	   int32_t		   src_x,
1436ba797d6Smrg	   int32_t		   src_y,
1446ba797d6Smrg	   int32_t                 mask_x,
1456ba797d6Smrg	   int32_t                 mask_y,
1466ba797d6Smrg	   int32_t                 dest_x,
1476ba797d6Smrg	   int32_t                 dest_y,
1486ba797d6Smrg	   int32_t                 width,
1496ba797d6Smrg	   int32_t                 height)
1506ba797d6Smrg{
1516ba797d6Smrg    pixman_composite_info_t info;
1526ba797d6Smrg
1536ba797d6Smrg    info.op = op;
1546ba797d6Smrg    info.src_image = src_image;
1556ba797d6Smrg    info.mask_image = mask_image;
1566ba797d6Smrg    info.dest_image = dest_image;
1576ba797d6Smrg    info.src_x = src_x;
1586ba797d6Smrg    info.src_y = src_y;
1596ba797d6Smrg    info.mask_x = mask_x;
1606ba797d6Smrg    info.mask_y = mask_y;
1616ba797d6Smrg    info.dest_x = dest_x;
1626ba797d6Smrg    info.dest_y = dest_y;
1636ba797d6Smrg    info.width = width;
1646ba797d6Smrg    info.height = height;
1656ba797d6Smrg
1666ba797d6Smrg    func (0, &info);
1671b18d63aSmrg}
1681b18d63aSmrg
1696ca29ff0Smrgdouble
1701b18d63aSmrgnoinline
1711b18d63aSmrgbench_L  (pixman_op_t              op,
1721b18d63aSmrg          pixman_image_t *         src_img,
1731b18d63aSmrg          pixman_image_t *         mask_img,
1741b18d63aSmrg          pixman_image_t *         dst_img,
1751b18d63aSmrg          int64_t                  n,
1761b18d63aSmrg          pixman_composite_func_t  func,
1771b18d63aSmrg          int                      width,
1781b18d63aSmrg          int                      lines_count)
1791b18d63aSmrg{
180f4f78bb6Smrg    int64_t      i, j, k;
1811b18d63aSmrg    int          x = 0;
1821b18d63aSmrg    int          q = 0;
1831b18d63aSmrg    volatile int qx;
1841b18d63aSmrg
1851b18d63aSmrg    for (i = 0; i < n; i++)
1861b18d63aSmrg    {
187f4f78bb6Smrg        /* For caches without allocate-on-write, we need to force the
188f4f78bb6Smrg         * destination buffer back into the cache on each iteration,
189f4f78bb6Smrg         * otherwise if they are evicted during the test, they remain
190f4f78bb6Smrg         * uncached. This doesn't matter for tests which read the
191f4f78bb6Smrg         * destination buffer, or for caches that do allocate-on-write,
192f4f78bb6Smrg         * but in those cases this loop just adds constant time, which
193f4f78bb6Smrg         * should be successfully cancelled out.
194f4f78bb6Smrg         */
195f4f78bb6Smrg        for (j = 0; j < lines_count; j++)
196f4f78bb6Smrg        {
197f4f78bb6Smrg            for (k = 0; k < width + 62; k += CACHELINE_LENGTH / sizeof *dst)
198f4f78bb6Smrg            {
199f4f78bb6Smrg                q += dst[j * WIDTH + k];
200f4f78bb6Smrg            }
201f4f78bb6Smrg            q += dst[j * WIDTH + width + 62];
202f4f78bb6Smrg        }
2031b18d63aSmrg	if (++x >= 64)
2041b18d63aSmrg	    x = 0;
2056ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 63 - x, 0, width, lines_count);
2061b18d63aSmrg    }
2071b18d63aSmrg    qx = q;
2086ca29ff0Smrg
2096ca29ff0Smrg    return (double)n * lines_count * width;
2101b18d63aSmrg}
2111b18d63aSmrg
2126ca29ff0Smrgdouble
2131b18d63aSmrgnoinline
2141b18d63aSmrgbench_M (pixman_op_t              op,
2151b18d63aSmrg         pixman_image_t *         src_img,
2161b18d63aSmrg         pixman_image_t *         mask_img,
2171b18d63aSmrg         pixman_image_t *         dst_img,
2181b18d63aSmrg         int64_t                  n,
2191b18d63aSmrg         pixman_composite_func_t  func)
2201b18d63aSmrg{
2211b18d63aSmrg    int64_t i;
2221b18d63aSmrg    int     x = 0;
2231b18d63aSmrg
2241b18d63aSmrg    for (i = 0; i < n; i++)
2251b18d63aSmrg    {
2261b18d63aSmrg	if (++x >= 64)
2271b18d63aSmrg	    x = 0;
2286ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, x, 0, x, 0, 1, 0, WIDTH - 64, HEIGHT);
2291b18d63aSmrg    }
2306ca29ff0Smrg
2316ca29ff0Smrg    return (double)n * (WIDTH - 64) * HEIGHT;
2321b18d63aSmrg}
2331b18d63aSmrg
2341b18d63aSmrgdouble
2351b18d63aSmrgnoinline
2361b18d63aSmrgbench_HT (pixman_op_t              op,
2371b18d63aSmrg          pixman_image_t *         src_img,
2381b18d63aSmrg          pixman_image_t *         mask_img,
2391b18d63aSmrg          pixman_image_t *         dst_img,
2401b18d63aSmrg          int64_t                  n,
2411b18d63aSmrg          pixman_composite_func_t  func)
2421b18d63aSmrg{
2431b18d63aSmrg    double  pix_cnt = 0;
2441b18d63aSmrg    int     x = 0;
2451b18d63aSmrg    int     y = 0;
2461b18d63aSmrg    int64_t i;
2471b18d63aSmrg
2481b18d63aSmrg    srand (0);
2491b18d63aSmrg    for (i = 0; i < n; i++)
2501b18d63aSmrg    {
2511b18d63aSmrg	int w = (rand () % (TILEWIDTH * 2)) + 1;
2521b18d63aSmrg	int h = (rand () % (TILEWIDTH * 2)) + 1;
2531b18d63aSmrg	if (x + w > WIDTH)
2541b18d63aSmrg	{
2551b18d63aSmrg	    x = 0;
2561b18d63aSmrg	    y += TILEWIDTH * 2;
2571b18d63aSmrg	}
2581b18d63aSmrg	if (y + h > HEIGHT)
2591b18d63aSmrg	{
2601b18d63aSmrg	    y = 0;
2611b18d63aSmrg	}
2626ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
2631b18d63aSmrg	x += w;
2641b18d63aSmrg	pix_cnt += w * h;
2651b18d63aSmrg    }
2661b18d63aSmrg    return pix_cnt;
2671b18d63aSmrg}
2681b18d63aSmrg
2691b18d63aSmrgdouble
2701b18d63aSmrgnoinline
2711b18d63aSmrgbench_VT (pixman_op_t              op,
2721b18d63aSmrg          pixman_image_t *         src_img,
2731b18d63aSmrg          pixman_image_t *         mask_img,
2741b18d63aSmrg          pixman_image_t *         dst_img,
2751b18d63aSmrg          int64_t                  n,
2761b18d63aSmrg          pixman_composite_func_t  func)
2771b18d63aSmrg{
2781b18d63aSmrg    double  pix_cnt = 0;
2791b18d63aSmrg    int     x = 0;
2801b18d63aSmrg    int     y = 0;
2811b18d63aSmrg    int64_t i;
2821b18d63aSmrg
2831b18d63aSmrg    srand (0);
2841b18d63aSmrg    for (i = 0; i < n; i++)
2851b18d63aSmrg    {
2861b18d63aSmrg	int w = (rand () % (TILEWIDTH * 2)) + 1;
2871b18d63aSmrg	int h = (rand () % (TILEWIDTH * 2)) + 1;
2881b18d63aSmrg	if (y + h > HEIGHT)
2891b18d63aSmrg	{
2901b18d63aSmrg	    y = 0;
2911b18d63aSmrg	    x += TILEWIDTH * 2;
2921b18d63aSmrg	}
2931b18d63aSmrg	if (x + w > WIDTH)
2941b18d63aSmrg	{
2951b18d63aSmrg	    x = 0;
2961b18d63aSmrg	}
2976ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
2981b18d63aSmrg	y += h;
2991b18d63aSmrg	pix_cnt += w * h;
3001b18d63aSmrg    }
3011b18d63aSmrg    return pix_cnt;
3021b18d63aSmrg}
3031b18d63aSmrg
3041b18d63aSmrgdouble
3051b18d63aSmrgnoinline
3061b18d63aSmrgbench_R (pixman_op_t              op,
3071b18d63aSmrg         pixman_image_t *         src_img,
3081b18d63aSmrg         pixman_image_t *         mask_img,
3091b18d63aSmrg         pixman_image_t *         dst_img,
3101b18d63aSmrg         int64_t                  n,
3111b18d63aSmrg         pixman_composite_func_t  func,
3121b18d63aSmrg         int                      maxw,
3131b18d63aSmrg         int                      maxh)
3141b18d63aSmrg{
3151b18d63aSmrg    double  pix_cnt = 0;
3161b18d63aSmrg    int64_t i;
3171b18d63aSmrg
3181b18d63aSmrg    if (maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2)
3191b18d63aSmrg    {
3201b18d63aSmrg	printf("error: maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2\n");
3211b18d63aSmrg        return 0;
3221b18d63aSmrg    }
3231b18d63aSmrg
3241b18d63aSmrg    srand (0);
3251b18d63aSmrg    for (i = 0; i < n; i++)
3261b18d63aSmrg    {
3271b18d63aSmrg	int w = (rand () % (TILEWIDTH * 2)) + 1;
3281b18d63aSmrg	int h = (rand () % (TILEWIDTH * 2)) + 1;
3291b18d63aSmrg	int sx = rand () % (maxw - TILEWIDTH * 2);
3301b18d63aSmrg	int sy = rand () % (maxh - TILEWIDTH * 2);
3311b18d63aSmrg	int dx = rand () % (maxw - TILEWIDTH * 2);
3321b18d63aSmrg	int dy = rand () % (maxh - TILEWIDTH * 2);
3336ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
3341b18d63aSmrg	pix_cnt += w * h;
3351b18d63aSmrg    }
3361b18d63aSmrg    return pix_cnt;
3371b18d63aSmrg}
3381b18d63aSmrg
3391b18d63aSmrgdouble
3401b18d63aSmrgnoinline
3411b18d63aSmrgbench_RT (pixman_op_t              op,
3421b18d63aSmrg          pixman_image_t *         src_img,
3431b18d63aSmrg          pixman_image_t *         mask_img,
3441b18d63aSmrg          pixman_image_t *         dst_img,
3451b18d63aSmrg          int64_t                  n,
3461b18d63aSmrg          pixman_composite_func_t  func,
3471b18d63aSmrg          int                      maxw,
3481b18d63aSmrg          int                      maxh)
3491b18d63aSmrg{
3501b18d63aSmrg    double  pix_cnt = 0;
3511b18d63aSmrg    int64_t i;
3521b18d63aSmrg
3531b18d63aSmrg    if (maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2)
3541b18d63aSmrg    {
3551b18d63aSmrg	printf("error: maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2\n");
3561b18d63aSmrg        return 0;
3571b18d63aSmrg    }
3581b18d63aSmrg
3591b18d63aSmrg    srand (0);
3601b18d63aSmrg    for (i = 0; i < n; i++)
3611b18d63aSmrg    {
3621b18d63aSmrg	int w = (rand () % (TINYWIDTH * 2)) + 1;
3631b18d63aSmrg	int h = (rand () % (TINYWIDTH * 2)) + 1;
3641b18d63aSmrg	int sx = rand () % (maxw - TINYWIDTH * 2);
3651b18d63aSmrg	int sy = rand () % (maxh - TINYWIDTH * 2);
3661b18d63aSmrg	int dx = rand () % (maxw - TINYWIDTH * 2);
3671b18d63aSmrg	int dy = rand () % (maxh - TINYWIDTH * 2);
3686ba797d6Smrg	call_func (func, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
3691b18d63aSmrg	pix_cnt += w * h;
3701b18d63aSmrg    }
3711b18d63aSmrg    return pix_cnt;
3721b18d63aSmrg}
3731b18d63aSmrg
3746ca29ff0Smrgstatic double
3756ca29ff0SmrgMpx_per_sec (double pix_cnt, double t1, double t2, double t3)
3766ca29ff0Smrg{
3776ca29ff0Smrg    double overhead = t2 - t1;
3786ca29ff0Smrg    double testtime = t3 - t2;
3796ca29ff0Smrg
3806ca29ff0Smrg    return pix_cnt / (testtime - overhead) / 1e6;
3816ca29ff0Smrg}
3826ca29ff0Smrg
3831b18d63aSmrgvoid
3846ca29ff0Smrgbench_composite (const char *testname,
3856ca29ff0Smrg                 int         src_fmt,
3866ca29ff0Smrg                 int         src_flags,
3876ca29ff0Smrg                 int         op,
3886ca29ff0Smrg                 int         mask_fmt,
3896ca29ff0Smrg                 int         mask_flags,
3906ca29ff0Smrg                 int         dst_fmt,
3916ca29ff0Smrg                 double      npix)
3921b18d63aSmrg{
3931b18d63aSmrg    pixman_image_t *                src_img;
3941b18d63aSmrg    pixman_image_t *                dst_img;
3951b18d63aSmrg    pixman_image_t *                mask_img;
3961b18d63aSmrg    pixman_image_t *                xsrc_img;
3971b18d63aSmrg    pixman_image_t *                xdst_img;
3981b18d63aSmrg    pixman_image_t *                xmask_img;
3991b18d63aSmrg    double                          t1, t2, t3, pix_cnt;
4001b18d63aSmrg    int64_t                         n, l1test_width, nlines;
4011b18d63aSmrg    double                             bytes_per_pix = 0;
402f4f78bb6Smrg    pixman_bool_t                   bench_pixbuf = FALSE;
4031b18d63aSmrg
4041b18d63aSmrg    pixman_composite_func_t func = pixman_image_composite_wrapper;
4051b18d63aSmrg
4061b18d63aSmrg    if (!(src_flags & SOLID_FLAG))
4071b18d63aSmrg    {
4081b18d63aSmrg        bytes_per_pix += (src_fmt >> 24) / 8.0;
4091b18d63aSmrg        src_img = pixman_image_create_bits (src_fmt,
4101b18d63aSmrg                                            WIDTH, HEIGHT,
4111b18d63aSmrg                                            src,
4121b18d63aSmrg                                            WIDTH * 4);
4131b18d63aSmrg        xsrc_img = pixman_image_create_bits (src_fmt,
4141b18d63aSmrg                                             XWIDTH, XHEIGHT,
4151b18d63aSmrg                                             src,
4161b18d63aSmrg                                             XWIDTH * 4);
4171b18d63aSmrg    }
4181b18d63aSmrg    else
4191b18d63aSmrg    {
4201b18d63aSmrg        src_img = pixman_image_create_bits (src_fmt,
4211b18d63aSmrg                                            1, 1,
4221b18d63aSmrg                                            src,
4231b18d63aSmrg                                            4);
4241b18d63aSmrg        xsrc_img = pixman_image_create_bits (src_fmt,
4251b18d63aSmrg                                             1, 1,
4261b18d63aSmrg                                             src,
4271b18d63aSmrg                                             4);
4281b18d63aSmrg        pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
4291b18d63aSmrg        pixman_image_set_repeat (xsrc_img, PIXMAN_REPEAT_NORMAL);
4301b18d63aSmrg    }
4311b18d63aSmrg
4321b18d63aSmrg    bytes_per_pix += (dst_fmt >> 24) / 8.0;
4331b18d63aSmrg    dst_img = pixman_image_create_bits (dst_fmt,
4341b18d63aSmrg                                        WIDTH, HEIGHT,
4351b18d63aSmrg                                        dst,
4361b18d63aSmrg                                        WIDTH * 4);
4371b18d63aSmrg
4381b18d63aSmrg    mask_img = NULL;
4391b18d63aSmrg    xmask_img = NULL;
440f4f78bb6Smrg    if (strcmp (testname, "pixbuf") == 0 || strcmp (testname, "rpixbuf") == 0)
441f4f78bb6Smrg    {
442f4f78bb6Smrg        bench_pixbuf = TRUE;
443f4f78bb6Smrg    }
4441b18d63aSmrg    if (!(mask_flags & SOLID_FLAG) && mask_fmt != PIXMAN_null)
4451b18d63aSmrg    {
4461b18d63aSmrg        bytes_per_pix += (mask_fmt >> 24) / ((op == PIXMAN_OP_SRC) ? 8.0 : 4.0);
4471b18d63aSmrg        mask_img = pixman_image_create_bits (mask_fmt,
4481b18d63aSmrg                                             WIDTH, HEIGHT,
449f4f78bb6Smrg                                             bench_pixbuf ? src : mask,
4501b18d63aSmrg                                             WIDTH * 4);
4511b18d63aSmrg        xmask_img = pixman_image_create_bits (mask_fmt,
4521b18d63aSmrg                                             XWIDTH, XHEIGHT,
453f4f78bb6Smrg                                             bench_pixbuf ? src : mask,
4541b18d63aSmrg                                             XWIDTH * 4);
4551b18d63aSmrg    }
4561b18d63aSmrg    else if (mask_fmt != PIXMAN_null)
4571b18d63aSmrg    {
4581b18d63aSmrg        mask_img = pixman_image_create_bits (mask_fmt,
4591b18d63aSmrg                                             1, 1,
4601b18d63aSmrg                                             mask,
4611b18d63aSmrg                                             4);
4621b18d63aSmrg        xmask_img = pixman_image_create_bits (mask_fmt,
4631b18d63aSmrg                                             1, 1,
4641b18d63aSmrg                                             mask,
4651b18d63aSmrg                                             4 * 4);
4661b18d63aSmrg       pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
4671b18d63aSmrg       pixman_image_set_repeat (xmask_img, PIXMAN_REPEAT_NORMAL);
4681b18d63aSmrg    }
4691b18d63aSmrg    if ((mask_flags & CA_FLAG) && mask_fmt != PIXMAN_null)
4701b18d63aSmrg    {
4711b18d63aSmrg       pixman_image_set_component_alpha (mask_img, 1);
4721b18d63aSmrg    }
4731b18d63aSmrg    xdst_img = pixman_image_create_bits (dst_fmt,
4741b18d63aSmrg                                         XWIDTH, XHEIGHT,
4751b18d63aSmrg                                         dst,
4761b18d63aSmrg                                         XWIDTH * 4);
4771b18d63aSmrg
4786ca29ff0Smrg    if (!use_csv_output)
4796ca29ff0Smrg        printf ("%24s %c", testname, func != pixman_image_composite_wrapper ?
4806ca29ff0Smrg                '-' : '=');
4811b18d63aSmrg
4821b18d63aSmrg    memcpy (dst, src, BUFSIZE);
483f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
4841b18d63aSmrg
4851b18d63aSmrg    l1test_width = L1CACHE_SIZE / 8 - 64;
4861b18d63aSmrg    if (l1test_width < 1)
4871b18d63aSmrg	l1test_width = 1;
4881b18d63aSmrg    if (l1test_width > WIDTH - 64)
4891b18d63aSmrg	l1test_width = WIDTH - 64;
4901b18d63aSmrg    n = 1 + npix / (l1test_width * 8);
4911b18d63aSmrg    t1 = gettime ();
4921b18d63aSmrg#if EXCLUDE_OVERHEAD
4936ca29ff0Smrg    pix_cnt = bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, 1);
4941b18d63aSmrg#endif
4951b18d63aSmrg    t2 = gettime ();
4966ca29ff0Smrg    pix_cnt = bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, 1);
4971b18d63aSmrg    t3 = gettime ();
4986ca29ff0Smrg    if (use_csv_output)
4996ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5006ca29ff0Smrg    else
5016ca29ff0Smrg        printf ("  L1:%7.2f", Mpx_per_sec (pix_cnt, t1, t2, t3));
5021b18d63aSmrg    fflush (stdout);
5031b18d63aSmrg
5041b18d63aSmrg    memcpy (dst, src, BUFSIZE);
505f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5061b18d63aSmrg
5071b18d63aSmrg    nlines = (L2CACHE_SIZE / l1test_width) /
5081b18d63aSmrg	((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8);
5091b18d63aSmrg    if (nlines < 1)
5101b18d63aSmrg	nlines = 1;
5111b18d63aSmrg    n = 1 + npix / (l1test_width * nlines);
5121b18d63aSmrg    t1 = gettime ();
5131b18d63aSmrg#if EXCLUDE_OVERHEAD
5146ca29ff0Smrg    pix_cnt = bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, nlines);
5151b18d63aSmrg#endif
5161b18d63aSmrg    t2 = gettime ();
5176ca29ff0Smrg    pix_cnt = bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, nlines);
5181b18d63aSmrg    t3 = gettime ();
5196ca29ff0Smrg    if (use_csv_output)
5206ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5216ca29ff0Smrg    else
5226ca29ff0Smrg        printf ("  L2:%7.2f", Mpx_per_sec (pix_cnt, t1, t2, t3));
5231b18d63aSmrg    fflush (stdout);
5241b18d63aSmrg
5251b18d63aSmrg    memcpy (dst, src, BUFSIZE);
526f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5271b18d63aSmrg
5281b18d63aSmrg    n = 1 + npix / (WIDTH * HEIGHT);
5291b18d63aSmrg    t1 = gettime ();
5301b18d63aSmrg#if EXCLUDE_OVERHEAD
5316ca29ff0Smrg    pix_cnt = bench_M (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
5321b18d63aSmrg#endif
5331b18d63aSmrg    t2 = gettime ();
5346ca29ff0Smrg    pix_cnt = bench_M (op, src_img, mask_img, dst_img, n, func);
5351b18d63aSmrg    t3 = gettime ();
5366ca29ff0Smrg    if (use_csv_output)
5376ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5386ca29ff0Smrg    else
5396ca29ff0Smrg        printf ("  M:%6.2f (%6.2f%%)", Mpx_per_sec (pix_cnt, t1, t2, t3),
5406ca29ff0Smrg                (pix_cnt / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) );
5411b18d63aSmrg    fflush (stdout);
5421b18d63aSmrg
5431b18d63aSmrg    memcpy (dst, src, BUFSIZE);
544f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5451b18d63aSmrg
5461b18d63aSmrg    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
5471b18d63aSmrg    t1 = gettime ();
5481b18d63aSmrg#if EXCLUDE_OVERHEAD
5491b18d63aSmrg    pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
5501b18d63aSmrg#endif
5511b18d63aSmrg    t2 = gettime ();
5521b18d63aSmrg    pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, func);
5531b18d63aSmrg    t3 = gettime ();
5546ca29ff0Smrg    if (use_csv_output)
5556ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5566ca29ff0Smrg    else
5576ca29ff0Smrg        printf ("  HT:%6.2f", Mpx_per_sec (pix_cnt, t1, t2, t3));
5581b18d63aSmrg    fflush (stdout);
5591b18d63aSmrg
5601b18d63aSmrg    memcpy (dst, src, BUFSIZE);
561f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5621b18d63aSmrg
5631b18d63aSmrg    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
5641b18d63aSmrg    t1 = gettime ();
5651b18d63aSmrg#if EXCLUDE_OVERHEAD
5661b18d63aSmrg    pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
5671b18d63aSmrg#endif
5681b18d63aSmrg    t2 = gettime ();
5691b18d63aSmrg    pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, func);
5701b18d63aSmrg    t3 = gettime ();
5716ca29ff0Smrg    if (use_csv_output)
5726ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5736ca29ff0Smrg    else
5746ca29ff0Smrg        printf ("  VT:%6.2f", Mpx_per_sec (pix_cnt, t1, t2, t3));
5751b18d63aSmrg    fflush (stdout);
5761b18d63aSmrg
5771b18d63aSmrg    memcpy (dst, src, BUFSIZE);
578f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5791b18d63aSmrg
5801b18d63aSmrg    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
5811b18d63aSmrg    t1 = gettime ();
5821b18d63aSmrg#if EXCLUDE_OVERHEAD
5831b18d63aSmrg    pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
5841b18d63aSmrg#endif
5851b18d63aSmrg    t2 = gettime ();
5861b18d63aSmrg    pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
5871b18d63aSmrg    t3 = gettime ();
5886ca29ff0Smrg    if (use_csv_output)
5896ca29ff0Smrg        printf ("%g,", Mpx_per_sec (pix_cnt, t1, t2, t3));
5906ca29ff0Smrg    else
5916ca29ff0Smrg        printf ("  R:%6.2f", Mpx_per_sec (pix_cnt, t1, t2, t3));
5921b18d63aSmrg    fflush (stdout);
5931b18d63aSmrg
5941b18d63aSmrg    memcpy (dst, src, BUFSIZE);
595f4f78bb6Smrg    memcpy (src, dst, BUFSIZE);
5961b18d63aSmrg
5971b18d63aSmrg    n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH);
5981b18d63aSmrg    t1 = gettime ();
5991b18d63aSmrg#if EXCLUDE_OVERHEAD
6001b18d63aSmrg    pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
6011b18d63aSmrg#endif
6021b18d63aSmrg    t2 = gettime ();
6031b18d63aSmrg    pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
6041b18d63aSmrg    t3 = gettime ();
6056ca29ff0Smrg    if (use_csv_output)
6066ca29ff0Smrg        printf ("%g\n", Mpx_per_sec (pix_cnt, t1, t2, t3));
6076ca29ff0Smrg    else
6086ca29ff0Smrg        printf ("  RT:%6.2f (%4.0fKops/s)\n", Mpx_per_sec (pix_cnt, t1, t2, t3), (double) n / ((t3 - t2) * 1000));
6091b18d63aSmrg
6101b18d63aSmrg    if (mask_img) {
6111b18d63aSmrg	pixman_image_unref (mask_img);
6121b18d63aSmrg	pixman_image_unref (xmask_img);
6131b18d63aSmrg    }
6141b18d63aSmrg    pixman_image_unref (src_img);
6151b18d63aSmrg    pixman_image_unref (dst_img);
6161b18d63aSmrg    pixman_image_unref (xsrc_img);
6171b18d63aSmrg    pixman_image_unref (xdst_img);
6181b18d63aSmrg}
6191b18d63aSmrg
6201b18d63aSmrg#define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE)
6211b18d63aSmrg
6226ca29ff0Smrgstruct test_entry
6231b18d63aSmrg{
6246ca29ff0Smrg    const char *testname;
6256ca29ff0Smrg    int         src_fmt;
6266ca29ff0Smrg    int         src_flags;
6276ca29ff0Smrg    int         op;
6286ca29ff0Smrg    int         mask_fmt;
6296ca29ff0Smrg    int         mask_flags;
6306ca29ff0Smrg    int         dst_fmt;
6316ca29ff0Smrg};
6326ca29ff0Smrg
6336ca29ff0Smrgtypedef struct test_entry test_entry_t;
6346ca29ff0Smrg
6356ca29ff0Smrgstatic const test_entry_t tests_tbl[] =
6361b18d63aSmrg{
6371b18d63aSmrg    { "add_8_8_8",             PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
6381b18d63aSmrg    { "add_n_8_8",             PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
6391b18d63aSmrg    { "add_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
6401b18d63aSmrg    { "add_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
6411b18d63aSmrg    { "add_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
6421b18d63aSmrg    { "add_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
6431b18d63aSmrg    { "add_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
6441b18d63aSmrg    { "add_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
6451b18d63aSmrg    { "add_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
6461b18d63aSmrg    { "add_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
6471b18d63aSmrg    { "add_n_8",               PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
6481b18d63aSmrg    { "add_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6491b18d63aSmrg    { "add_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
6501b18d63aSmrg    { "add_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6511b18d63aSmrg    { "add_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
6521b18d63aSmrg    { "add_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
6531b18d63aSmrg    { "add_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
6541b18d63aSmrg    { "add_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
6551b18d63aSmrg    { "add_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
6561b18d63aSmrg    { "add_8_8",               PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
6571b18d63aSmrg    { "add_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
6581b18d63aSmrg    { "add_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6591b18d63aSmrg    { "add_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6601b18d63aSmrg    { "add_8888_1555",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
6611b18d63aSmrg    { "add_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
6621b18d63aSmrg    { "add_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
6631b18d63aSmrg    { "add_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6641b18d63aSmrg    { "add_1555_1555",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
6651b18d63aSmrg    { "add_0565_2x10",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
6661b18d63aSmrg    { "add_2a10_2a10",         PIXMAN_a2r10g10b10, 0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
6679ad247e8Sjmcneill    { "in_n_8_8",              PIXMAN_a8r8g8b8,    1, PIXMAN_OP_IN,      PIXMAN_a8,       0, PIXMAN_a8 },
6689ad247e8Sjmcneill    { "in_8_8",                PIXMAN_a8,          0, PIXMAN_OP_IN,      PIXMAN_null,     0, PIXMAN_a8 },
6691b18d63aSmrg    { "src_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
6701b18d63aSmrg    { "src_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6711b18d63aSmrg    { "src_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
6721b18d63aSmrg    { "src_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
6731b18d63aSmrg    { "src_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
6741b18d63aSmrg    { "src_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6751b18d63aSmrg    { "src_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
6761b18d63aSmrg    { "src_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
6771b18d63aSmrg    { "src_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
678f4f78bb6Smrg    { "src_0565_8888",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6791b18d63aSmrg    { "src_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
6801b18d63aSmrg    { "src_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
6811b18d63aSmrg    { "src_8888_2x10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
6821b18d63aSmrg    { "src_8888_2a10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
6831b18d63aSmrg    { "src_0888_0565",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6841b18d63aSmrg    { "src_0888_8888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6851b18d63aSmrg    { "src_0888_x888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
686f4f78bb6Smrg    { "src_0888_8888_rev",     PIXMAN_b8g8r8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
687f4f78bb6Smrg    { "src_0888_0565_rev",     PIXMAN_b8g8r8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6881b18d63aSmrg    { "src_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
6891b18d63aSmrg    { "src_x888_8888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6901b18d63aSmrg    { "src_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
6911b18d63aSmrg    { "src_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6921b18d63aSmrg    { "src_1555_0565",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
6931b18d63aSmrg    { "src_0565_1555",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
694f4f78bb6Smrg    { "src_8_8",               PIXMAN_a8,          0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8 },
695f4f78bb6Smrg    { "src_n_8",               PIXMAN_a8,          1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8 },
6961b18d63aSmrg    { "src_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
6971b18d63aSmrg    { "src_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
6981b18d63aSmrg    { "src_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
6991b18d63aSmrg    { "src_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
7001b18d63aSmrg    { "src_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
7011b18d63aSmrg    { "src_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7021b18d63aSmrg    { "src_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
7031b18d63aSmrg    { "src_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
7041b18d63aSmrg    { "src_8888_8_0565",       PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7051b18d63aSmrg    { "src_0888_8_0565",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7061b18d63aSmrg    { "src_0888_8_8888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7071b18d63aSmrg    { "src_0888_8_x888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
7081b18d63aSmrg    { "src_x888_8_x888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
7091b18d63aSmrg    { "src_x888_8_8888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7101b18d63aSmrg    { "src_0565_8_0565",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7111b18d63aSmrg    { "src_1555_8_0565",       PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7121b18d63aSmrg    { "src_0565_8_1555",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
7131b18d63aSmrg    { "over_n_x888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
7141b18d63aSmrg    { "over_n_8888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
7151b18d63aSmrg    { "over_n_0565",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
7161b18d63aSmrg    { "over_n_1555",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
7171b18d63aSmrg    { "over_8888_0565",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
7189ad247e8Sjmcneill    { "over_8888_8888",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
7191b18d63aSmrg    { "over_8888_x888",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
7206ba797d6Smrg    { "over_x888_8_0565",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7219ad247e8Sjmcneill    { "over_x888_8_8888",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7221b18d63aSmrg    { "over_n_8_0565",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7231b18d63aSmrg    { "over_n_8_1555",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
7241b18d63aSmrg    { "over_n_8_4444",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
7251b18d63aSmrg    { "over_n_8_2222",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
7261b18d63aSmrg    { "over_n_8_x888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
7271b18d63aSmrg    { "over_n_8_8888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7281b18d63aSmrg    { "over_n_8_2x10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
7291b18d63aSmrg    { "over_n_8_2a10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
7301b18d63aSmrg    { "over_n_8888_8888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
7311b18d63aSmrg    { "over_n_8888_x888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
7321b18d63aSmrg    { "over_n_8888_0565_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
7331b18d63aSmrg    { "over_n_8888_1555_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
7341b18d63aSmrg    { "over_n_8888_4444_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a4r4g4b4 },
7351b18d63aSmrg    { "over_n_8888_2222_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r2g2b2 },
7361b18d63aSmrg    { "over_n_8888_2x10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x2r10g10b10 },
7371b18d63aSmrg    { "over_n_8888_2a10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r10g10b10 },
7381b18d63aSmrg    { "over_8888_n_8888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a8r8g8b8 },
7391b18d63aSmrg    { "over_8888_n_x888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_x8r8g8b8 },
7401b18d63aSmrg    { "over_8888_n_0565",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_r5g6b5 },
7411b18d63aSmrg    { "over_8888_n_1555",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a1r5g5b5 },
7429ad247e8Sjmcneill    { "over_x888_n_8888",      PIXMAN_x8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a8r8g8b8 },
7431b18d63aSmrg    { "outrev_n_8_0565",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_r5g6b5 },
7441b18d63aSmrg    { "outrev_n_8_1555",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
7451b18d63aSmrg    { "outrev_n_8_x888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
7461b18d63aSmrg    { "outrev_n_8_8888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
7471b18d63aSmrg    { "outrev_n_8888_0565_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
7481b18d63aSmrg    { "outrev_n_8888_1555_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
7491b18d63aSmrg    { "outrev_n_8888_x888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
7501b18d63aSmrg    { "outrev_n_8888_8888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
7516ca29ff0Smrg    { "over_reverse_n_8888",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER_REVERSE, PIXMAN_null, 0, PIXMAN_a8r8g8b8 },
7526ca29ff0Smrg    { "in_reverse_8888_8888",  PIXMAN_a8r8g8b8,    0, PIXMAN_OP_IN_REVERSE, PIXMAN_null,  0, PIXMAN_a8r8g8b8 },
753f4f78bb6Smrg    { "pixbuf",                PIXMAN_x8b8g8r8,    0, PIXMAN_OP_SRC,     PIXMAN_a8b8g8r8, 0, PIXMAN_a8r8g8b8 },
754f4f78bb6Smrg    { "rpixbuf",               PIXMAN_x8b8g8r8,    0, PIXMAN_OP_SRC,     PIXMAN_a8b8g8r8, 0, PIXMAN_a8b8g8r8 },
7551b18d63aSmrg};
7561b18d63aSmrg
7576ca29ff0Smrgstatic const test_entry_t special_patterns[] =
7586ca29ff0Smrg{
7596ca29ff0Smrg    { "add_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
7606ca29ff0Smrg    { "add_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
7616ca29ff0Smrg    { "src_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
7626ca29ff0Smrg    { "src_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
7636ca29ff0Smrg    { "src_0888_8888_rev",     PIXMAN_b8g8r8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
7646ca29ff0Smrg    { "src_0888_0565_rev",     PIXMAN_b8g8r8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
7656ca29ff0Smrg    { "src_n_8",               PIXMAN_a8,          1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8 },
7666ca29ff0Smrg    { "pixbuf",                PIXMAN_x8b8g8r8,    0, PIXMAN_OP_SRC,     PIXMAN_a8b8g8r8, 0, PIXMAN_a8r8g8b8 },
7676ca29ff0Smrg    { "rpixbuf",               PIXMAN_x8b8g8r8,    0, PIXMAN_OP_SRC,     PIXMAN_a8b8g8r8, 0, PIXMAN_a8b8g8r8 },
7686ca29ff0Smrg};
7696ca29ff0Smrg
7706ca29ff0Smrg/* Returns the sub-string's end pointer in string. */
7716ca29ff0Smrgstatic const char *
7726ca29ff0Smrgcopy_sub_string (char       *buf,
7736ca29ff0Smrg                 const char *string,
7746ca29ff0Smrg                 const char *scan_from,
7756ca29ff0Smrg                 const char *end)
7761b18d63aSmrg{
7776ca29ff0Smrg    const char *delim;
7786ca29ff0Smrg    size_t n;
7796ca29ff0Smrg
7806ca29ff0Smrg    delim = strchr (scan_from, '_');
7816ca29ff0Smrg    if (!delim)
7826ca29ff0Smrg        delim = end;
7836ca29ff0Smrg
7846ca29ff0Smrg    n = delim - string;
7856ca29ff0Smrg    strncpy(buf, string, n);
7866ca29ff0Smrg    buf[n] = '\0';
7876ca29ff0Smrg
7886ca29ff0Smrg    return delim;
7896ca29ff0Smrg}
7906ca29ff0Smrg
7916ca29ff0Smrgstatic pixman_op_t
7926ca29ff0Smrgparse_longest_operator (char *buf, const char **strp, const char *end)
7936ca29ff0Smrg{
7946ca29ff0Smrg    const char *p = *strp;
7956ca29ff0Smrg    const char *sub_end;
7966ca29ff0Smrg    const char *best_end = p;
7976ca29ff0Smrg    pixman_op_t best_op = PIXMAN_OP_NONE;
7986ca29ff0Smrg    pixman_op_t op;
7996ca29ff0Smrg
8006ca29ff0Smrg    while (p < end)
8016ca29ff0Smrg    {
8026ca29ff0Smrg        sub_end = copy_sub_string (buf, *strp, p, end);
8036ca29ff0Smrg        op = operator_from_string (buf);
8046ca29ff0Smrg        p = sub_end + 1;
8056ca29ff0Smrg
8066ca29ff0Smrg        if (op != PIXMAN_OP_NONE)
8076ca29ff0Smrg        {
8086ca29ff0Smrg            best_end = p;
8096ca29ff0Smrg            best_op = op;
8106ca29ff0Smrg        }
8116ca29ff0Smrg    }
8126ca29ff0Smrg
8136ca29ff0Smrg    *strp = best_end;
8146ca29ff0Smrg    return best_op;
8156ca29ff0Smrg}
8166ca29ff0Smrg
8176ca29ff0Smrgstatic pixman_format_code_t
8186ca29ff0Smrgparse_format (char *buf, const char **p, const char *end)
8196ca29ff0Smrg{
8206ca29ff0Smrg    pixman_format_code_t format;
8216ca29ff0Smrg    const char *delim;
8226ca29ff0Smrg
8236ca29ff0Smrg    if (*p >= end)
8246ca29ff0Smrg        return PIXMAN_null;
8256ca29ff0Smrg
8266ca29ff0Smrg    delim = copy_sub_string (buf, *p, *p, end);
8276ca29ff0Smrg    format = format_from_string (buf);
8286ca29ff0Smrg
8296ca29ff0Smrg    if (format != PIXMAN_null)
8306ca29ff0Smrg        *p = delim + 1;
8316ca29ff0Smrg
8326ca29ff0Smrg    return format;
8336ca29ff0Smrg}
8346ca29ff0Smrg
8356ca29ff0Smrgstatic int
8366ca29ff0Smrgparse_test_pattern (test_entry_t *test, const char *pattern)
8376ca29ff0Smrg{
8386ca29ff0Smrg    const char *p = pattern;
8396ca29ff0Smrg    const char *end = pattern + strlen (pattern);
8406ca29ff0Smrg    char buf[1024];
8416ca29ff0Smrg    pixman_format_code_t format[3];
8421b18d63aSmrg    int i;
8436ca29ff0Smrg
8446ca29ff0Smrg    if (strlen (pattern) > sizeof (buf) - 1)
8456ca29ff0Smrg        return -1;
8466ca29ff0Smrg
8476ca29ff0Smrg    /* Special cases that the parser cannot produce. */
8486ca29ff0Smrg    for (i = 0; i < ARRAY_LENGTH (special_patterns); i++)
8499ad247e8Sjmcneill    {
8506ca29ff0Smrg        if (strcmp (pattern, special_patterns[i].testname) == 0)
8516ca29ff0Smrg        {
8526ca29ff0Smrg            *test = special_patterns[i];
8536ca29ff0Smrg            return 0;
8546ca29ff0Smrg        }
8559ad247e8Sjmcneill    }
8569ad247e8Sjmcneill
8576ca29ff0Smrg    test->testname = pattern;
8586ca29ff0Smrg
8596ca29ff0Smrg    /* Extract operator, may contain delimiters,
8606ca29ff0Smrg     * so take the longest string that matches.
8616ca29ff0Smrg     */
8626ca29ff0Smrg    test->op = parse_longest_operator (buf, &p, end);
8636ca29ff0Smrg    if (test->op == PIXMAN_OP_NONE)
8646ca29ff0Smrg        return -1;
8656ca29ff0Smrg
8666ca29ff0Smrg    /* extract up to three pixel formats */
8676ca29ff0Smrg    format[0] = parse_format (buf, &p, end);
8686ca29ff0Smrg    format[1] = parse_format (buf, &p, end);
8696ca29ff0Smrg    format[2] = parse_format (buf, &p, end);
8706ca29ff0Smrg
8716ca29ff0Smrg    if (format[0] == PIXMAN_null || format[1] == PIXMAN_null)
8726ca29ff0Smrg        return -1;
8736ca29ff0Smrg
8746ca29ff0Smrg    /* recognize CA flag */
8756ca29ff0Smrg    test->mask_flags = 0;
8766ca29ff0Smrg    if (p < end)
8779ad247e8Sjmcneill    {
8786ca29ff0Smrg        if (strcmp (p, "ca") == 0)
8796ca29ff0Smrg            test->mask_flags |= CA_FLAG;
8806ca29ff0Smrg        else
8816ca29ff0Smrg            return -1; /* trailing garbage */
8829ad247e8Sjmcneill    }
8831b18d63aSmrg
8846ca29ff0Smrg    test->src_fmt = format[0];
8856ca29ff0Smrg    if (format[2] == PIXMAN_null)
8866ca29ff0Smrg    {
8876ca29ff0Smrg        test->mask_fmt = PIXMAN_null;
8886ca29ff0Smrg        test->dst_fmt = format[1];
8896ca29ff0Smrg    }
8906ca29ff0Smrg    else
8916ca29ff0Smrg    {
8926ca29ff0Smrg        test->mask_fmt = format[1];
8936ca29ff0Smrg        test->dst_fmt = format[2];
8946ca29ff0Smrg    }
8956ca29ff0Smrg
8966ca29ff0Smrg    test->src_flags = 0;
8976ca29ff0Smrg    if (test->src_fmt == PIXMAN_solid)
8986ca29ff0Smrg    {
8996ca29ff0Smrg        test->src_fmt = PIXMAN_a8r8g8b8;
9006ca29ff0Smrg        test->src_flags |= SOLID_FLAG;
9016ca29ff0Smrg    }
9026ca29ff0Smrg
9036ca29ff0Smrg    if (test->mask_fmt == PIXMAN_solid)
9046ca29ff0Smrg    {
9056ca29ff0Smrg        if (test->mask_flags & CA_FLAG)
9066ca29ff0Smrg            test->mask_fmt = PIXMAN_a8r8g8b8;
9076ca29ff0Smrg        else
9086ca29ff0Smrg            test->mask_fmt = PIXMAN_a8;
9096ca29ff0Smrg
9106ca29ff0Smrg        test->mask_flags |= SOLID_FLAG;
9116ca29ff0Smrg    }
9126ca29ff0Smrg
9136ca29ff0Smrg    return 0;
9146ca29ff0Smrg}
9151b18d63aSmrg
9166ca29ff0Smrgstatic int
9176ca29ff0Smrgcheck_int (int got, int expected, const char *name, const char *field)
9186ca29ff0Smrg{
9196ca29ff0Smrg    if (got == expected)
9206ca29ff0Smrg        return 0;
9216ca29ff0Smrg
9226ca29ff0Smrg    printf ("%s: %s failure: expected %d, got %d.\n",
9236ca29ff0Smrg            name, field, expected, got);
9246ca29ff0Smrg
9256ca29ff0Smrg    return 1;
9266ca29ff0Smrg}
9276ca29ff0Smrg
9286ca29ff0Smrgstatic int
9296ca29ff0Smrgcheck_format (int got, int expected, const char *name, const char *field)
9306ca29ff0Smrg{
9316ca29ff0Smrg    if (got == expected)
9326ca29ff0Smrg        return 0;
9336ca29ff0Smrg
9346ca29ff0Smrg    printf ("%s: %s failure: expected %s (%#x), got %s (%#x).\n",
9356ca29ff0Smrg            name, field,
9366ca29ff0Smrg            format_name (expected), expected,
9376ca29ff0Smrg            format_name (got), got);
9386ca29ff0Smrg
9396ca29ff0Smrg    return 1;
9406ca29ff0Smrg}
9416ca29ff0Smrg
9426ca29ff0Smrgstatic void
9436ca29ff0Smrgparser_self_test (void)
9446ca29ff0Smrg{
9456ca29ff0Smrg    const test_entry_t *ent;
9466ca29ff0Smrg    test_entry_t test;
9476ca29ff0Smrg    int fails = 0;
9486ca29ff0Smrg    int i;
9496ca29ff0Smrg
9506ca29ff0Smrg    for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++)
9516ca29ff0Smrg    {
9526ca29ff0Smrg        ent = &tests_tbl[i];
9536ca29ff0Smrg
9546ca29ff0Smrg        if (parse_test_pattern (&test, ent->testname) < 0)
9556ca29ff0Smrg        {
9566ca29ff0Smrg            printf ("parsing failed for '%s'\n", ent->testname);
9576ca29ff0Smrg            fails++;
9586ca29ff0Smrg            continue;
9596ca29ff0Smrg        }
9606ca29ff0Smrg
9616ca29ff0Smrg        fails += check_format (test.src_fmt, ent->src_fmt,
9626ca29ff0Smrg                               ent->testname, "src_fmt");
9636ca29ff0Smrg        fails += check_format (test.mask_fmt, ent->mask_fmt,
9646ca29ff0Smrg                               ent->testname, "mask_fmt");
9656ca29ff0Smrg        fails += check_format (test.dst_fmt, ent->dst_fmt,
9666ca29ff0Smrg                               ent->testname, "dst_fmt");
9676ca29ff0Smrg        fails += check_int    (test.src_flags, ent->src_flags,
9686ca29ff0Smrg                               ent->testname, "src_flags");
9696ca29ff0Smrg        fails += check_int    (test.mask_flags, ent->mask_flags,
9706ca29ff0Smrg                               ent->testname, "mask_flags");
9716ca29ff0Smrg        fails += check_int    (test.op, ent->op, ent->testname, "op");
9726ca29ff0Smrg    }
9736ca29ff0Smrg
9746ca29ff0Smrg    if (fails)
9756ca29ff0Smrg    {
9766ca29ff0Smrg        printf ("Parser self-test failed.\n");
9776ca29ff0Smrg        exit (EXIT_FAILURE);
9786ca29ff0Smrg    }
9796ca29ff0Smrg
9806ca29ff0Smrg    if (!use_csv_output)
9816ca29ff0Smrg        printf ("Parser self-test complete.\n");
9826ca29ff0Smrg}
9836ca29ff0Smrg
9846ca29ff0Smrgstatic void
9856ca29ff0Smrgprint_test_details (const test_entry_t *test)
9866ca29ff0Smrg{
9876ca29ff0Smrg    printf ("%s: %s, src %s%s, mask %s%s%s, dst %s\n",
9886ca29ff0Smrg            test->testname,
9896ca29ff0Smrg            operator_name (test->op),
9906ca29ff0Smrg            format_name (test->src_fmt),
9916ca29ff0Smrg            test->src_flags & SOLID_FLAG ? " solid" : "",
9926ca29ff0Smrg            format_name (test->mask_fmt),
9936ca29ff0Smrg            test->mask_flags & SOLID_FLAG ? " solid" : "",
9946ca29ff0Smrg            test->mask_flags & CA_FLAG ? " CA" : "",
9956ca29ff0Smrg            format_name (test->dst_fmt));
9966ca29ff0Smrg}
9976ca29ff0Smrg
9986ca29ff0Smrgstatic void
9996ca29ff0Smrgrun_one_test (const char *pattern, double bandwidth_, pixman_bool_t prdetails)
10006ca29ff0Smrg{
10016ca29ff0Smrg    test_entry_t test;
10026ca29ff0Smrg
10036ca29ff0Smrg    if (parse_test_pattern (&test, pattern) < 0)
10046ca29ff0Smrg    {
10056ca29ff0Smrg        printf ("Error: Could not parse the test pattern '%s'.\n", pattern);
10066ca29ff0Smrg        return;
10076ca29ff0Smrg    }
10086ca29ff0Smrg
10096ca29ff0Smrg    if (prdetails)
10106ca29ff0Smrg    {
10116ca29ff0Smrg        print_test_details (&test);
10126ca29ff0Smrg        printf ("---\n");
10136ca29ff0Smrg    }
10146ca29ff0Smrg
10156ca29ff0Smrg    bench_composite (pattern,
10166ca29ff0Smrg                     test.src_fmt,
10176ca29ff0Smrg                     test.src_flags,
10186ca29ff0Smrg                     test.op,
10196ca29ff0Smrg                     test.mask_fmt,
10206ca29ff0Smrg                     test.mask_flags,
10216ca29ff0Smrg                     test.dst_fmt,
10226ca29ff0Smrg                     bandwidth_ / 8);
10236ca29ff0Smrg}
10246ca29ff0Smrg
10256ca29ff0Smrgstatic void
10266ca29ff0Smrgrun_default_tests (double bandwidth_)
10276ca29ff0Smrg{
10286ca29ff0Smrg    int i;
10296ca29ff0Smrg
10306ca29ff0Smrg    for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++)
10316ca29ff0Smrg        run_one_test (tests_tbl[i].testname, bandwidth_, FALSE);
10326ca29ff0Smrg}
10336ca29ff0Smrg
10346ca29ff0Smrgstatic void
10356ca29ff0Smrgprint_explanation (void)
10366ca29ff0Smrg{
10371b18d63aSmrg    printf ("Benchmark for a set of most commonly used functions\n");
10381b18d63aSmrg    printf ("---\n");
10391b18d63aSmrg    printf ("All results are presented in millions of pixels per second\n");
10401b18d63aSmrg    printf ("L1  - small Xx1 rectangle (fitting L1 cache), always blitted at the same\n");
10411b18d63aSmrg    printf ("      memory location with small drift in horizontal direction\n");
10421b18d63aSmrg    printf ("L2  - small XxY rectangle (fitting L2 cache), always blitted at the same\n");
10431b18d63aSmrg    printf ("      memory location with small drift in horizontal direction\n");
10441b18d63aSmrg    printf ("M   - large %dx%d rectangle, always blitted at the same\n",
10451b18d63aSmrg            WIDTH - 64, HEIGHT);
10461b18d63aSmrg    printf ("      memory location with small drift in horizontal direction\n");
10471b18d63aSmrg    printf ("HT  - random rectangles with %dx%d average size are copied from\n",
10481b18d63aSmrg            TILEWIDTH, TILEWIDTH);
10491b18d63aSmrg    printf ("      one %dx%d buffer to another, traversing from left to right\n",
10501b18d63aSmrg            WIDTH, HEIGHT);
10511b18d63aSmrg    printf ("      and from top to bottom\n");
10521b18d63aSmrg    printf ("VT  - random rectangles with %dx%d average size are copied from\n",
10531b18d63aSmrg            TILEWIDTH, TILEWIDTH);
10541b18d63aSmrg    printf ("      one %dx%d buffer to another, traversing from top to bottom\n",
10551b18d63aSmrg            WIDTH, HEIGHT);
10561b18d63aSmrg    printf ("      and from left to right\n");
10571b18d63aSmrg    printf ("R   - random rectangles with %dx%d average size are copied from\n",
10581b18d63aSmrg            TILEWIDTH, TILEWIDTH);
10591b18d63aSmrg    printf ("      random locations of one %dx%d buffer to another\n",
10601b18d63aSmrg            WIDTH, HEIGHT);
10611b18d63aSmrg    printf ("RT  - as R, but %dx%d average sized rectangles are copied\n",
10621b18d63aSmrg            TINYWIDTH, TINYWIDTH);
10631b18d63aSmrg    printf ("---\n");
10646ca29ff0Smrg}
10656ca29ff0Smrg
10666ca29ff0Smrgstatic void
10676ca29ff0Smrgprint_speed_scaling (double bw)
10686ca29ff0Smrg{
10691b18d63aSmrg    printf ("reference memcpy speed = %.1fMB/s (%.1fMP/s for 32bpp fills)\n",
10706ca29ff0Smrg            bw / 1000000., bw / 4000000);
10716ca29ff0Smrg
10729ad247e8Sjmcneill    if (use_scaling)
10739ad247e8Sjmcneill    {
10749ad247e8Sjmcneill	printf ("---\n");
10759ad247e8Sjmcneill	if (filter == PIXMAN_FILTER_BILINEAR)
10769ad247e8Sjmcneill	    printf ("BILINEAR scaling\n");
10779ad247e8Sjmcneill	else if (filter == PIXMAN_FILTER_NEAREST)
10789ad247e8Sjmcneill	    printf ("NEAREST scaling\n");
10799ad247e8Sjmcneill	else
10809ad247e8Sjmcneill	    printf ("UNKNOWN scaling\n");
10819ad247e8Sjmcneill    }
10826ca29ff0Smrg
10831b18d63aSmrg    printf ("---\n");
10846ca29ff0Smrg}
10851b18d63aSmrg
10866ca29ff0Smrgstatic void
10876ca29ff0Smrgusage (const char *progname)
10886ca29ff0Smrg{
10896ca29ff0Smrg    printf ("Usage: %s [-b] [-n] [-c] [-m M] pattern\n", progname);
10906ca29ff0Smrg    printf ("  -n : benchmark nearest scaling\n");
10916ca29ff0Smrg    printf ("  -b : benchmark bilinear scaling\n");
10926ca29ff0Smrg    printf ("  -c : print output as CSV data\n");
10936ca29ff0Smrg    printf ("  -m M : set reference memcpy speed to M MB/s instead of measuring it\n");
10946ca29ff0Smrg}
10956ca29ff0Smrg
10966ca29ff0Smrgint
10976ca29ff0Smrgmain (int argc, char *argv[])
10986ca29ff0Smrg{
10996ca29ff0Smrg    int i;
11006ca29ff0Smrg    const char *pattern = NULL;
11016ca29ff0Smrg
11026ca29ff0Smrg    for (i = 1; i < argc; i++)
11031b18d63aSmrg    {
11046ca29ff0Smrg	if (argv[i][0] == '-')
11051b18d63aSmrg	{
11066ca29ff0Smrg	    if (strchr (argv[i] + 1, 'b'))
11076ca29ff0Smrg	    {
11086ca29ff0Smrg		use_scaling = TRUE;
11096ca29ff0Smrg		filter = PIXMAN_FILTER_BILINEAR;
11106ca29ff0Smrg	    }
11116ca29ff0Smrg	    else if (strchr (argv[i] + 1, 'n'))
11126ca29ff0Smrg	    {
11136ca29ff0Smrg		use_scaling = TRUE;
11146ca29ff0Smrg		filter = PIXMAN_FILTER_NEAREST;
11156ca29ff0Smrg	    }
11166ca29ff0Smrg
11176ca29ff0Smrg	    if (strchr (argv[i] + 1, 'c'))
11186ca29ff0Smrg		use_csv_output = TRUE;
11196ca29ff0Smrg
11206ca29ff0Smrg	    if (strcmp (argv[i], "-m") == 0 && i + 1 < argc)
11216ca29ff0Smrg		bandwidth = atof (argv[++i]) * 1e6;
11221b18d63aSmrg	}
11236ca29ff0Smrg	else
11246ca29ff0Smrg	{
11256ca29ff0Smrg	    if (pattern)
11266ca29ff0Smrg	    {
11276ca29ff0Smrg		pattern = NULL;
11286ca29ff0Smrg		printf ("Error: extra arguments given.\n");
11296ca29ff0Smrg		break;
11306ca29ff0Smrg	    }
11316ca29ff0Smrg	    pattern = argv[i];
11326ca29ff0Smrg	}
11336ca29ff0Smrg    }
11346ca29ff0Smrg
11356ca29ff0Smrg    if (!pattern)
11366ca29ff0Smrg    {
11376ca29ff0Smrg	usage (argv[0]);
11386ca29ff0Smrg	return 1;
11391b18d63aSmrg    }
11401b18d63aSmrg
11416ca29ff0Smrg    parser_self_test ();
11426ca29ff0Smrg
11436ca29ff0Smrg    src = aligned_malloc (4096, BUFSIZE * 3);
11446ca29ff0Smrg    memset (src, 0xCC, BUFSIZE * 3);
11456ca29ff0Smrg    dst = src + (BUFSIZE / 4);
11466ca29ff0Smrg    mask = dst + (BUFSIZE / 4);
11476ca29ff0Smrg
11486ca29ff0Smrg    if (!use_csv_output)
11496ca29ff0Smrg        print_explanation ();
11506ca29ff0Smrg
11516ca29ff0Smrg    if (bandwidth < 1.0)
11526ca29ff0Smrg        bandwidth = bench_memcpy ();
11536ca29ff0Smrg    if (!use_csv_output)
11546ca29ff0Smrg        print_speed_scaling (bandwidth);
11556ca29ff0Smrg
11566ca29ff0Smrg    if (strcmp (pattern, "all") == 0)
11576ca29ff0Smrg        run_default_tests (bandwidth);
11586ca29ff0Smrg    else
11596ca29ff0Smrg        run_one_test (pattern, bandwidth, !use_csv_output);
11606ca29ff0Smrg
11611b18d63aSmrg    free (src);
11621b18d63aSmrg    return 0;
11631b18d63aSmrg}
1164