11b18d63aSmrg#include <assert.h>
21b18d63aSmrg#include <stdlib.h>
31b18d63aSmrg#include <stdio.h>
41b18d63aSmrg#include <string.h>
59ad247e8Sjmcneill#include "utils.h"
61b18d63aSmrg
71b18d63aSmrg/*
81b18d63aSmrg * We have a source image filled with solid color, set NORMAL or PAD repeat,
91b18d63aSmrg * and some transform which results in nearest neighbour scaling.
101b18d63aSmrg *
111b18d63aSmrg * The expected result is either that the destination image filled with this solid
121b18d63aSmrg * color or, if the transformation is such that we can't composite anything at
131b18d63aSmrg * all, that nothing has changed in the destination.
141b18d63aSmrg *
151b18d63aSmrg * The surrounding memory of the source image is a different solid color so that
161b18d63aSmrg * we are sure to get failures if we access it.
171b18d63aSmrg */
181b18d63aSmrgstatic int
191b18d63aSmrgrun_test (int32_t		dst_width,
201b18d63aSmrg	  int32_t		dst_height,
211b18d63aSmrg	  int32_t		src_width,
221b18d63aSmrg	  int32_t		src_height,
231b18d63aSmrg	  int32_t		src_x,
241b18d63aSmrg	  int32_t		src_y,
251b18d63aSmrg	  int32_t		scale_x,
261b18d63aSmrg	  int32_t		scale_y,
271b18d63aSmrg	  pixman_filter_t	filter,
281b18d63aSmrg	  pixman_repeat_t	repeat)
291b18d63aSmrg{
301b18d63aSmrg    pixman_image_t *   src_img;
311b18d63aSmrg    pixman_image_t *   dst_img;
321b18d63aSmrg    pixman_transform_t transform;
331b18d63aSmrg    uint32_t *         srcbuf;
341b18d63aSmrg    uint32_t *         dstbuf;
351b18d63aSmrg    pixman_color_t     color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc };
369ad247e8Sjmcneill    pixman_image_t *   solid;
371b18d63aSmrg    int result;
381b18d63aSmrg    int i;
391b18d63aSmrg
401b18d63aSmrg    static const pixman_fixed_t kernel[] =
411b18d63aSmrg    {
421b18d63aSmrg#define D(f)	(pixman_double_to_fixed (f) + 0x0001)
431b18d63aSmrg
441b18d63aSmrg	pixman_int_to_fixed (5),
451b18d63aSmrg	pixman_int_to_fixed (5),
461b18d63aSmrg	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
471b18d63aSmrg	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
481b18d63aSmrg	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
491b18d63aSmrg	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
501b18d63aSmrg	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0)
511b18d63aSmrg    };
521b18d63aSmrg
531b18d63aSmrg    result = 0;
541b18d63aSmrg
551b18d63aSmrg    srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4);
561b18d63aSmrg    dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4);
571b18d63aSmrg
581b18d63aSmrg    memset (srcbuf, 0x88, src_width * src_height * 4);
591b18d63aSmrg    memset (dstbuf, 0x33, dst_width * dst_height * 4);
601b18d63aSmrg
611b18d63aSmrg    src_img = pixman_image_create_bits (
621b18d63aSmrg        PIXMAN_a8r8g8b8, src_width, src_height,
631b18d63aSmrg	srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4);
641b18d63aSmrg
659ad247e8Sjmcneill    solid = pixman_image_create_solid_fill (&color_cc);
669ad247e8Sjmcneill    pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, src_img,
679ad247e8Sjmcneill			      0, 0, 0, 0, 0, 0, src_width, src_height);
689ad247e8Sjmcneill    pixman_image_unref (solid);
691b18d63aSmrg
701b18d63aSmrg    dst_img = pixman_image_create_bits (
711b18d63aSmrg        PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4);
721b18d63aSmrg
731b18d63aSmrg    pixman_transform_init_scale (&transform, scale_x, scale_y);
741b18d63aSmrg    pixman_image_set_transform (src_img, &transform);
751b18d63aSmrg    pixman_image_set_repeat (src_img, repeat);
761b18d63aSmrg    if (filter == PIXMAN_FILTER_CONVOLUTION)
771b18d63aSmrg	pixman_image_set_filter (src_img, filter, kernel, 27);
781b18d63aSmrg    else
791b18d63aSmrg	pixman_image_set_filter (src_img, filter, NULL, 0);
801b18d63aSmrg
811b18d63aSmrg    pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
821b18d63aSmrg                            src_x, src_y, 0, 0, 0, 0, dst_width, dst_height);
831b18d63aSmrg
841b18d63aSmrg    pixman_image_unref (src_img);
851b18d63aSmrg    pixman_image_unref (dst_img);
861b18d63aSmrg
871b18d63aSmrg    for (i = 0; i < dst_width * dst_height; i++)
881b18d63aSmrg    {
891b18d63aSmrg	if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
901b18d63aSmrg	{
911b18d63aSmrg	    result = 1;
921b18d63aSmrg	    break;
931b18d63aSmrg	}
941b18d63aSmrg    }
951b18d63aSmrg
961b18d63aSmrg    free (srcbuf);
971b18d63aSmrg    free (dstbuf);
981b18d63aSmrg    return result;
991b18d63aSmrg}
1001b18d63aSmrg
1016ba797d6Smrgtypedef struct filter_info_t filter_info_t;
1026ba797d6Smrgstruct filter_info_t
1031b18d63aSmrg{
1046ba797d6Smrg    pixman_filter_t value;
1051b18d63aSmrg    char name[28];
1061b18d63aSmrg};
1071b18d63aSmrg
1086ba797d6Smrgstatic const filter_info_t filters[] =
1091b18d63aSmrg{
1101b18d63aSmrg    { PIXMAN_FILTER_NEAREST, "NEAREST" },
1111b18d63aSmrg    { PIXMAN_FILTER_BILINEAR, "BILINEAR" },
1121b18d63aSmrg    { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
1131b18d63aSmrg};
1141b18d63aSmrg
1156ba797d6Smrgtypedef struct repeat_info_t repeat_info_t;
1166ba797d6Smrgstruct repeat_info_t
1176ba797d6Smrg{
1186ba797d6Smrg    pixman_repeat_t value;
1196ba797d6Smrg    char name[28];
1206ba797d6Smrg};
1216ba797d6Smrg
1226ba797d6Smrg
1236ba797d6Smrgstatic const repeat_info_t repeats[] =
1241b18d63aSmrg{
1251b18d63aSmrg    { PIXMAN_REPEAT_PAD, "PAD" },
1261b18d63aSmrg    { PIXMAN_REPEAT_REFLECT, "REFLECT" },
1271b18d63aSmrg    { PIXMAN_REPEAT_NORMAL, "NORMAL" }
1281b18d63aSmrg};
1291b18d63aSmrg
1301b18d63aSmrgstatic int
1311b18d63aSmrgdo_test (int32_t		dst_size,
1321b18d63aSmrg	 int32_t		src_size,
1331b18d63aSmrg	 int32_t		src_offs,
1341b18d63aSmrg	 int32_t		scale_factor)
1351b18d63aSmrg{
1361b18d63aSmrg    int i, j;
1371b18d63aSmrg
1389ad247e8Sjmcneill    for (i = 0; i < ARRAY_LENGTH (filters); ++i)
1391b18d63aSmrg    {
1409ad247e8Sjmcneill	for (j = 0; j < ARRAY_LENGTH (repeats); ++j)
1411b18d63aSmrg	{
1421b18d63aSmrg	    /* horizontal test */
1431b18d63aSmrg	    if (run_test (dst_size, 1,
1441b18d63aSmrg			  src_size, 1,
1451b18d63aSmrg			  src_offs, 0,
1461b18d63aSmrg			  scale_factor, 65536,
1471b18d63aSmrg			  filters[i].value,
1481b18d63aSmrg			  repeats[j].value) != 0)
1491b18d63aSmrg	    {
1501b18d63aSmrg		printf ("Vertical test failed with %s filter and repeat mode %s\n",
1511b18d63aSmrg			filters[i].name, repeats[j].name);
1521b18d63aSmrg
1531b18d63aSmrg		return 1;
1541b18d63aSmrg	    }
1551b18d63aSmrg
1561b18d63aSmrg	    /* vertical test */
1571b18d63aSmrg	    if (run_test (1, dst_size,
1581b18d63aSmrg			  1, src_size,
1591b18d63aSmrg			  0, src_offs,
1601b18d63aSmrg			  65536, scale_factor,
1611b18d63aSmrg			  filters[i].value,
1621b18d63aSmrg			  repeats[j].value) != 0)
1631b18d63aSmrg	    {
1641b18d63aSmrg		printf ("Vertical test failed with %s filter and repeat mode %s\n",
1651b18d63aSmrg			filters[i].name, repeats[j].name);
1661b18d63aSmrg
1671b18d63aSmrg		return 1;
1681b18d63aSmrg	    }
1691b18d63aSmrg	}
1701b18d63aSmrg    }
1711b18d63aSmrg
1721b18d63aSmrg    return 0;
1731b18d63aSmrg}
1741b18d63aSmrg
1751b18d63aSmrgint
1761b18d63aSmrgmain (int argc, char *argv[])
1771b18d63aSmrg{
1781b18d63aSmrg    int i;
1791b18d63aSmrg
1801b18d63aSmrg    pixman_disable_out_of_bounds_workaround ();
1811b18d63aSmrg
1821b18d63aSmrg    /* can potentially crash */
1831b18d63aSmrg    assert (do_test (
1841b18d63aSmrg		48000, 32767, 1, 65536 * 128) == 0);
1851b18d63aSmrg
1861b18d63aSmrg    /* can potentially get into a deadloop */
1871b18d63aSmrg    assert (do_test (
1881b18d63aSmrg		16384, 65536, 32, 32768) == 0);
1891b18d63aSmrg
1901b18d63aSmrg    /* can potentially access memory outside source image buffer */
1911b18d63aSmrg    assert (do_test (
1921b18d63aSmrg		10, 10, 0, 1) == 0);
1931b18d63aSmrg    assert (do_test (
1941b18d63aSmrg		10, 10, 0, 0) == 0);
1951b18d63aSmrg
1961b18d63aSmrg    for (i = 0; i < 100; ++i)
1971b18d63aSmrg    {
1981b18d63aSmrg	pixman_fixed_t one_seventh =
1991b18d63aSmrg	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16);
2001b18d63aSmrg
2011b18d63aSmrg	assert (do_test (
2021b18d63aSmrg		    1, 7, 3, one_seventh + i - 50) == 0);
2031b18d63aSmrg    }
2041b18d63aSmrg
2051b18d63aSmrg    for (i = 0; i < 100; ++i)
2061b18d63aSmrg    {
2071b18d63aSmrg	pixman_fixed_t scale =
2081b18d63aSmrg	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16);
2091b18d63aSmrg
2101b18d63aSmrg	assert (do_test (
2111b18d63aSmrg		    1, 32767, 16383, scale + i - 50) == 0);
2121b18d63aSmrg    }
2131b18d63aSmrg
2141b18d63aSmrg    /* can potentially provide invalid results (out of range matrix stuff) */
2151b18d63aSmrg    assert (do_test (
2161b18d63aSmrg	48000, 32767, 16384, 65536 * 128) == 0);
2171b18d63aSmrg
2181b18d63aSmrg    return 0;
2191b18d63aSmrg}
220