11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <assert.h>
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h>
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdio.h>
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <string.h>
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "utils.h"
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * We have a source image filled with solid color, set NORMAL or PAD repeat,
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * and some transform which results in nearest neighbour scaling.
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The expected result is either that the destination image filled with this solid
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * color or, if the transformation is such that we can't composite anything at
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * all, that nothing has changed in the destination.
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The surrounding memory of the source image is a different solid color so that
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * we are sure to get failures if we access it.
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic int
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reckrun_test (int32_t		dst_width,
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		dst_height,
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		src_width,
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		src_height,
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		src_x,
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		src_y,
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		scale_x,
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  int32_t		scale_y,
271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  pixman_filter_t	filter,
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	  pixman_repeat_t	repeat)
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *   src_img;
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *   dst_img;
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_transform_t transform;
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *         srcbuf;
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *         dstbuf;
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_color_t     color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc };
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_t *   solid;
371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int result;
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    static const pixman_fixed_t kernel[] =
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define D(f)	(pixman_double_to_fixed (f) + 0x0001)
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_int_to_fixed (5),
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_int_to_fixed (5),
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0)
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    };
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    result = 0;
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4);
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4);
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    memset (srcbuf, 0x88, src_width * src_height * 4);
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    memset (dstbuf, 0x33, dst_width * dst_height * 4);
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    src_img = pixman_image_create_bits (
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        PIXMAN_a8r8g8b8, src_width, src_height,
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4);
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    solid = pixman_image_create_solid_fill (&color_cc);
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, src_img,
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			      0, 0, 0, 0, 0, 0, src_width, src_height);
681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_unref (solid);
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    dst_img = pixman_image_create_bits (
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck        PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4);
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_transform_init_scale (&transform, scale_x, scale_y);
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_set_transform (src_img, &transform);
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_set_repeat (src_img, repeat);
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    if (filter == PIXMAN_FILTER_CONVOLUTION)
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_image_set_filter (src_img, filter, kernel, 27);
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    else
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_image_set_filter (src_img, filter, NULL, 0);
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck                            src_x, src_y, 0, 0, 0, 0, dst_width, dst_height);
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_unref (src_img);
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_image_unref (dst_img);
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < dst_width * dst_height; i++)
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    result = 1;
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    break;
931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    free (srcbuf);
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    free (dstbuf);
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return result;
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef struct filter_info_t filter_info_t;
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstruct filter_info_t
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_filter_t value;
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    char name[28];
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic const filter_info_t filters[] =
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_FILTER_NEAREST, "NEAREST" },
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_FILTER_BILINEAR, "BILINEAR" },
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef struct repeat_info_t repeat_info_t;
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstruct repeat_info_t
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_repeat_t value;
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    char name[28];
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic const repeat_info_t repeats[] =
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_REPEAT_PAD, "PAD" },
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_REPEAT_REFLECT, "REFLECT" },
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    { PIXMAN_REPEAT_NORMAL, "NORMAL" }
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck};
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic int
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdo_test (int32_t		dst_size,
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 int32_t		src_size,
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 int32_t		src_offs,
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 int32_t		scale_factor)
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i, j;
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < ARRAY_LENGTH (filters); ++i)
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	for (j = 0; j < ARRAY_LENGTH (repeats); ++j)
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* horizontal test */
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (run_test (dst_size, 1,
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  src_size, 1,
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  src_offs, 0,
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  scale_factor, 65536,
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  filters[i].value,
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  repeats[j].value) != 0)
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		printf ("Vertical test failed with %s filter and repeat mode %s\n",
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			filters[i].name, repeats[j].name);
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		return 1;
1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* vertical test */
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    if (run_test (1, dst_size,
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  1, src_size,
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  0, src_offs,
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  65536, scale_factor,
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  filters[i].value,
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			  repeats[j].value) != 0)
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		printf ("Vertical test failed with %s filter and repeat mode %s\n",
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			filters[i].name, repeats[j].name);
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		return 1;
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return 0;
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reckint
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reckmain (int argc, char *argv[])
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int i;
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_disable_out_of_bounds_workaround ();
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* can potentially crash */
1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    assert (do_test (
1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		48000, 32767, 1, 65536 * 128) == 0);
1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* can potentially get into a deadloop */
1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    assert (do_test (
1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		16384, 65536, 32, 32768) == 0);
1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* can potentially access memory outside source image buffer */
1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    assert (do_test (
1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		10, 10, 0, 1) == 0);
1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    assert (do_test (
1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		10, 10, 0, 0) == 0);
1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < 100; ++i)
1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t one_seventh =
1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16);
2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	assert (do_test (
2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    1, 7, 3, one_seventh + i - 50) == 0);
2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (i = 0; i < 100; ++i)
2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t scale =
2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16);
2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	assert (do_test (
2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    1, 32767, 16383, scale + i - 50) == 0);
2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    /* can potentially provide invalid results (out of range matrix stuff) */
2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    assert (do_test (
2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	48000, 32767, 16384, 65536 * 128) == 0);
2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    return 0;
2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
220