16ca29ff0Smrg/*
26ca29ff0Smrg * Copyright © 2014 RISC OS Open Ltd
36ca29ff0Smrg *
46ca29ff0Smrg * Permission to use, copy, modify, distribute, and sell this software and its
56ca29ff0Smrg * documentation for any purpose is hereby granted without fee, provided that
66ca29ff0Smrg * the above copyright notice appear in all copies and that both that
76ca29ff0Smrg * copyright notice and this permission notice appear in supporting
86ca29ff0Smrg * documentation, and that the name of the copyright holders not be used in
96ca29ff0Smrg * advertising or publicity pertaining to distribution of the software without
106ca29ff0Smrg * specific, written prior permission.  The copyright holders make no
116ca29ff0Smrg * representations about the suitability of this software for any purpose.  It
126ca29ff0Smrg * is provided "as is" without express or implied warranty.
136ca29ff0Smrg *
146ca29ff0Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
156ca29ff0Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
166ca29ff0Smrg * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
176ca29ff0Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
186ca29ff0Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
196ca29ff0Smrg * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
206ca29ff0Smrg * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
216ca29ff0Smrg * SOFTWARE.
226ca29ff0Smrg *
236ca29ff0Smrg * Author:  Ben Avison (bavison@riscosopen.org)
246ca29ff0Smrg */
256ca29ff0Smrg
266ca29ff0Smrg#include <stdio.h>
276ca29ff0Smrg#include <stdlib.h>
286ca29ff0Smrg#include <string.h>
296ca29ff0Smrg#include <ctype.h>
306ca29ff0Smrg#include <stdint.h>
316ca29ff0Smrg#include "utils.h"
326ca29ff0Smrg
336ca29ff0Smrg#ifdef HAVE_GETTIMEOFDAY
346ca29ff0Smrg#include <sys/time.h>
356ca29ff0Smrg#else
366ca29ff0Smrg#include <time.h>
376ca29ff0Smrg#endif
386ca29ff0Smrg
396ca29ff0Smrg#define WIDTH  1920
406ca29ff0Smrg#define HEIGHT 1080
416ca29ff0Smrg
426ca29ff0Smrg/* How much data to read to flush all cached data to RAM */
436ca29ff0Smrg#define MAX_L2CACHE_SIZE (8 * 1024 * 1024)
446ca29ff0Smrg
456ca29ff0Smrg#define PAGE_SIZE (4 * 1024)
466ca29ff0Smrg
476ca29ff0Smrgstruct bench_info
486ca29ff0Smrg{
496ca29ff0Smrg    pixman_op_t           op;
506ca29ff0Smrg    pixman_transform_t    transform;
516ca29ff0Smrg    pixman_image_t       *src_image;
526ca29ff0Smrg    pixman_image_t       *mask_image;
536ca29ff0Smrg    pixman_image_t       *dest_image;
546ca29ff0Smrg    int32_t               src_x;
556ca29ff0Smrg    int32_t               src_y;
566ca29ff0Smrg};
576ca29ff0Smrg
586ca29ff0Smrgtypedef struct bench_info bench_info_t;
596ca29ff0Smrg
606ca29ff0Smrgstruct box_48_16
616ca29ff0Smrg{
626ca29ff0Smrg    pixman_fixed_48_16_t        x1;
636ca29ff0Smrg    pixman_fixed_48_16_t        y1;
646ca29ff0Smrg    pixman_fixed_48_16_t        x2;
656ca29ff0Smrg    pixman_fixed_48_16_t        y2;
666ca29ff0Smrg};
676ca29ff0Smrg
686ca29ff0Smrgtypedef struct box_48_16 box_48_16_t;
696ca29ff0Smrg
706ca29ff0Smrg/* This function is copied verbatim from pixman.c. */
716ca29ff0Smrgstatic pixman_bool_t
726ca29ff0Smrgcompute_transformed_extents (pixman_transform_t   *transform,
736ca29ff0Smrg			     const pixman_box32_t *extents,
746ca29ff0Smrg			     box_48_16_t          *transformed)
756ca29ff0Smrg{
766ca29ff0Smrg    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
776ca29ff0Smrg    pixman_fixed_t x1, y1, x2, y2;
786ca29ff0Smrg    int i;
796ca29ff0Smrg
806ca29ff0Smrg    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
816ca29ff0Smrg    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
826ca29ff0Smrg    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
836ca29ff0Smrg    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
846ca29ff0Smrg
856ca29ff0Smrg    if (!transform)
866ca29ff0Smrg    {
876ca29ff0Smrg	transformed->x1 = x1;
886ca29ff0Smrg	transformed->y1 = y1;
896ca29ff0Smrg	transformed->x2 = x2;
906ca29ff0Smrg	transformed->y2 = y2;
916ca29ff0Smrg
926ca29ff0Smrg	return TRUE;
936ca29ff0Smrg    }
946ca29ff0Smrg
956ca29ff0Smrg    tx1 = ty1 = INT64_MAX;
966ca29ff0Smrg    tx2 = ty2 = INT64_MIN;
976ca29ff0Smrg
986ca29ff0Smrg    for (i = 0; i < 4; ++i)
996ca29ff0Smrg    {
1006ca29ff0Smrg	pixman_fixed_48_16_t tx, ty;
1016ca29ff0Smrg	pixman_vector_t v;
1026ca29ff0Smrg
1036ca29ff0Smrg	v.vector[0] = (i & 0x01)? x1 : x2;
1046ca29ff0Smrg	v.vector[1] = (i & 0x02)? y1 : y2;
1056ca29ff0Smrg	v.vector[2] = pixman_fixed_1;
1066ca29ff0Smrg
1076ca29ff0Smrg	if (!pixman_transform_point (transform, &v))
1086ca29ff0Smrg	    return FALSE;
1096ca29ff0Smrg
1106ca29ff0Smrg	tx = (pixman_fixed_48_16_t)v.vector[0];
1116ca29ff0Smrg	ty = (pixman_fixed_48_16_t)v.vector[1];
1126ca29ff0Smrg
1136ca29ff0Smrg	if (tx < tx1)
1146ca29ff0Smrg	    tx1 = tx;
1156ca29ff0Smrg	if (ty < ty1)
1166ca29ff0Smrg	    ty1 = ty;
1176ca29ff0Smrg	if (tx > tx2)
1186ca29ff0Smrg	    tx2 = tx;
1196ca29ff0Smrg	if (ty > ty2)
1206ca29ff0Smrg	    ty2 = ty;
1216ca29ff0Smrg    }
1226ca29ff0Smrg
1236ca29ff0Smrg    transformed->x1 = tx1;
1246ca29ff0Smrg    transformed->y1 = ty1;
1256ca29ff0Smrg    transformed->x2 = tx2;
1266ca29ff0Smrg    transformed->y2 = ty2;
1276ca29ff0Smrg
1286ca29ff0Smrg    return TRUE;
1296ca29ff0Smrg}
1306ca29ff0Smrg
1316ca29ff0Smrgstatic void
1326ca29ff0Smrgcreate_image (uint32_t                   width,
1336ca29ff0Smrg              uint32_t                   height,
1346ca29ff0Smrg              pixman_format_code_t       format,
1356ca29ff0Smrg              pixman_filter_t            filter,
1366ca29ff0Smrg              uint32_t                 **bits,
1376ca29ff0Smrg              pixman_image_t           **image)
1386ca29ff0Smrg{
1396ca29ff0Smrg    uint32_t stride = (width * PIXMAN_FORMAT_BPP (format) + 31) / 32 * 4;
1406ca29ff0Smrg
1416ca29ff0Smrg    *bits = aligned_malloc (PAGE_SIZE, stride * height);
1426ca29ff0Smrg    memset (*bits, 0xCC, stride * height);
1436ca29ff0Smrg    *image = pixman_image_create_bits (format, width, height, *bits, stride);
1446ca29ff0Smrg    pixman_image_set_repeat (*image, PIXMAN_REPEAT_NORMAL);
1456ca29ff0Smrg    pixman_image_set_filter (*image, filter, NULL, 0);
1466ca29ff0Smrg}
1476ca29ff0Smrg
1486ca29ff0Smrg/* This needs to match the shortest cacheline length we expect to encounter */
1496ca29ff0Smrg#define CACHE_CLEAN_INCREMENT 32
1506ca29ff0Smrg
1516ca29ff0Smrgstatic void
1526ca29ff0Smrgflush_cache (void)
1536ca29ff0Smrg{
1546ca29ff0Smrg    static const char clean_space[MAX_L2CACHE_SIZE];
1556ca29ff0Smrg    volatile const char *x = clean_space;
1566ca29ff0Smrg    const char *clean_end = clean_space + sizeof clean_space;
1576ca29ff0Smrg
1586ca29ff0Smrg    while (x < clean_end)
1596ca29ff0Smrg    {
1606ca29ff0Smrg        (void) *x;
1616ca29ff0Smrg        x += CACHE_CLEAN_INCREMENT;
1626ca29ff0Smrg    }
1636ca29ff0Smrg}
1646ca29ff0Smrg
1656ca29ff0Smrg/* Obtain current time in microseconds modulo 2^32 */
1666ca29ff0Smrguint32_t
1676ca29ff0Smrggettimei (void)
1686ca29ff0Smrg{
1696ca29ff0Smrg#ifdef HAVE_GETTIMEOFDAY
1706ca29ff0Smrg    struct timeval tv;
1716ca29ff0Smrg
1726ca29ff0Smrg    gettimeofday (&tv, NULL);
1736ca29ff0Smrg    return tv.tv_sec * 1000000 + tv.tv_usec;
1746ca29ff0Smrg#else
1756ca29ff0Smrg    return (uint64_t) clock () * 1000000 / CLOCKS_PER_SEC;
1766ca29ff0Smrg#endif
1776ca29ff0Smrg}
1786ca29ff0Smrg
1796ca29ff0Smrgstatic void
1806ca29ff0Smrgpixman_image_composite_wrapper (const pixman_composite_info_t *info)
1816ca29ff0Smrg{
1826ca29ff0Smrg    pixman_image_composite (info->op,
1836ca29ff0Smrg                            info->src_image, info->mask_image, info->dest_image,
1846ca29ff0Smrg                            info->src_x, info->src_y,
1856ca29ff0Smrg                            info->mask_x, info->mask_y,
1866ca29ff0Smrg                            info->dest_x, info->dest_y,
1876ca29ff0Smrg                            info->width, info->height);
1886ca29ff0Smrg}
1896ca29ff0Smrg
1906ca29ff0Smrgstatic void
1916ca29ff0Smrgpixman_image_composite_empty (const pixman_composite_info_t *info)
1926ca29ff0Smrg{
1936ca29ff0Smrg    pixman_image_composite (info->op,
1946ca29ff0Smrg                            info->src_image, info->mask_image, info->dest_image,
1956ca29ff0Smrg                            info->src_x, info->src_y,
1966ca29ff0Smrg                            info->mask_x, info->mask_y,
1976ca29ff0Smrg                            info->dest_x, info->dest_y,
1986ca29ff0Smrg                            1, 1);
1996ca29ff0Smrg}
2006ca29ff0Smrg
2016ca29ff0Smrgstatic void
2026ca29ff0Smrgbench (const bench_info_t *bi,
2036ca29ff0Smrg       uint32_t            max_n,
2046ca29ff0Smrg       uint32_t            max_time,
2056ca29ff0Smrg       uint32_t           *ret_n,
2066ca29ff0Smrg       uint32_t           *ret_time,
2076ca29ff0Smrg       void              (*func) (const pixman_composite_info_t *info))
2086ca29ff0Smrg{
2096ca29ff0Smrg    uint32_t n = 0;
2106ca29ff0Smrg    uint32_t t0;
2116ca29ff0Smrg    uint32_t t1;
2126ca29ff0Smrg    uint32_t x = 0;
2136ca29ff0Smrg    pixman_transform_t t;
2146ca29ff0Smrg    pixman_composite_info_t info;
2156ca29ff0Smrg
2166ca29ff0Smrg    t = bi->transform;
2176ca29ff0Smrg    info.op = bi->op;
2186ca29ff0Smrg    info.src_image = bi->src_image;
2196ca29ff0Smrg    info.mask_image = bi->mask_image;
2206ca29ff0Smrg    info.dest_image = bi->dest_image;
2216ca29ff0Smrg    info.src_x = 0;
2226ca29ff0Smrg    info.src_y = 0;
2236ca29ff0Smrg    info.mask_x = 0;
2246ca29ff0Smrg    info.mask_y = 0;
2256ca29ff0Smrg    /* info.dest_x set below */
2266ca29ff0Smrg    info.dest_y = 0;
2276ca29ff0Smrg    info.width = WIDTH;
2286ca29ff0Smrg    info.height = HEIGHT;
2296ca29ff0Smrg
2306ca29ff0Smrg    t0 = gettimei ();
2316ca29ff0Smrg
2326ca29ff0Smrg    do
2336ca29ff0Smrg    {
2346ca29ff0Smrg
2356ca29ff0Smrg        if (++x >= 64)
2366ca29ff0Smrg            x = 0;
2376ca29ff0Smrg
2386ca29ff0Smrg        info.dest_x = 63 - x;
2396ca29ff0Smrg
2406ca29ff0Smrg        t.matrix[0][2] = pixman_int_to_fixed (bi->src_x + x);
2416ca29ff0Smrg        t.matrix[1][2] = pixman_int_to_fixed (bi->src_y);
2426ca29ff0Smrg        pixman_image_set_transform (bi->src_image, &t);
2436ca29ff0Smrg
2446ca29ff0Smrg        if (bi->mask_image)
2456ca29ff0Smrg            pixman_image_set_transform (bi->mask_image, &t);
2466ca29ff0Smrg
2476ca29ff0Smrg        func (&info);
2486ca29ff0Smrg        t1 = gettimei ();
2496ca29ff0Smrg    }
2506ca29ff0Smrg    while (++n < max_n && (t1 - t0) < max_time);
2516ca29ff0Smrg
2526ca29ff0Smrg    if (ret_n)
2536ca29ff0Smrg        *ret_n = n;
2546ca29ff0Smrg
2556ca29ff0Smrg    *ret_time = t1 - t0;
2566ca29ff0Smrg}
2576ca29ff0Smrg
2586ca29ff0Smrgint
2596ca29ff0Smrgparse_fixed_argument (char *arg, pixman_fixed_t *value)
2606ca29ff0Smrg{
2616ca29ff0Smrg    char *tailptr;
2626ca29ff0Smrg
2636ca29ff0Smrg    *value = pixman_double_to_fixed (strtod (arg, &tailptr));
2646ca29ff0Smrg
2656ca29ff0Smrg    return *tailptr == '\0';
2666ca29ff0Smrg}
2676ca29ff0Smrg
2686ca29ff0Smrgint
2696ca29ff0Smrgparse_arguments (int                   argc,
2706ca29ff0Smrg                 char                 *argv[],
2716ca29ff0Smrg                 pixman_transform_t   *t,
2726ca29ff0Smrg                 pixman_op_t          *op,
2736ca29ff0Smrg                 pixman_format_code_t *src_format,
2746ca29ff0Smrg                 pixman_format_code_t *mask_format,
2756ca29ff0Smrg                 pixman_format_code_t *dest_format)
2766ca29ff0Smrg{
2776ca29ff0Smrg    if (!parse_fixed_argument (*argv, &t->matrix[0][0]))
2786ca29ff0Smrg        return 0;
2796ca29ff0Smrg
2806ca29ff0Smrg    if (*++argv == NULL)
2816ca29ff0Smrg        return 1;
2826ca29ff0Smrg
2836ca29ff0Smrg    if (!parse_fixed_argument (*argv, &t->matrix[0][1]))
2846ca29ff0Smrg        return 0;
2856ca29ff0Smrg
2866ca29ff0Smrg    if (*++argv == NULL)
2876ca29ff0Smrg        return 1;
2886ca29ff0Smrg
2896ca29ff0Smrg    if (!parse_fixed_argument (*argv, &t->matrix[1][0]))
2906ca29ff0Smrg        return 0;
2916ca29ff0Smrg
2926ca29ff0Smrg    if (*++argv == NULL)
2936ca29ff0Smrg        return 1;
2946ca29ff0Smrg
2956ca29ff0Smrg    if (!parse_fixed_argument (*argv, &t->matrix[1][1]))
2966ca29ff0Smrg        return 0;
2976ca29ff0Smrg
2986ca29ff0Smrg    if (*++argv == NULL)
2996ca29ff0Smrg        return 1;
3006ca29ff0Smrg
3016ca29ff0Smrg    *op = operator_from_string (*argv);
3026ca29ff0Smrg    if (*op == PIXMAN_OP_NONE)
3036ca29ff0Smrg        return 0;
3046ca29ff0Smrg
3056ca29ff0Smrg    if (*++argv == NULL)
3066ca29ff0Smrg        return 1;
3076ca29ff0Smrg
3086ca29ff0Smrg    *src_format = format_from_string (*argv);
3096ca29ff0Smrg    if (*src_format == PIXMAN_null)
3106ca29ff0Smrg        return 0;
3116ca29ff0Smrg
3126ca29ff0Smrg    ++argv;
3136ca29ff0Smrg    if (argv[0] && argv[1])
3146ca29ff0Smrg    {
3156ca29ff0Smrg        *mask_format = format_from_string (*argv);
3166ca29ff0Smrg        if (*mask_format == PIXMAN_null)
3176ca29ff0Smrg            return 0;
3186ca29ff0Smrg        ++argv;
3196ca29ff0Smrg    }
3206ca29ff0Smrg    if (*argv)
3216ca29ff0Smrg    {
3226ca29ff0Smrg        *dest_format = format_from_string (*argv);
3236ca29ff0Smrg        if (*dest_format == PIXMAN_null)
3246ca29ff0Smrg            return 0;
3256ca29ff0Smrg    }
3266ca29ff0Smrg    return 1;
3276ca29ff0Smrg}
3286ca29ff0Smrg
3296ca29ff0Smrgstatic void
3306ca29ff0Smrgrun_benchmark (const bench_info_t *bi)
3316ca29ff0Smrg{
3326ca29ff0Smrg    uint32_t n;  /* number of iterations in at least 5 seconds */
3336ca29ff0Smrg    uint32_t t1; /* time taken to do n iterations, microseconds */
3346ca29ff0Smrg    uint32_t t2; /* calling overhead for n iterations, microseconds */
3356ca29ff0Smrg
3366ca29ff0Smrg    flush_cache ();
3376ca29ff0Smrg    bench (bi, UINT32_MAX, 5000000, &n, &t1, pixman_image_composite_wrapper);
3386ca29ff0Smrg    bench (bi, n, UINT32_MAX, NULL, &t2, pixman_image_composite_empty);
3396ca29ff0Smrg
3406ca29ff0Smrg    /* The result indicates the output rate in megapixels/second */
3416ca29ff0Smrg    printf ("%6.2f\n", (double) n * WIDTH * HEIGHT / (t1 - t2));
3426ca29ff0Smrg}
3436ca29ff0Smrg
3446ca29ff0Smrg
3456ca29ff0Smrgint
3466ca29ff0Smrgmain (int argc, char *argv[])
3476ca29ff0Smrg{
3486ca29ff0Smrg    bench_info_t         binfo;
3496ca29ff0Smrg    pixman_filter_t      filter      = PIXMAN_FILTER_NEAREST;
3506ca29ff0Smrg    pixman_format_code_t src_format  = PIXMAN_a8r8g8b8;
3516ca29ff0Smrg    pixman_format_code_t mask_format = 0;
3526ca29ff0Smrg    pixman_format_code_t dest_format = PIXMAN_a8r8g8b8;
3536ca29ff0Smrg    pixman_box32_t       dest_box    = { 0, 0, WIDTH, HEIGHT };
3546ca29ff0Smrg    box_48_16_t          transformed = { 0 };
3556ca29ff0Smrg    int32_t xmin, ymin, xmax, ymax;
3566ca29ff0Smrg    uint32_t *src, *mask, *dest;
3576ca29ff0Smrg
3586ca29ff0Smrg    binfo.op         = PIXMAN_OP_SRC;
3596ca29ff0Smrg    binfo.mask_image = NULL;
3606ca29ff0Smrg    pixman_transform_init_identity (&binfo.transform);
3616ca29ff0Smrg
3626ca29ff0Smrg    ++argv;
3636ca29ff0Smrg    if (*argv && (*argv)[0] == '-' && (*argv)[1] == 'n')
3646ca29ff0Smrg    {
3656ca29ff0Smrg        filter = PIXMAN_FILTER_NEAREST;
3666ca29ff0Smrg        ++argv;
3676ca29ff0Smrg        --argc;
3686ca29ff0Smrg    }
3696ca29ff0Smrg
3706ca29ff0Smrg    if (*argv && (*argv)[0] == '-' && (*argv)[1] == 'b')
3716ca29ff0Smrg    {
3726ca29ff0Smrg        filter = PIXMAN_FILTER_BILINEAR;
3736ca29ff0Smrg        ++argv;
3746ca29ff0Smrg        --argc;
3756ca29ff0Smrg    }
3766ca29ff0Smrg
3776ca29ff0Smrg    if (argc == 1 ||
3786ca29ff0Smrg        !parse_arguments (argc, argv, &binfo.transform, &binfo.op,
3796ca29ff0Smrg                          &src_format, &mask_format, &dest_format))
3806ca29ff0Smrg    {
3816ca29ff0Smrg        printf ("Usage: affine-bench [-n] [-b] axx [axy] [ayx] [ayy] [combine type]\n");
3826ca29ff0Smrg        printf ("                    [src format] [mask format] [dest format]\n");
3836ca29ff0Smrg        printf ("  -n : nearest scaling (default)\n");
3846ca29ff0Smrg        printf ("  -b : bilinear scaling\n");
3856ca29ff0Smrg        printf ("  axx : x_out:x_in factor\n");
3866ca29ff0Smrg        printf ("  axy : x_out:y_in factor (default 0)\n");
3876ca29ff0Smrg        printf ("  ayx : y_out:x_in factor (default 0)\n");
3886ca29ff0Smrg        printf ("  ayy : y_out:y_in factor (default 1)\n");
3896ca29ff0Smrg        printf ("  combine type : src, over, in etc (default src)\n");
3906ca29ff0Smrg        printf ("  src format : a8r8g8b8, r5g6b5 etc (default a8r8g8b8)\n");
3916ca29ff0Smrg        printf ("  mask format : as for src format, but no mask used if omitted\n");
3926ca29ff0Smrg        printf ("  dest format : as for src format (default a8r8g8b8)\n");
3936ca29ff0Smrg        printf ("The output is a single number in megapixels/second.\n");
3946ca29ff0Smrg
3956ca29ff0Smrg        return EXIT_FAILURE;
3966ca29ff0Smrg    }
3976ca29ff0Smrg
3986ca29ff0Smrg    /* Compute required extents for source and mask image so they qualify
3996ca29ff0Smrg     * for COVER fast paths and get the flags in pixman.c:analyze_extent().
4006ca29ff0Smrg     * These computations are for FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR,
4016ca29ff0Smrg     * but at the same time they also allow COVER_CLIP_NEAREST.
4026ca29ff0Smrg     */
4036ca29ff0Smrg    compute_transformed_extents (&binfo.transform, &dest_box, &transformed);
4046ca29ff0Smrg    xmin = pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2);
4056ca29ff0Smrg    ymin = pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2);
4066ca29ff0Smrg    xmax = pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2);
4076ca29ff0Smrg    ymax = pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2);
4086ca29ff0Smrg    /* Note:
4096ca29ff0Smrg     * The upper limits can be reduced to the following when fetchers
4106ca29ff0Smrg     * are guaranteed to not access pixels with zero weight. This concerns
4116ca29ff0Smrg     * particularly all bilinear samplers.
4126ca29ff0Smrg     *
4136ca29ff0Smrg     * xmax = pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2 - pixman_fixed_e);
4146ca29ff0Smrg     * ymax = pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2 - pixman_fixed_e);
4156ca29ff0Smrg     * This is equivalent to subtracting 0.5 and rounding up, rather than
4166ca29ff0Smrg     * subtracting 0.5, rounding down and adding 1.
4176ca29ff0Smrg     */
4186ca29ff0Smrg    binfo.src_x = -xmin;
4196ca29ff0Smrg    binfo.src_y = -ymin;
4206ca29ff0Smrg
4216ca29ff0Smrg    /* Always over-allocate width by 64 pixels for all src, mask and dst,
4226ca29ff0Smrg     * so that we can iterate over an x-offset 0..63 in bench ().
4236ca29ff0Smrg     * This is similar to lowlevel-blt-bench, which uses the same method
4246ca29ff0Smrg     * to hit different cacheline misalignments.
4256ca29ff0Smrg     */
4266ca29ff0Smrg    create_image (xmax - xmin + 64, ymax - ymin + 1, src_format, filter,
4276ca29ff0Smrg                  &src, &binfo.src_image);
4286ca29ff0Smrg
4296ca29ff0Smrg    if (mask_format)
4306ca29ff0Smrg    {
4316ca29ff0Smrg        create_image (xmax - xmin + 64, ymax - ymin + 1, mask_format, filter,
4326ca29ff0Smrg                      &mask, &binfo.mask_image);
4336ca29ff0Smrg
4346ca29ff0Smrg        if ((PIXMAN_FORMAT_R(mask_format) ||
4356ca29ff0Smrg             PIXMAN_FORMAT_G(mask_format) ||
4366ca29ff0Smrg             PIXMAN_FORMAT_B(mask_format)))
4376ca29ff0Smrg        {
4386ca29ff0Smrg            pixman_image_set_component_alpha (binfo.mask_image, 1);
4396ca29ff0Smrg        }
4406ca29ff0Smrg    }
4416ca29ff0Smrg
4426ca29ff0Smrg    create_image (WIDTH + 64, HEIGHT, dest_format, filter,
4436ca29ff0Smrg                  &dest, &binfo.dest_image);
4446ca29ff0Smrg
4456ca29ff0Smrg    run_benchmark (&binfo);
4466ca29ff0Smrg
4476ca29ff0Smrg    return EXIT_SUCCESS;
4486ca29ff0Smrg}
449