1#include <ctype.h>
2#include "utils.h"
3
4static int
5check_op (pixman_op_t          op,
6          pixman_format_code_t src_format,
7          pixman_format_code_t dest_format)
8{
9    uint32_t src_alpha_mask, src_green_mask;
10    uint32_t dest_alpha_mask, dest_green_mask;
11    pixel_checker_t src_checker, dest_checker;
12    pixman_image_t *si, *di;
13    uint32_t sa, sg, da, dg;
14    uint32_t s, d;
15    int retval = 0;
16
17    pixel_checker_init (&src_checker, src_format);
18    pixel_checker_init (&dest_checker, dest_format);
19
20    pixel_checker_get_masks (
21        &src_checker, &src_alpha_mask, NULL, &src_green_mask, NULL);
22    pixel_checker_get_masks (
23        &dest_checker, &dest_alpha_mask, NULL, &dest_green_mask, NULL);
24
25    /* printf ("masks: %x %x %x %x\n", */
26    /* 	    src_alpha_mask, src_green_mask, */
27    /* 	    dest_alpha_mask, dest_green_mask); */
28
29    si = pixman_image_create_bits (src_format, 1, 1, &s, 4);
30    di = pixman_image_create_bits (dest_format, 1, 1, &d, 4);
31
32    sa = 0;
33    do
34    {
35        sg = 0;
36        do
37        {
38            da = 0;
39            do
40            {
41                dg = 0;
42                do
43                {
44                    color_t src_color, dest_color, result_color;
45                    uint32_t orig_d;
46
47                    s = sa | sg;
48                    d = da | dg;
49
50                    orig_d = d;
51
52		    pixel_checker_convert_pixel_to_color (&src_checker, s, &src_color);
53		    pixel_checker_convert_pixel_to_color (&dest_checker, d, &dest_color);
54
55		    do_composite (op, &src_color, NULL, &dest_color, &result_color, FALSE);
56
57
58		    if (!is_little_endian())
59                    {
60			s <<= 32 - PIXMAN_FORMAT_BPP (src_format);
61			d <<= 32 - PIXMAN_FORMAT_BPP (dest_format);
62                    }
63
64		    pixman_image_composite32 (op, si, NULL, di,
65					      0, 0, 0, 0, 0, 0, 1, 1);
66
67		    if (!is_little_endian())
68                        d >>= (32 - PIXMAN_FORMAT_BPP (dest_format));
69
70                    if (!pixel_checker_check (&dest_checker, d, &result_color))
71                    {
72                        printf ("---- test failed ----\n");
73                        printf ("operator: %-32s\n", operator_name (op));
74                        printf ("source:   %-12s pixel: %08x\n", format_name (src_format), s);
75                        printf ("dest:     %-12s pixel: %08x\n", format_name (dest_format), orig_d);
76                        printf ("got:      %-12s pixel: %08x\n", format_name (dest_format), d);
77
78                        retval = 1;
79                    }
80
81                    dg -= dest_green_mask;
82                    dg &= dest_green_mask;
83                }
84                while (dg != 0);
85
86                da -= dest_alpha_mask;
87                da &= dest_alpha_mask;
88            }
89            while (da != 0);
90
91            sg -= src_green_mask;
92            sg &= src_green_mask;
93        }
94        while (sg != 0);
95
96        sa -= src_alpha_mask;
97        sa &= src_alpha_mask;
98    }
99    while (sa != 0);
100
101    pixman_image_unref (si);
102    pixman_image_unref (di);
103
104    return retval;
105}
106
107static const pixman_op_t op_list[] =
108{
109    PIXMAN_OP_CLEAR,
110    PIXMAN_OP_SRC,
111    PIXMAN_OP_DST,
112    PIXMAN_OP_OVER,
113    PIXMAN_OP_OVER_REVERSE,
114    PIXMAN_OP_IN,
115    PIXMAN_OP_IN_REVERSE,
116    PIXMAN_OP_OUT,
117    PIXMAN_OP_OUT_REVERSE,
118    PIXMAN_OP_ATOP,
119    PIXMAN_OP_ATOP_REVERSE,
120    PIXMAN_OP_XOR,
121    PIXMAN_OP_ADD,
122    PIXMAN_OP_SATURATE,
123
124    PIXMAN_OP_DISJOINT_CLEAR,
125    PIXMAN_OP_DISJOINT_SRC,
126    PIXMAN_OP_DISJOINT_DST,
127    PIXMAN_OP_DISJOINT_OVER,
128    PIXMAN_OP_DISJOINT_OVER_REVERSE,
129    PIXMAN_OP_DISJOINT_IN,
130    PIXMAN_OP_DISJOINT_IN_REVERSE,
131    PIXMAN_OP_DISJOINT_OUT,
132    PIXMAN_OP_DISJOINT_OUT_REVERSE,
133    PIXMAN_OP_DISJOINT_ATOP,
134    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
135    PIXMAN_OP_DISJOINT_XOR,
136
137    PIXMAN_OP_CONJOINT_CLEAR,
138    PIXMAN_OP_CONJOINT_SRC,
139    PIXMAN_OP_CONJOINT_DST,
140    PIXMAN_OP_CONJOINT_OVER,
141    PIXMAN_OP_CONJOINT_OVER_REVERSE,
142    PIXMAN_OP_CONJOINT_IN,
143    PIXMAN_OP_CONJOINT_IN_REVERSE,
144    PIXMAN_OP_CONJOINT_OUT,
145    PIXMAN_OP_CONJOINT_OUT_REVERSE,
146    PIXMAN_OP_CONJOINT_ATOP,
147    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
148    PIXMAN_OP_CONJOINT_XOR,
149};
150
151static const pixman_format_code_t format_list[] =
152{
153    PIXMAN_a8r8g8b8,
154    PIXMAN_x8r8g8b8,
155    PIXMAN_a8b8g8r8,
156    PIXMAN_x8b8g8r8,
157    PIXMAN_b8g8r8a8,
158    PIXMAN_b8g8r8x8,
159    PIXMAN_r8g8b8a8,
160    PIXMAN_r8g8b8x8,
161    PIXMAN_x14r6g6b6,
162    PIXMAN_x2r10g10b10,
163    PIXMAN_a2r10g10b10,
164    PIXMAN_x2b10g10r10,
165    PIXMAN_a2b10g10r10,
166    PIXMAN_a8r8g8b8_sRGB,
167    PIXMAN_r8g8b8,
168    PIXMAN_b8g8r8,
169    PIXMAN_r5g6b5,
170    PIXMAN_b5g6r5,
171    PIXMAN_a1r5g5b5,
172    PIXMAN_x1r5g5b5,
173    PIXMAN_a1b5g5r5,
174    PIXMAN_x1b5g5r5,
175    PIXMAN_a4r4g4b4,
176    PIXMAN_x4r4g4b4,
177    PIXMAN_a4b4g4r4,
178    PIXMAN_x4b4g4r4,
179    PIXMAN_a8,
180    PIXMAN_r3g3b2,
181    PIXMAN_b2g3r3,
182    PIXMAN_a2r2g2b2,
183    PIXMAN_a2b2g2r2,
184    PIXMAN_x4a4,
185    PIXMAN_a4,
186    PIXMAN_r1g2b1,
187    PIXMAN_b1g2r1,
188    PIXMAN_a1r1g1b1,
189    PIXMAN_a1b1g1r1,
190    PIXMAN_a1,
191};
192
193static pixman_format_code_t
194format_from_string (const char *s)
195{
196    int i;
197
198    for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
199    {
200        if (strcasecmp (format_name (format_list[i]), s) == 0)
201            return format_list[i];
202    }
203
204    return PIXMAN_null;
205}
206
207static void
208emit (const char *s, int *n_chars)
209{
210    *n_chars += printf ("%s,", s);
211    if (*n_chars > 60)
212    {
213        printf ("\n    ");
214        *n_chars = 0;
215    }
216    else
217    {
218        printf (" ");
219        (*n_chars)++;
220    }
221}
222
223static void
224list_formats (void)
225{
226    int n_chars;
227    int i;
228
229    printf ("Formats:\n    ");
230
231    n_chars = 0;
232    for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
233        emit (format_name (format_list[i]), &n_chars);
234
235    printf ("\n\n");
236}
237
238static void
239list_operators (void)
240{
241    char short_name [128] = { 0 };
242    int i, n_chars;
243
244    printf ("Operators:\n    ");
245
246    n_chars = 0;
247    for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
248    {
249        pixman_op_t op = op_list[i];
250        int j;
251
252        snprintf (short_name, sizeof (short_name) - 1, "%s",
253                  operator_name (op) + strlen ("PIXMAN_OP_"));
254
255        for (j = 0; short_name[j] != '\0'; ++j)
256            short_name[j] = tolower (short_name[j]);
257
258        emit (short_name, &n_chars);
259    }
260
261    printf ("\n\n");
262}
263
264static pixman_op_t
265operator_from_string (const char *s)
266{
267    char full_name[128] = { 0 };
268    int i;
269
270    snprintf (full_name, (sizeof full_name) - 1, "PIXMAN_OP_%s", s);
271
272    for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
273    {
274        pixman_op_t op = op_list[i];
275
276        if (strcasecmp (operator_name (op), full_name) == 0)
277            return op;
278    }
279
280    return PIXMAN_OP_NONE;
281}
282
283int
284main (int argc, char **argv)
285{
286    enum { OPTION_OP, OPTION_SRC, OPTION_DEST, LAST_OPTION } option;
287    pixman_format_code_t src_fmt, dest_fmt;
288    pixman_op_t op;
289
290    op = PIXMAN_OP_NONE;
291    src_fmt = PIXMAN_null;
292    dest_fmt = PIXMAN_null;
293
294    argc--;
295    argv++;
296
297    for (option = OPTION_OP; option < LAST_OPTION; ++option)
298    {
299        char *arg = NULL;
300
301        if (argc)
302        {
303            argc--;
304            arg = *argv++;
305        }
306
307        switch (option)
308        {
309        case OPTION_OP:
310            if (!arg)
311                printf ("  - missing operator\n");
312            else if ((op = operator_from_string (arg)) == PIXMAN_OP_NONE)
313                printf ("  - unknown operator %s\n", arg);
314            break;
315
316        case OPTION_SRC:
317            if (!arg)
318                printf ("  - missing source format\n");
319            else if ((src_fmt = format_from_string (arg)) == PIXMAN_null)
320                printf ("  - unknown source format %s\n", arg);
321            break;
322
323        case OPTION_DEST:
324            if (!arg)
325                printf ("  - missing destination format\n");
326            else if ((dest_fmt = format_from_string (arg)) == PIXMAN_null)
327                printf ("  - unknown destination format %s\n", arg);
328            break;
329
330        default:
331            assert (0);
332            break;
333        }
334    }
335
336    while (argc--)
337    {
338        op = PIXMAN_OP_NONE;
339        printf ("  - unexpected argument: %s\n", *argv++);
340    }
341
342    if (op == PIXMAN_OP_NONE || src_fmt == PIXMAN_null || dest_fmt == PIXMAN_null)
343    {
344        printf ("\nUsage:\n    check-formats <operator> <src-format> <dest-format>\n\n");
345        list_operators();
346        list_formats();
347
348        return -1;
349    }
350
351    return check_op (op, src_fmt, dest_fmt);
352}
353