Home | History | Annotate | Download | only in test
      1 #include <assert.h>
      2 #include <stdlib.h>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include "utils.h"
      6 
      7 /*
      8  * We have a source image filled with solid color, set NORMAL or PAD repeat,
      9  * and some transform which results in nearest neighbour scaling.
     10  *
     11  * The expected result is either that the destination image filled with this solid
     12  * color or, if the transformation is such that we can't composite anything at
     13  * all, that nothing has changed in the destination.
     14  *
     15  * The surrounding memory of the source image is a different solid color so that
     16  * we are sure to get failures if we access it.
     17  */
     18 static int
     19 run_test (int32_t		dst_width,
     20 	  int32_t		dst_height,
     21 	  int32_t		src_width,
     22 	  int32_t		src_height,
     23 	  int32_t		src_x,
     24 	  int32_t		src_y,
     25 	  int32_t		scale_x,
     26 	  int32_t		scale_y,
     27 	  pixman_filter_t	filter,
     28 	  pixman_repeat_t	repeat)
     29 {
     30     pixman_image_t *   src_img;
     31     pixman_image_t *   dst_img;
     32     pixman_transform_t transform;
     33     uint32_t *         srcbuf;
     34     uint32_t *         dstbuf;
     35     pixman_color_t     color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc };
     36     pixman_image_t *   solid;
     37     int result;
     38     int i;
     39 
     40     static const pixman_fixed_t kernel[] =
     41     {
     42 #define D(f)	(pixman_double_to_fixed (f) + 0x0001)
     43 
     44 	pixman_int_to_fixed (5),
     45 	pixman_int_to_fixed (5),
     46 	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
     47 	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
     48 	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
     49 	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
     50 	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0)
     51     };
     52 
     53     result = 0;
     54 
     55     srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4);
     56     dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4);
     57 
     58     memset (srcbuf, 0x88, src_width * src_height * 4);
     59     memset (dstbuf, 0x33, dst_width * dst_height * 4);
     60 
     61     src_img = pixman_image_create_bits (
     62         PIXMAN_a8r8g8b8, src_width, src_height,
     63 	srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4);
     64 
     65     solid = pixman_image_create_solid_fill (&color_cc);
     66     pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, src_img,
     67 			      0, 0, 0, 0, 0, 0, src_width, src_height);
     68     pixman_image_unref (solid);
     69 
     70     dst_img = pixman_image_create_bits (
     71         PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4);
     72 
     73     pixman_transform_init_scale (&transform, scale_x, scale_y);
     74     pixman_image_set_transform (src_img, &transform);
     75     pixman_image_set_repeat (src_img, repeat);
     76     if (filter == PIXMAN_FILTER_CONVOLUTION)
     77 	pixman_image_set_filter (src_img, filter, kernel, 27);
     78     else
     79 	pixman_image_set_filter (src_img, filter, NULL, 0);
     80 
     81     pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
     82                             src_x, src_y, 0, 0, 0, 0, dst_width, dst_height);
     83 
     84     pixman_image_unref (src_img);
     85     pixman_image_unref (dst_img);
     86 
     87     for (i = 0; i < dst_width * dst_height; i++)
     88     {
     89 	if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
     90 	{
     91 	    result = 1;
     92 	    break;
     93 	}
     94     }
     95 
     96     free (srcbuf);
     97     free (dstbuf);
     98     return result;
     99 }
    100 
    101 typedef struct filter_info_t filter_info_t;
    102 struct filter_info_t
    103 {
    104     pixman_filter_t value;
    105     char name[28];
    106 };
    107 
    108 static const filter_info_t filters[] =
    109 {
    110     { PIXMAN_FILTER_NEAREST, "NEAREST" },
    111     { PIXMAN_FILTER_BILINEAR, "BILINEAR" },
    112     { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
    113 };
    114 
    115 typedef struct repeat_info_t repeat_info_t;
    116 struct repeat_info_t
    117 {
    118     pixman_repeat_t value;
    119     char name[28];
    120 };
    121 
    122 
    123 static const repeat_info_t repeats[] =
    124 {
    125     { PIXMAN_REPEAT_PAD, "PAD" },
    126     { PIXMAN_REPEAT_REFLECT, "REFLECT" },
    127     { PIXMAN_REPEAT_NORMAL, "NORMAL" }
    128 };
    129 
    130 static int
    131 do_test (int32_t		dst_size,
    132 	 int32_t		src_size,
    133 	 int32_t		src_offs,
    134 	 int32_t		scale_factor)
    135 {
    136     int i, j;
    137 
    138     for (i = 0; i < ARRAY_LENGTH (filters); ++i)
    139     {
    140 	for (j = 0; j < ARRAY_LENGTH (repeats); ++j)
    141 	{
    142 	    /* horizontal test */
    143 	    if (run_test (dst_size, 1,
    144 			  src_size, 1,
    145 			  src_offs, 0,
    146 			  scale_factor, 65536,
    147 			  filters[i].value,
    148 			  repeats[j].value) != 0)
    149 	    {
    150 		printf ("Vertical test failed with %s filter and repeat mode %s\n",
    151 			filters[i].name, repeats[j].name);
    152 
    153 		return 1;
    154 	    }
    155 
    156 	    /* vertical test */
    157 	    if (run_test (1, dst_size,
    158 			  1, src_size,
    159 			  0, src_offs,
    160 			  65536, scale_factor,
    161 			  filters[i].value,
    162 			  repeats[j].value) != 0)
    163 	    {
    164 		printf ("Vertical test failed with %s filter and repeat mode %s\n",
    165 			filters[i].name, repeats[j].name);
    166 
    167 		return 1;
    168 	    }
    169 	}
    170     }
    171 
    172     return 0;
    173 }
    174 
    175 int
    176 main (int argc, char *argv[])
    177 {
    178     int i;
    179 
    180     pixman_disable_out_of_bounds_workaround ();
    181 
    182     /* can potentially crash */
    183     assert (do_test (
    184 		48000, 32767, 1, 65536 * 128) == 0);
    185 
    186     /* can potentially get into a deadloop */
    187     assert (do_test (
    188 		16384, 65536, 32, 32768) == 0);
    189 
    190     /* can potentially access memory outside source image buffer */
    191     assert (do_test (
    192 		10, 10, 0, 1) == 0);
    193     assert (do_test (
    194 		10, 10, 0, 0) == 0);
    195 
    196     for (i = 0; i < 100; ++i)
    197     {
    198 	pixman_fixed_t one_seventh =
    199 	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16);
    200 
    201 	assert (do_test (
    202 		    1, 7, 3, one_seventh + i - 50) == 0);
    203     }
    204 
    205     for (i = 0; i < 100; ++i)
    206     {
    207 	pixman_fixed_t scale =
    208 	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16);
    209 
    210 	assert (do_test (
    211 		    1, 32767, 16383, scale + i - 50) == 0);
    212     }
    213 
    214     /* can potentially provide invalid results (out of range matrix stuff) */
    215     assert (do_test (
    216 	48000, 32767, 16384, 65536 * 128) == 0);
    217 
    218     return 0;
    219 }
    220