• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
run_test(int32_t dst_width,int32_t dst_height,int32_t src_width,int32_t src_height,int32_t src_x,int32_t src_y,int32_t scale_x,int32_t scale_y,pixman_filter_t filter,pixman_repeat_t repeat)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
do_test(int32_t dst_size,int32_t src_size,int32_t src_offs,int32_t scale_factor)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
main(int argc,char * argv[])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