• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "utils.h"
4 
5 #define WIDTH 48
6 #define HEIGHT 48
7 
8 static const pixman_format_code_t formats[] =
9 {
10     PIXMAN_a8r8g8b8,
11     PIXMAN_a2r10g10b10,
12     PIXMAN_a4r4g4b4,
13     PIXMAN_a8,
14     PIXMAN_rgba_float,
15 };
16 
17 static const pixman_format_code_t alpha_formats[] =
18 {
19     PIXMAN_null,
20     PIXMAN_a8,
21     PIXMAN_a2r10g10b10,
22     PIXMAN_a4r4g4b4,
23     PIXMAN_rgba_float,
24 };
25 
26 static const int origins[] =
27 {
28     0, 10, -100
29 };
30 
31 static void
on_destroy(pixman_image_t * image,void * data)32 on_destroy (pixman_image_t *image, void *data)
33 {
34     uint32_t *bits = pixman_image_get_data (image);
35 
36     fence_free (bits);
37 }
38 
39 static pixman_image_t *
make_image(pixman_format_code_t format)40 make_image (pixman_format_code_t format)
41 {
42     uint32_t *bits;
43     uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
44     pixman_image_t *image;
45 
46     if (format != PIXMAN_rgba_float)
47 	bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
48     else
49 	bits = (uint32_t *)make_random_floats (WIDTH * HEIGHT * bpp);
50 
51     image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
52 
53     if (image && bits)
54 	pixman_image_set_destroy_function (image, on_destroy, NULL);
55 
56     return image;
57 }
58 
59 static float
get_alpha(pixman_image_t * image,int x,int y,int orig_x,int orig_y)60 get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
61 {
62     uint8_t *bits;
63     uint32_t r;
64 
65     if (image->common.alpha_map)
66     {
67 	if (x - orig_x >= 0 && x - orig_x < WIDTH &&
68 	    y - orig_y >= 0 && y - orig_y < HEIGHT)
69 	{
70 	    image = (pixman_image_t *)image->common.alpha_map;
71 
72 	    x -= orig_x;
73 	    y -= orig_y;
74 	}
75 	else
76 	{
77 	    return 0.f;
78 	}
79     }
80 
81     bits = (uint8_t *)image->bits.bits;
82 
83     if (image->bits.format == PIXMAN_a8)
84     {
85 	r = bits[y * WIDTH + x];
86 	return r / 255.f;
87     }
88     else if (image->bits.format == PIXMAN_a2r10g10b10)
89     {
90 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
91 	return r / 3.f;
92     }
93     else if (image->bits.format == PIXMAN_a8r8g8b8)
94     {
95 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
96 	return r / 255.f;
97     }
98     else if (image->bits.format == PIXMAN_a4r4g4b4)
99     {
100 	r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
101 	return r / 15.f;
102     }
103     else if (image->bits.format == PIXMAN_rgba_float)
104     {
105 	return ((float *)bits)[y * WIDTH * 4 + x * 4 + 3];
106     }
107     else
108     {
109 	assert (0);
110 	return 0.f;
111     }
112 }
113 
114 static uint16_t
get_red(pixman_image_t * image,int x,int y,int orig_x,int orig_y)115 get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
116 {
117     uint8_t *bits;
118     uint16_t r;
119 
120     bits = (uint8_t *)image->bits.bits;
121 
122     if (image->bits.format == PIXMAN_a8)
123     {
124 	r = 0x00;
125     }
126     else if (image->bits.format == PIXMAN_a2r10g10b10)
127     {
128 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 14;
129 	r &= 0xffc0;
130 	r |= (r >> 10);
131     }
132     else if (image->bits.format == PIXMAN_a8r8g8b8)
133     {
134 	r = ((uint32_t *)bits)[y * WIDTH + x] >> 16;
135 	r &= 0xff;
136 	r |= r << 8;
137     }
138     else if (image->bits.format == PIXMAN_a4r4g4b4)
139     {
140 	r = ((uint16_t *)bits)[y * WIDTH + x] >> 8;
141 	r &= 0xf;
142 	r |= r << 4;
143 	r |= r << 8;
144     }
145     else if (image->bits.format == PIXMAN_rgba_float)
146     {
147 	double tmp = ((float *)bits)[y * WIDTH * 4 + x * 4];
148 	return tmp * 65535.;
149     }
150     else
151     {
152 	assert (0);
153     }
154 
155     return r;
156 }
157 
get_alpha_err(pixman_format_code_t sf,pixman_format_code_t saf,pixman_format_code_t df,pixman_format_code_t daf)158 static float get_alpha_err(pixman_format_code_t sf, pixman_format_code_t saf,
159 			   pixman_format_code_t df, pixman_format_code_t daf)
160 {
161 	pixman_format_code_t s = saf != PIXMAN_null ? saf : sf;
162 	pixman_format_code_t d = daf != PIXMAN_null ? daf : df;
163 
164 	/* There are cases where we go through the 8 bit compositing
165 	 * path even with 10bpc and higher formats.
166 	 */
167 	if (PIXMAN_FORMAT_A(s) == PIXMAN_FORMAT_A(d))
168 		return 1.f / 255.f;
169 	else if (PIXMAN_FORMAT_A(s) > PIXMAN_FORMAT_A(d))
170 		return 1.f / ((1 << PIXMAN_FORMAT_A(d)) - 1);
171 	else
172 		return 1.f / ((1 << PIXMAN_FORMAT_A(s)) - 1);
173 }
174 
175 static int
run_test(int s,int d,int sa,int da,int soff,int doff)176 run_test (int s, int d, int sa, int da, int soff, int doff)
177 {
178     pixman_format_code_t sf = formats[s];
179     pixman_format_code_t df = formats[d];
180     pixman_format_code_t saf = alpha_formats[sa];
181     pixman_format_code_t daf = alpha_formats[da];
182     pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
183     pixman_transform_t t1;
184     int j, k;
185     int n_red_bits;
186 
187     soff = origins[soff];
188     doff = origins[doff];
189 
190     n_red_bits = PIXMAN_FORMAT_R (df);
191 
192     /* Source */
193     src = make_image (sf);
194     if (saf != PIXMAN_null)
195     {
196 	alpha = make_image (saf);
197 	pixman_image_set_alpha_map (src, alpha, soff, soff);
198 	pixman_image_unref (alpha);
199     }
200 
201     /* Destination */
202     orig_dst = make_image (df);
203     dst = make_image (df);
204     pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
205 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
206 
207     if (daf != PIXMAN_null)
208     {
209 	orig_alpha = make_image (daf);
210 	alpha = make_image (daf);
211 
212 	pixman_image_composite (PIXMAN_OP_SRC, orig_alpha, NULL, alpha,
213 				0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
214 
215 	pixman_image_set_alpha_map (orig_dst, orig_alpha, doff, doff);
216 	pixman_image_set_alpha_map (dst, alpha, doff, doff);
217 
218 	pixman_image_unref (orig_alpha);
219 	pixman_image_unref (alpha);
220     }
221 
222     /* Transformations, repeats and filters on destinations should be ignored,
223      * so just set some random ones.
224      */
225     pixman_transform_init_identity (&t1);
226     pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
227     pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
228     pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
229 
230     pixman_image_set_transform (dst, &t1);
231     pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
232     pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
233 
234     pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
235 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
236 
237     for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
238     {
239 	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
240 	{
241 	    float sa, da, oda, refa;
242 	    uint16_t sr, dr, odr, refr;
243 	    float err;
244 
245 	    err = get_alpha_err(sf, saf, df, daf);
246 
247 	    sa = get_alpha (src, k, j, soff, soff);
248 	    da = get_alpha (dst, k, j, doff, doff);
249 	    oda = get_alpha (orig_dst, k, j, doff, doff);
250 
251 	    if (sa + oda > 1.f)
252 		refa = 1.f;
253 	    else
254 		refa = sa + oda;
255 
256 	    if (da - err > refa ||
257 	        da + err < refa)
258 	    {
259 		printf ("\nWrong alpha value at (%d, %d). Should be %g; got %g. Source was %g, original dest was %g\n",
260 			k, j, refa, da, sa, oda);
261 
262 		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
263 			format_name (sf),
264 			format_name (saf),
265 			soff, soff,
266 			format_name (df),
267 			format_name (daf),
268 			doff, doff);
269 		return 1;
270 	    }
271 
272 	    /* There are cases where we go through the 8 bit compositing
273 	     * path even with 10bpc formats. This results in incorrect
274 	     * results here, so only do the red check for narrow formats
275 	     */
276 	    if (n_red_bits <= 8)
277 	    {
278 		sr = get_red (src, k, j, soff, soff);
279 		dr = get_red (dst, k, j, doff, doff);
280 		odr = get_red (orig_dst, k, j, doff, doff);
281 
282 		if (sr + odr > 0xffff)
283 		    refr = 0xffff;
284 		else
285 		    refr = sr + odr;
286 
287 		if (abs ((dr >> (16 - n_red_bits)) - (refr >> (16 - n_red_bits))) > 1)
288 		{
289 		    printf ("%d red bits\n", n_red_bits);
290 		    printf ("\nWrong red value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
291 			    k, j, refr, dr, sr, odr);
292 
293 		    printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
294 			    format_name (sf),
295 			    format_name (saf),
296 			    soff, soff,
297 			    format_name (df),
298 			    format_name (daf),
299 			    doff, doff);
300 		    return 1;
301 		}
302 	    }
303 	}
304     }
305 
306     pixman_image_set_alpha_map (src, NULL, 0, 0);
307     pixman_image_set_alpha_map (dst, NULL, 0, 0);
308     pixman_image_set_alpha_map (orig_dst, NULL, 0, 0);
309 
310     pixman_image_unref (src);
311     pixman_image_unref (dst);
312     pixman_image_unref (orig_dst);
313 
314     return 0;
315 }
316 
317 int
main(int argc,char ** argv)318 main (int argc, char **argv)
319 {
320     int i, j, a, b, x, y;
321 
322     prng_srand (0);
323 
324     for (i = 0; i < ARRAY_LENGTH (formats); ++i)
325     {
326 	for (j = 0; j < ARRAY_LENGTH (formats); ++j)
327 	{
328 	    for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
329 	    {
330 		for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
331 		{
332 		    for (x = 0; x < ARRAY_LENGTH (origins); ++x)
333 		    {
334 			for (y = 0; y < ARRAY_LENGTH (origins); ++y)
335 			{
336 			    if (run_test (i, j, a, b, x, y) != 0)
337 				return 1;
338 			}
339 		    }
340 		}
341 	    }
342 	}
343     }
344 
345     return 0;
346 }
347