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