16ca29ff0Smrg/*
26ca29ff0Smrg * Copyright © 2015 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
276ca29ff0Smrg/*
286ca29ff0Smrg * This test aims to verify both numerical correctness and the honouring of
296ca29ff0Smrg * array bounds for scaled plots (both nearest-neighbour and bilinear) at or
306ca29ff0Smrg * close to the boundary conditions for applicability of "cover" type fast paths
316ca29ff0Smrg * and iter fetch routines.
326ca29ff0Smrg *
336ca29ff0Smrg * It has a secondary purpose: by setting the env var EXACT (to any value) it
346ca29ff0Smrg * will only test plots that are exactly on the boundary condition. This makes
356ca29ff0Smrg * it possible to ensure that "cover" routines are being used to the maximum,
366ca29ff0Smrg * although this requires the use of a debugger or code instrumentation to
376ca29ff0Smrg * verify.
386ca29ff0Smrg */
396ca29ff0Smrg
406ca29ff0Smrg#include "utils.h"
416ca29ff0Smrg#include <stdlib.h>
426ca29ff0Smrg#include <stdio.h>
436ca29ff0Smrg
446ca29ff0Smrg/* Approximate limits for random scale factor generation - these ensure we can
456ca29ff0Smrg * get at least 8x reduction and 8x enlargement.
466ca29ff0Smrg */
476ca29ff0Smrg#define LOG2_MAX_FACTOR (3)
486ca29ff0Smrg
496ca29ff0Smrg/* 1/sqrt(2) (or sqrt(0.5), or 2^-0.5) as a 0.32 fixed-point number */
506ca29ff0Smrg#define INV_SQRT_2_0POINT32_FIXED (0xB504F334u)
516ca29ff0Smrg
526ca29ff0Smrg/* The largest increment that can be generated by random_scale_factor().
536ca29ff0Smrg * This occurs when the "mantissa" part is 0xFFFFFFFF and the "exponent"
546ca29ff0Smrg * part is -LOG2_MAX_FACTOR.
556ca29ff0Smrg */
566ca29ff0Smrg#define MAX_INC ((pixman_fixed_t) \
576ca29ff0Smrg                 (INV_SQRT_2_0POINT32_FIXED >> (31 - 16 - LOG2_MAX_FACTOR)))
586ca29ff0Smrg
596ca29ff0Smrg/* Minimum source width (in pixels) based on a typical page size of 4K and
606ca29ff0Smrg * maximum colour depth of 32bpp.
616ca29ff0Smrg */
626ca29ff0Smrg#define MIN_SRC_WIDTH (4096 / 4)
636ca29ff0Smrg
646ca29ff0Smrg/* Derive the destination width so that at max increment we fit within source */
656ca29ff0Smrg#define DST_WIDTH (MIN_SRC_WIDTH * pixman_fixed_1 / MAX_INC)
666ca29ff0Smrg
676ca29ff0Smrg/* Calculate heights the other way round.
686ca29ff0Smrg * No limits due to page alignment here.
696ca29ff0Smrg */
706ca29ff0Smrg#define DST_HEIGHT 3
716ca29ff0Smrg#define SRC_HEIGHT ((DST_HEIGHT * MAX_INC + pixman_fixed_1 - 1) / pixman_fixed_1)
726ca29ff0Smrg
736ca29ff0Smrg/* At the time of writing, all the scaled fast paths use SRC, OVER or ADD
746ca29ff0Smrg * Porter-Duff operators. XOR is included in the list to ensure good
756ca29ff0Smrg * representation of iter scanline fetch routines.
766ca29ff0Smrg */
776ca29ff0Smrgstatic const pixman_op_t op_list[] = {
786ca29ff0Smrg    PIXMAN_OP_SRC,
796ca29ff0Smrg    PIXMAN_OP_OVER,
806ca29ff0Smrg    PIXMAN_OP_ADD,
816ca29ff0Smrg    PIXMAN_OP_XOR,
826ca29ff0Smrg};
836ca29ff0Smrg
846ca29ff0Smrg/* At the time of writing, all the scaled fast paths use a8r8g8b8, x8r8g8b8
856ca29ff0Smrg * or r5g6b5, or red-blue swapped versions of the same. When a mask channel is
866ca29ff0Smrg * used, it is always a8 (and so implicitly not component alpha). a1r5g5b5 is
876ca29ff0Smrg * included because it is the only other format to feature in any iters. */
886ca29ff0Smrgstatic const pixman_format_code_t img_fmt_list[] = {
896ca29ff0Smrg    PIXMAN_a8r8g8b8,
906ca29ff0Smrg    PIXMAN_x8r8g8b8,
916ca29ff0Smrg    PIXMAN_r5g6b5,
926ca29ff0Smrg    PIXMAN_a1r5g5b5
936ca29ff0Smrg};
946ca29ff0Smrg
956ca29ff0Smrg/* This is a flag reflecting the environment variable EXACT. It can be used
966ca29ff0Smrg * to ensure that source coordinates corresponding exactly to the "cover" limits
976ca29ff0Smrg * are used, rather than any "near misses". This can, for example, be used in
986ca29ff0Smrg * conjunction with a debugger to ensure that only COVER fast paths are used.
996ca29ff0Smrg */
1006ca29ff0Smrgstatic int exact;
1016ca29ff0Smrg
1026ca29ff0Smrgstatic pixman_image_t *
1036ca29ff0Smrgcreate_src_image (pixman_format_code_t fmt)
1046ca29ff0Smrg{
1056ca29ff0Smrg    pixman_image_t *tmp_img, *img;
1066ca29ff0Smrg
1076ca29ff0Smrg    /* We need the left-most and right-most MIN_SRC_WIDTH pixels to have
1086ca29ff0Smrg     * predictable values, even though fence_image_create_bits() may allocate
1096ca29ff0Smrg     * an image somewhat larger than that, by an amount that varies depending
1106ca29ff0Smrg     * upon the page size on the current platform. The solution is to create a
1116ca29ff0Smrg     * temporary non-fenced image that is exactly MIN_SRC_WIDTH wide and blit it
1126ca29ff0Smrg     * into the fenced image.
1136ca29ff0Smrg     */
1146ca29ff0Smrg    tmp_img = pixman_image_create_bits (fmt, MIN_SRC_WIDTH, SRC_HEIGHT,
1156ca29ff0Smrg                                        NULL, 0);
1166ca29ff0Smrg    if (tmp_img == NULL)
1176ca29ff0Smrg        return NULL;
1186ca29ff0Smrg
1196ca29ff0Smrg    img = fence_image_create_bits (fmt, MIN_SRC_WIDTH, SRC_HEIGHT, TRUE);
1206ca29ff0Smrg    if (img == NULL)
1216ca29ff0Smrg    {
1226ca29ff0Smrg        pixman_image_unref (tmp_img);
1236ca29ff0Smrg        return NULL;
1246ca29ff0Smrg    }
1256ca29ff0Smrg
1266ca29ff0Smrg    prng_randmemset (tmp_img->bits.bits,
1276ca29ff0Smrg                     tmp_img->bits.rowstride * SRC_HEIGHT * sizeof (uint32_t),
1286ca29ff0Smrg                     0);
1296ca29ff0Smrg    image_endian_swap (tmp_img);
1306ca29ff0Smrg
1316ca29ff0Smrg    pixman_image_composite (PIXMAN_OP_SRC, tmp_img, NULL, img,
1326ca29ff0Smrg                            0, 0, 0, 0, 0, 0,
1336ca29ff0Smrg                            MIN_SRC_WIDTH, SRC_HEIGHT);
1346ca29ff0Smrg    pixman_image_composite (PIXMAN_OP_SRC, tmp_img, NULL, img,
1356ca29ff0Smrg                            0, 0, 0, 0, img->bits.width - MIN_SRC_WIDTH, 0,
1366ca29ff0Smrg                            MIN_SRC_WIDTH, SRC_HEIGHT);
1376ca29ff0Smrg
1386ca29ff0Smrg    pixman_image_unref (tmp_img);
1396ca29ff0Smrg
1406ca29ff0Smrg    return img;
1416ca29ff0Smrg}
1426ca29ff0Smrg
1436ca29ff0Smrgstatic pixman_fixed_t
1446ca29ff0Smrgrandom_scale_factor(void)
1456ca29ff0Smrg{
1466ca29ff0Smrg    /* Get a random number with top bit set. */
1476ca29ff0Smrg    uint32_t f = prng_rand () | 0x80000000u;
1486ca29ff0Smrg
1496ca29ff0Smrg    /* In log(2) space, this is still approximately evenly spread between 31
1506ca29ff0Smrg     * and 32. Divide by sqrt(2) to centre the distribution on 2^31.
1516ca29ff0Smrg     */
1526ca29ff0Smrg    f = ((uint64_t) f * INV_SQRT_2_0POINT32_FIXED) >> 32;
1536ca29ff0Smrg
1546ca29ff0Smrg    /* Now shift right (ie divide by an integer power of 2) to spread the
1556ca29ff0Smrg     * distribution between centres at 2^(16 +/- LOG2_MAX_FACTOR).
1566ca29ff0Smrg     */
1576ca29ff0Smrg    f >>= 31 - 16 + prng_rand_n (2 * LOG2_MAX_FACTOR + 1) - LOG2_MAX_FACTOR;
1586ca29ff0Smrg
1596ca29ff0Smrg    return f;
1606ca29ff0Smrg}
1616ca29ff0Smrg
1626ca29ff0Smrgstatic pixman_fixed_t
1636ca29ff0Smrgcalc_translate (int            dst_size,
1646ca29ff0Smrg                int            src_size,
1656ca29ff0Smrg                pixman_fixed_t scale,
1666ca29ff0Smrg                pixman_bool_t  low_align,
1676ca29ff0Smrg                pixman_bool_t  bilinear)
1686ca29ff0Smrg{
1696ca29ff0Smrg    pixman_fixed_t ref_src, ref_dst, scaled_dst;
1706ca29ff0Smrg
1716ca29ff0Smrg    if (low_align)
1726ca29ff0Smrg    {
1736ca29ff0Smrg        ref_src = bilinear ? pixman_fixed_1 / 2 : pixman_fixed_e;
1746ca29ff0Smrg        ref_dst = pixman_fixed_1 / 2;
1756ca29ff0Smrg    }
1766ca29ff0Smrg    else
1776ca29ff0Smrg    {
1786ca29ff0Smrg        ref_src = pixman_int_to_fixed (src_size) -
1796ca29ff0Smrg                  bilinear * pixman_fixed_1 / 2;
1806ca29ff0Smrg        ref_dst = pixman_int_to_fixed (dst_size) - pixman_fixed_1 / 2;
1816ca29ff0Smrg    }
1826ca29ff0Smrg
1836ca29ff0Smrg    scaled_dst = ((uint64_t) ref_dst * scale + pixman_fixed_1 / 2) /
1846ca29ff0Smrg                 pixman_fixed_1;
1856ca29ff0Smrg
1866ca29ff0Smrg    /* We need the translation to be set such that when ref_dst is fed through
1876ca29ff0Smrg     * the transformation matrix, we get ref_src as the result.
1886ca29ff0Smrg     */
1896ca29ff0Smrg    return ref_src - scaled_dst;
1906ca29ff0Smrg}
1916ca29ff0Smrg
1926ca29ff0Smrgstatic pixman_fixed_t
1936ca29ff0Smrgrandom_offset (void)
1946ca29ff0Smrg{
1956ca29ff0Smrg    pixman_fixed_t offset = 0;
1966ca29ff0Smrg
1976ca29ff0Smrg    /* Ensure we test the exact case quite a lot */
1986ca29ff0Smrg    if (prng_rand_n (2))
1996ca29ff0Smrg        return offset;
2006ca29ff0Smrg
2016ca29ff0Smrg    /* What happens when we are close to the edge of the first
2026ca29ff0Smrg     * interpolation step?
2036ca29ff0Smrg     */
2046ca29ff0Smrg    if (prng_rand_n (2))
2056ca29ff0Smrg        offset += (pixman_fixed_1 >> BILINEAR_INTERPOLATION_BITS) - 16;
2066ca29ff0Smrg
2076ca29ff0Smrg    /* Try fine-grained variations */
2086ca29ff0Smrg    offset += prng_rand_n (32);
2096ca29ff0Smrg
2106ca29ff0Smrg    /* Test in both directions */
2116ca29ff0Smrg    if (prng_rand_n (2))
2126ca29ff0Smrg        offset = -offset;
2136ca29ff0Smrg
2146ca29ff0Smrg    return offset;
2156ca29ff0Smrg}
2166ca29ff0Smrg
2176ca29ff0Smrgstatic void
2186ca29ff0Smrgcheck_transform (pixman_image_t     *dst_img,
2196ca29ff0Smrg                 pixman_image_t     *src_img,
2206ca29ff0Smrg                 pixman_transform_t *transform,
2216ca29ff0Smrg                 pixman_bool_t       bilinear)
2226ca29ff0Smrg{
2236ca29ff0Smrg    pixman_vector_t v1, v2;
2246ca29ff0Smrg
2256ca29ff0Smrg    v1.vector[0] = pixman_fixed_1 / 2;
2266ca29ff0Smrg    v1.vector[1] = pixman_fixed_1 / 2;
2276ca29ff0Smrg    v1.vector[2] = pixman_fixed_1;
2286ca29ff0Smrg    assert (pixman_transform_point (transform, &v1));
2296ca29ff0Smrg
2306ca29ff0Smrg    v2.vector[0] = pixman_int_to_fixed (dst_img->bits.width) -
2316ca29ff0Smrg                   pixman_fixed_1 / 2;
2326ca29ff0Smrg    v2.vector[1] = pixman_int_to_fixed (dst_img->bits.height) -
2336ca29ff0Smrg                   pixman_fixed_1 / 2;
2346ca29ff0Smrg    v2.vector[2] = pixman_fixed_1;
2356ca29ff0Smrg    assert (pixman_transform_point (transform, &v2));
2366ca29ff0Smrg
2376ca29ff0Smrg    if (bilinear)
2386ca29ff0Smrg    {
2396ca29ff0Smrg        assert (v1.vector[0] >= pixman_fixed_1 / 2);
2406ca29ff0Smrg        assert (v1.vector[1] >= pixman_fixed_1 / 2);
2416ca29ff0Smrg        assert (v2.vector[0] <= pixman_int_to_fixed (src_img->bits.width) -
2426ca29ff0Smrg                                    pixman_fixed_1 / 2);
2436ca29ff0Smrg        assert (v2.vector[1] <= pixman_int_to_fixed (src_img->bits.height) -
2446ca29ff0Smrg                                    pixman_fixed_1 / 2);
2456ca29ff0Smrg    }
2466ca29ff0Smrg    else
2476ca29ff0Smrg    {
2486ca29ff0Smrg        assert (v1.vector[0] >= pixman_fixed_e);
2496ca29ff0Smrg        assert (v1.vector[1] >= pixman_fixed_e);
2506ca29ff0Smrg        assert (v2.vector[0] <= pixman_int_to_fixed (src_img->bits.width));
2516ca29ff0Smrg        assert (v2.vector[1] <= pixman_int_to_fixed (src_img->bits.height));
2526ca29ff0Smrg    }
2536ca29ff0Smrg}
2546ca29ff0Smrg
2556ca29ff0Smrgstatic uint32_t
2566ca29ff0Smrgtest_cover (int testnum, int verbose)
2576ca29ff0Smrg{
2586ca29ff0Smrg    pixman_fixed_t         x_scale, y_scale;
2596ca29ff0Smrg    pixman_bool_t          left_align, top_align;
2606ca29ff0Smrg    pixman_bool_t          bilinear;
2616ca29ff0Smrg    pixman_filter_t        filter;
2626ca29ff0Smrg    pixman_op_t            op;
2636ca29ff0Smrg    size_t                 src_fmt_index;
2646ca29ff0Smrg    pixman_format_code_t   src_fmt, dst_fmt, mask_fmt;
2656ca29ff0Smrg    pixman_image_t        *src_img, *dst_img, *mask_img;
2666ca29ff0Smrg    pixman_transform_t     src_transform, mask_transform;
2676ca29ff0Smrg    pixman_fixed_t         fuzz[4];
2686ca29ff0Smrg    uint32_t               crc32;
2696ca29ff0Smrg
2706ca29ff0Smrg    /* We allocate one fenced image for each pixel format up-front. This is to
2716ca29ff0Smrg     * avoid spending a lot of time on memory management rather than on testing
2726ca29ff0Smrg     * Pixman optimisations. We need one per thread because the transformation
2736ca29ff0Smrg     * matrices and filtering are properties of the source and mask images.
2746ca29ff0Smrg     */
2756ca29ff0Smrg    static pixman_image_t *src_imgs[ARRAY_LENGTH (img_fmt_list)];
2766ca29ff0Smrg    static pixman_image_t *mask_bits_img;
2776ca29ff0Smrg    static pixman_bool_t   fence_images_created;
2786ca29ff0Smrg#ifdef USE_OPENMP
2796ca29ff0Smrg#pragma omp threadprivate (src_imgs)
2806ca29ff0Smrg#pragma omp threadprivate (mask_bits_img)
2816ca29ff0Smrg#pragma omp threadprivate (fence_images_created)
2826ca29ff0Smrg#endif
2836ca29ff0Smrg
2846ca29ff0Smrg    if (!fence_images_created)
2856ca29ff0Smrg    {
2866ca29ff0Smrg        int i;
2876ca29ff0Smrg
2886ca29ff0Smrg        prng_srand (0);
2896ca29ff0Smrg
2906ca29ff0Smrg        for (i = 0; i < ARRAY_LENGTH (img_fmt_list); i++)
2916ca29ff0Smrg            src_imgs[i] = create_src_image (img_fmt_list[i]);
2926ca29ff0Smrg
2936ca29ff0Smrg        mask_bits_img = create_src_image (PIXMAN_a8);
2946ca29ff0Smrg
2956ca29ff0Smrg        fence_images_created = TRUE;
2966ca29ff0Smrg    }
2976ca29ff0Smrg
2986ca29ff0Smrg    prng_srand (testnum);
2996ca29ff0Smrg
3006ca29ff0Smrg    x_scale = random_scale_factor ();
3016ca29ff0Smrg    y_scale = random_scale_factor ();
3026ca29ff0Smrg    left_align = prng_rand_n (2);
3036ca29ff0Smrg    top_align = prng_rand_n (2);
3046ca29ff0Smrg    bilinear = prng_rand_n (2);
3056ca29ff0Smrg    filter = bilinear ? PIXMAN_FILTER_BILINEAR : PIXMAN_FILTER_NEAREST;
3066ca29ff0Smrg
3076ca29ff0Smrg    op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))];
3086ca29ff0Smrg
3096ca29ff0Smrg    dst_fmt = img_fmt_list[prng_rand_n (ARRAY_LENGTH (img_fmt_list))];
3106ca29ff0Smrg    dst_img = pixman_image_create_bits (dst_fmt, DST_WIDTH, DST_HEIGHT,
3116ca29ff0Smrg                                        NULL, 0);
3126ca29ff0Smrg    prng_randmemset (dst_img->bits.bits,
3136ca29ff0Smrg                     dst_img->bits.rowstride * DST_HEIGHT * sizeof (uint32_t),
3146ca29ff0Smrg                     0);
3156ca29ff0Smrg    image_endian_swap (dst_img);
3166ca29ff0Smrg
3176ca29ff0Smrg    src_fmt_index = prng_rand_n (ARRAY_LENGTH (img_fmt_list));
3186ca29ff0Smrg    src_fmt = img_fmt_list[src_fmt_index];
3196ca29ff0Smrg    src_img = src_imgs[src_fmt_index];
3206ca29ff0Smrg    pixman_image_set_filter (src_img, filter, NULL, 0);
3216ca29ff0Smrg    pixman_transform_init_scale (&src_transform, x_scale, y_scale);
3226ca29ff0Smrg    src_transform.matrix[0][2] = calc_translate (dst_img->bits.width,
3236ca29ff0Smrg                                                 src_img->bits.width,
3246ca29ff0Smrg                                                 x_scale, left_align, bilinear);
3256ca29ff0Smrg    src_transform.matrix[1][2] = calc_translate (dst_img->bits.height,
3266ca29ff0Smrg                                                 src_img->bits.height,
3276ca29ff0Smrg                                                 y_scale, top_align, bilinear);
3286ca29ff0Smrg
3296ca29ff0Smrg    if (prng_rand_n (2))
3306ca29ff0Smrg    {
3316ca29ff0Smrg        /* No mask */
3326ca29ff0Smrg        mask_fmt = PIXMAN_null;
3336ca29ff0Smrg        mask_img = NULL;
3346ca29ff0Smrg    }
3356ca29ff0Smrg    else if (prng_rand_n (2))
3366ca29ff0Smrg    {
3376ca29ff0Smrg        /* a8 bitmap mask */
3386ca29ff0Smrg        mask_fmt = PIXMAN_a8;
3396ca29ff0Smrg        mask_img = mask_bits_img;
3406ca29ff0Smrg        pixman_image_set_filter (mask_img, filter, NULL, 0);
3416ca29ff0Smrg        pixman_transform_init_scale (&mask_transform, x_scale, y_scale);
3426ca29ff0Smrg        mask_transform.matrix[0][2] = calc_translate (dst_img->bits.width,
3436ca29ff0Smrg                                                      mask_img->bits.width,
3446ca29ff0Smrg                                                      x_scale, left_align,
3456ca29ff0Smrg                                                      bilinear);
3466ca29ff0Smrg        mask_transform.matrix[1][2] = calc_translate (dst_img->bits.height,
3476ca29ff0Smrg                                                      mask_img->bits.height,
3486ca29ff0Smrg                                                      y_scale, top_align,
3496ca29ff0Smrg                                                      bilinear);
3506ca29ff0Smrg    }
3516ca29ff0Smrg    else
3526ca29ff0Smrg    {
3536ca29ff0Smrg        /* Solid mask */
3546ca29ff0Smrg        pixman_color_t color;
3556ca29ff0Smrg        memset (&color, 0xAA, sizeof color);
3566ca29ff0Smrg        mask_fmt = PIXMAN_solid;
3576ca29ff0Smrg        mask_img = pixman_image_create_solid_fill (&color);
3586ca29ff0Smrg    }
3596ca29ff0Smrg
3606ca29ff0Smrg    if (!exact)
3616ca29ff0Smrg    {
3626ca29ff0Smrg        int i = 0;
3636ca29ff0Smrg
3646ca29ff0Smrg        while (i < 4)
3656ca29ff0Smrg            fuzz[i++] = random_offset ();
3666ca29ff0Smrg
3676ca29ff0Smrg        src_transform.matrix[0][2] += fuzz[0];
3686ca29ff0Smrg        src_transform.matrix[1][2] += fuzz[1];
3696ca29ff0Smrg        mask_transform.matrix[0][2] += fuzz[2];
3706ca29ff0Smrg        mask_transform.matrix[1][2] += fuzz[3];
3716ca29ff0Smrg    }
3726ca29ff0Smrg
3736ca29ff0Smrg    pixman_image_set_transform (src_img, &src_transform);
3746ca29ff0Smrg    if (mask_fmt == PIXMAN_a8)
3756ca29ff0Smrg        pixman_image_set_transform (mask_img, &mask_transform);
3766ca29ff0Smrg
3776ca29ff0Smrg    if (verbose)
3786ca29ff0Smrg    {
3796ca29ff0Smrg        printf ("op=%s\n", operator_name (op));
3806ca29ff0Smrg        printf ("src_fmt=%s, dst_fmt=%s, mask_fmt=%s\n",
3816ca29ff0Smrg                format_name (src_fmt), format_name (dst_fmt),
3826ca29ff0Smrg                format_name (mask_fmt));
3836ca29ff0Smrg        printf ("x_scale=0x%08X, y_scale=0x%08X, align %s/%s, %s\n",
3846ca29ff0Smrg                x_scale, y_scale,
3856ca29ff0Smrg                left_align ? "left" : "right", top_align ? "top" : "bottom",
3866ca29ff0Smrg                bilinear ? "bilinear" : "nearest");
3876ca29ff0Smrg
3886ca29ff0Smrg        if (!exact)
3896ca29ff0Smrg        {
3906ca29ff0Smrg            int i = 0;
3916ca29ff0Smrg
3926ca29ff0Smrg            printf ("fuzz factors");
3936ca29ff0Smrg            while (i < 4)
3946ca29ff0Smrg                printf (" %d", fuzz[i++]);
3956ca29ff0Smrg            printf ("\n");
3966ca29ff0Smrg        }
3976ca29ff0Smrg    }
3986ca29ff0Smrg
3996ca29ff0Smrg    if (exact)
4006ca29ff0Smrg    {
4016ca29ff0Smrg        check_transform (dst_img, src_img, &src_transform, bilinear);
4026ca29ff0Smrg        if (mask_fmt == PIXMAN_a8)
4036ca29ff0Smrg            check_transform (dst_img, mask_img, &mask_transform, bilinear);
4046ca29ff0Smrg    }
4056ca29ff0Smrg
4066ca29ff0Smrg    pixman_image_composite (op, src_img, mask_img, dst_img,
4076ca29ff0Smrg                            0, 0, 0, 0, 0, 0,
4086ca29ff0Smrg                            dst_img->bits.width, dst_img->bits.height);
4096ca29ff0Smrg
4106ca29ff0Smrg    if (verbose)
4116ca29ff0Smrg        print_image (dst_img);
4126ca29ff0Smrg
4136ca29ff0Smrg    crc32 = compute_crc32_for_image (0, dst_img);
4146ca29ff0Smrg
4156ca29ff0Smrg    pixman_image_unref (dst_img);
4166ca29ff0Smrg    if (mask_fmt == PIXMAN_solid)
4176ca29ff0Smrg        pixman_image_unref (mask_img);
4186ca29ff0Smrg
4196ca29ff0Smrg    return crc32;
4206ca29ff0Smrg}
4216ca29ff0Smrg
4226ca29ff0Smrg#if BILINEAR_INTERPOLATION_BITS == 7
4236ca29ff0Smrg#define CHECKSUM_FUZZ  0x6B56F607
4246ca29ff0Smrg#define CHECKSUM_EXACT 0xA669F4A3
4256ca29ff0Smrg#elif BILINEAR_INTERPOLATION_BITS == 4
4266ca29ff0Smrg#define CHECKSUM_FUZZ  0x83119ED0
4276ca29ff0Smrg#define CHECKSUM_EXACT 0x0D3382CD
4286ca29ff0Smrg#else
4296ca29ff0Smrg#define CHECKSUM_FUZZ  0x00000000
4306ca29ff0Smrg#define CHECKSUM_EXACT 0x00000000
4316ca29ff0Smrg#endif
4326ca29ff0Smrg
4336ca29ff0Smrgint
4346ca29ff0Smrgmain (int argc, const char *argv[])
4356ca29ff0Smrg{
4366ca29ff0Smrg    unsigned long page_size;
4376ca29ff0Smrg
4386ca29ff0Smrg    page_size = fence_get_page_size ();
4396ca29ff0Smrg    if (page_size == 0 || page_size > 16 * 1024)
4406ca29ff0Smrg        return 77; /* automake SKIP */
4416ca29ff0Smrg
4426ca29ff0Smrg    exact = getenv ("EXACT") != NULL;
4436ca29ff0Smrg    if (exact)
4446ca29ff0Smrg        printf ("Doing plots that are exactly aligned to boundaries\n");
4456ca29ff0Smrg
4466ca29ff0Smrg    return fuzzer_test_main ("cover", 2000000,
4476ca29ff0Smrg                             exact ? CHECKSUM_EXACT : CHECKSUM_FUZZ,
4486ca29ff0Smrg                             test_cover, argc, argv);
4496ca29ff0Smrg}
450