test: Fix bug in color_correct() in composite.c
[profile/ivi/pixman.git] / test / composite.c
1 /*
2  * Copyright © 2005 Eric Anholt
3  * Copyright © 2009 Chris Wilson
4  * Copyright © 2010 Soeren Sandmann
5  * Copyright © 2010 Red Hat, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Eric Anholt not be used in
12  * advertising or publicity pertaining to distribution of the software without
13  * specific, written prior permission.  Eric Anholt makes no
14  * representations about the suitability of this software for any purpose.  It
15  * is provided "as is" without express or implied warranty.
16  *
17  * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25
26 #include <pixman.h>
27 #include <stdio.h>
28 #include <stdlib.h> /* abort() */
29 #include <math.h>
30 #include <config.h>
31
32 #define FALSE 0
33 #define TRUE !FALSE
34
35 #define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
36 #define min(a,b) ((a) <= (b) ? (a) : (b))
37 #define max(a,b) ((a) >= (b) ? (a) : (b))
38
39 typedef struct color_t color_t;
40 typedef struct format_t format_t;
41 typedef struct image_t image_t;
42 typedef struct operator_t operator_t;
43
44 struct color_t
45 {
46     double r, g, b, a;
47 };
48
49 struct format_t
50 {
51     pixman_format_code_t format;
52     const char *name;
53 };
54
55 static color_t colors[] =
56 {
57     /* these are premultiplied in main() */
58     { 1.0, 1.0, 1.0, 1.0 },
59     { 1.0, 0.0, 0.0, 1.0 },
60     { 0.0, 1.0, 0.0, 1.0 },
61     { 0.0, 0.0, 1.0, 1.0 },
62     { 0.0, 0.0, 0.0, 1.0 },
63     { 0.5, 0.0, 0.0, 0.5 },
64 };
65
66 static uint16_t
67 _color_double_to_short (double d)
68 {
69     uint32_t i;
70
71     i = (uint32_t) (d * 65536);
72     i -= (i >> 16);
73
74     return i;
75 }
76
77 static void
78 compute_pixman_color (const color_t *color,
79                       pixman_color_t *out)
80 {
81     out->red   = _color_double_to_short (color->r);
82     out->green = _color_double_to_short (color->g);
83     out->blue  = _color_double_to_short (color->b);
84     out->alpha = _color_double_to_short (color->a);
85 }
86
87 static const format_t formats[] =
88 {
89 #define P(x) { PIXMAN_##x, #x }
90
91     /* 32bpp formats */
92     P(a8r8g8b8),
93     P(x8r8g8b8),
94     P(a8b8g8r8),
95     P(x8b8g8r8),
96     P(b8g8r8a8),
97     P(b8g8r8x8),
98     P(x2r10g10b10),
99     P(x2b10g10r10),
100
101     /* 24bpp formats */
102     P(r8g8b8),
103     P(b8g8r8),
104     P(r5g6b5),
105     P(b5g6r5),
106
107     /* 16bpp formats */
108     P(x1r5g5b5),
109     P(x1b5g5r5),
110
111     /* 8bpp formats */
112     P(a8),
113
114 #if 0
115     /* XXX: and here the errors begin!
116      *
117      * The formats below all have channels with 4 bits or less, and
118      * the eval_diff code doesn't deal correctly with that.
119      */
120     P(a2r10g10b10),
121     P(a2b10g10r10),
122
123     /* 16bpp formats */
124     P(a1r5g5b5),
125     P(a1b5g5r5),
126     P(a4b4g4r4),
127     P(x4b4g4r4),
128     P(a4r4g4b4),
129     P(x4r4g4b4),
130
131     /* 8bpp formats */
132     P(r3g3b2),
133     P(b2g3r3),
134     P(a2r2g2b2),
135     P(a2b2g2r2),
136
137     P(x4a4),
138
139     /* 4bpp formats */
140     P(a4),
141     P(r1g2b1),
142     P(b1g2r1),
143     P(a1r1g1b1),
144     P(a1b1g1r1),
145
146     /* 1bpp formats */
147     P(a1)
148 #endif
149 #undef P
150 };
151
152 struct image_t
153 {
154     pixman_image_t *image;
155     const format_t *format;
156     const color_t *color;
157     pixman_repeat_t repeat;
158     int size;
159 };
160
161 struct operator_t
162 {
163     pixman_op_t op;
164     const char *name;
165 };
166
167 static const operator_t operators[] =
168 {
169 #define P(x) { PIXMAN_OP_##x, #x }
170     P(CLEAR),
171     P(SRC),
172     P(DST),
173     P(OVER),
174     P(OVER_REVERSE),
175     P(IN),
176     P(IN_REVERSE),
177     P(OUT),
178     P(OUT_REVERSE),
179     P(ATOP),
180     P(ATOP_REVERSE),
181     P(XOR),
182     P(ADD),
183     P(SATURATE),
184
185     P(DISJOINT_CLEAR),
186     P(DISJOINT_SRC),
187     P(DISJOINT_DST),
188     P(DISJOINT_OVER),
189     P(DISJOINT_OVER_REVERSE),
190     P(DISJOINT_IN),
191     P(DISJOINT_IN_REVERSE),
192     P(DISJOINT_OUT),
193     P(DISJOINT_OUT_REVERSE),
194     P(DISJOINT_ATOP),
195     P(DISJOINT_ATOP_REVERSE),
196     P(DISJOINT_XOR),
197
198     P(CONJOINT_CLEAR),
199     P(CONJOINT_SRC),
200     P(CONJOINT_DST),
201     P(CONJOINT_OVER),
202     P(CONJOINT_OVER_REVERSE),
203     P(CONJOINT_IN),
204     P(CONJOINT_IN_REVERSE),
205     P(CONJOINT_OUT),
206     P(CONJOINT_OUT_REVERSE),
207     P(CONJOINT_ATOP),
208     P(CONJOINT_ATOP_REVERSE),
209     P(CONJOINT_XOR),
210 #undef P
211 };
212
213 static double
214 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
215 {
216 #define mult_chan(src, dst, Fa, Fb) min ((src) * (Fa) + (dst) * (Fb), 1.0)
217
218     double Fa, Fb;
219
220     switch (op)
221     {
222     case PIXMAN_OP_CLEAR:
223     case PIXMAN_OP_DISJOINT_CLEAR:
224     case PIXMAN_OP_CONJOINT_CLEAR:
225         return mult_chan (src, dst, 0.0, 0.0);
226
227     case PIXMAN_OP_SRC:
228     case PIXMAN_OP_DISJOINT_SRC:
229     case PIXMAN_OP_CONJOINT_SRC:
230         return mult_chan (src, dst, 1.0, 0.0);
231
232     case PIXMAN_OP_DST:
233     case PIXMAN_OP_DISJOINT_DST:
234     case PIXMAN_OP_CONJOINT_DST:
235         return mult_chan (src, dst, 0.0, 1.0);
236
237     case PIXMAN_OP_OVER:
238         return mult_chan (src, dst, 1.0, 1.0 - srca);
239
240     case PIXMAN_OP_OVER_REVERSE:
241         return mult_chan (src, dst, 1.0 - dsta, 1.0);
242
243     case PIXMAN_OP_IN:
244         return mult_chan (src, dst, dsta, 0.0);
245
246     case PIXMAN_OP_IN_REVERSE:
247         return mult_chan (src, dst, 0.0, srca);
248
249     case PIXMAN_OP_OUT:
250         return mult_chan (src, dst, 1.0 - dsta, 0.0);
251
252     case PIXMAN_OP_OUT_REVERSE:
253         return mult_chan (src, dst, 0.0, 1.0 - srca);
254
255     case PIXMAN_OP_ATOP:
256         return mult_chan (src, dst, dsta, 1.0 - srca);
257
258     case PIXMAN_OP_ATOP_REVERSE:
259         return mult_chan (src, dst, 1.0 - dsta,  srca);
260
261     case PIXMAN_OP_XOR:
262         return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
263
264     case PIXMAN_OP_ADD:
265         return mult_chan (src, dst, 1.0, 1.0);
266
267     case PIXMAN_OP_SATURATE:
268     case PIXMAN_OP_DISJOINT_OVER_REVERSE:
269         if (srca == 0.0)
270             Fa = 1.0;
271         else
272             Fa = min (1.0, (1.0 - dsta) / srca);
273         return mult_chan (src, dst, Fa, 1.0);
274
275     case PIXMAN_OP_DISJOINT_OVER:
276         if (dsta == 0.0)
277             Fb = 1.0;
278         else
279             Fb = min (1.0, (1.0 - srca) / dsta);
280         return mult_chan (src, dst, 1.0, Fb);
281
282     case PIXMAN_OP_DISJOINT_IN:
283         if (srca == 0.0)
284             Fa = 0.0;
285         else
286             Fa = max (0.0, 1.0 - (1.0 - dsta) / srca);
287         return mult_chan (src, dst, Fa, 0.0);
288
289     case PIXMAN_OP_DISJOINT_IN_REVERSE:
290         if (dsta == 0.0)
291             Fb = 0.0;
292         else
293             Fb = max (0.0, 1.0 - (1.0 - srca) / dsta);
294         return mult_chan (src, dst, 0.0, Fb);
295
296     case PIXMAN_OP_DISJOINT_OUT:
297         if (srca == 0.0)
298             Fa = 1.0;
299         else
300             Fa = min (1.0, (1.0 - dsta) / srca);
301         return mult_chan (src, dst, Fa, 0.0);
302
303     case PIXMAN_OP_DISJOINT_OUT_REVERSE:
304         if (dsta == 0.0)
305             Fb = 1.0;
306         else
307             Fb = min (1.0, (1.0 - srca) / dsta);
308         return mult_chan (src, dst, 0.0, Fb);
309
310     case PIXMAN_OP_DISJOINT_ATOP:
311         if (srca == 0.0)
312             Fa = 0.0;
313         else
314             Fa = max (0.0, 1.0 - (1.0 - dsta) / srca);
315         if (dsta == 0.0)
316             Fb = 1.0;
317         else
318             Fb = min (1.0, (1.0 - srca) / dsta);
319         return mult_chan (src, dst, Fa, Fb);
320
321     case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
322         if (srca == 0.0)
323             Fa = 1.0;
324         else
325             Fa = min (1.0, (1.0 - dsta) / srca);
326         if (dsta == 0.0)
327             Fb = 0.0;
328         else
329             Fb = max (0.0, 1.0 - (1.0 - srca) / dsta);
330         return mult_chan (src, dst, Fa, Fb);
331
332     case PIXMAN_OP_DISJOINT_XOR:
333         if (srca == 0.0)
334             Fa = 1.0;
335         else
336             Fa = min (1.0, (1.0 - dsta) / srca);
337         if (dsta == 0.0)
338             Fb = 1.0;
339         else
340             Fb = min (1.0, (1.0 - srca) / dsta);
341         return mult_chan (src, dst, Fa, Fb);
342
343     case PIXMAN_OP_CONJOINT_OVER:
344         if (dsta == 0.0)
345             Fb = 0.0;
346         else
347             Fb = max (0.0, 1.0 - srca / dsta);
348         return mult_chan (src, dst, 1.0, Fb);
349
350     case PIXMAN_OP_CONJOINT_OVER_REVERSE:
351         if (srca == 0.0)
352             Fa = 0.0;
353         else
354             Fa = max (0.0, 1.0 - dsta / srca);
355         return mult_chan (src, dst, Fa, 1.0);
356
357     case PIXMAN_OP_CONJOINT_IN:
358         if (srca == 0.0)
359             Fa = 1.0;
360         else
361             Fa = min (1.0, dsta / srca);
362         return mult_chan (src, dst, Fa, 0.0);
363
364     case PIXMAN_OP_CONJOINT_IN_REVERSE:
365         if (dsta == 0.0)
366             Fb = 1.0;
367         else
368             Fb = min (1.0, srca / dsta);
369         return mult_chan (src, dst, 0.0, Fb);
370
371     case PIXMAN_OP_CONJOINT_OUT:
372         if (srca == 0.0)
373             Fa = 0.0;
374         else
375             Fa = max (0.0, 1.0 - dsta / srca);
376         return mult_chan (src, dst, Fa, 0.0);
377
378     case PIXMAN_OP_CONJOINT_OUT_REVERSE:
379         if (dsta == 0.0)
380             Fb = 0.0;
381         else
382             Fb = max (0.0, 1.0 - srca / dsta);
383         return mult_chan (src, dst, 0.0, Fb);
384
385     case PIXMAN_OP_CONJOINT_ATOP:
386         if (srca == 0.0)
387             Fa = 1.0;
388         else
389             Fa = min (1.0, dsta / srca);
390         if (dsta == 0.0)
391             Fb = 0.0;
392         else
393             Fb = max (0.0, 1.0 - srca / dsta);
394         return mult_chan (src, dst, Fa, Fb);
395
396     case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
397         if (srca == 0.0)
398             Fa = 0.0;
399         else
400             Fa = max (0.0, 1.0 - dsta / srca);
401         if (dsta == 0.0)
402             Fb = 1.0;
403         else
404             Fb = min (1.0, srca / dsta);
405         return mult_chan (src, dst, Fa, Fb);
406
407     case PIXMAN_OP_CONJOINT_XOR:
408         if (srca == 0.0)
409             Fa = 0.0;
410         else
411             Fa = max (0.0, 1.0 - dsta / srca);
412         if (dsta == 0.0)
413             Fb = 0.0;
414         else
415             Fb = max (0.0, 1.0 - srca / dsta);
416         return mult_chan (src, dst, Fa, Fb);
417
418     case PIXMAN_OP_MULTIPLY:
419     case PIXMAN_OP_SCREEN:
420     case PIXMAN_OP_OVERLAY:
421     case PIXMAN_OP_DARKEN:
422     case PIXMAN_OP_LIGHTEN:
423     case PIXMAN_OP_COLOR_DODGE:
424     case PIXMAN_OP_COLOR_BURN:
425     case PIXMAN_OP_HARD_LIGHT:
426     case PIXMAN_OP_SOFT_LIGHT:
427     case PIXMAN_OP_DIFFERENCE:
428     case PIXMAN_OP_EXCLUSION:
429     case PIXMAN_OP_HSL_HUE:
430     case PIXMAN_OP_HSL_SATURATION:
431     case PIXMAN_OP_HSL_COLOR:
432     case PIXMAN_OP_HSL_LUMINOSITY:
433     default:
434         abort();
435     }
436 #undef mult_chan
437 }
438
439 static void
440 do_composite (pixman_op_t op,
441               const color_t *src,
442               const color_t *mask,
443               const color_t *dst,
444               color_t *result,
445               pixman_bool_t component_alpha)
446 {
447     color_t srcval, srcalpha;
448
449     if (mask == NULL)
450     {
451         srcval = *src;
452
453         srcalpha.r = src->a;
454         srcalpha.g = src->a;
455         srcalpha.b = src->a;
456         srcalpha.a = src->a;
457     }
458     else if (component_alpha)
459     {
460         srcval.r = src->r * mask->r;
461         srcval.g = src->g * mask->g;
462         srcval.b = src->b * mask->b;
463         srcval.a = src->a * mask->a;
464
465         srcalpha.r = src->a * mask->r;
466         srcalpha.g = src->a * mask->g;
467         srcalpha.b = src->a * mask->b;
468         srcalpha.a = src->a * mask->a;
469     }
470     else
471     {
472         srcval.r = src->r * mask->a;
473         srcval.g = src->g * mask->a;
474         srcval.b = src->b * mask->a;
475         srcval.a = src->a * mask->a;
476
477         srcalpha.r = src->a * mask->a;
478         srcalpha.g = src->a * mask->a;
479         srcalpha.b = src->a * mask->a;
480         srcalpha.a = src->a * mask->a;
481     }
482
483     result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
484     result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
485     result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
486     result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
487 }
488
489 static void
490 color_correct (pixman_format_code_t format,
491                color_t *color)
492 {
493 #define MASK(x) ((1 << (x)) - 1)
494 #define round_pix(pix, m)                                               \
495     ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m)))
496
497     if (PIXMAN_FORMAT_R (format) == 0)
498     {
499         color->r = 0.0;
500         color->g = 0.0;
501         color->b = 0.0;
502     }
503     else
504     {
505         color->r = round_pix (color->r, PIXMAN_FORMAT_R (format));
506         color->g = round_pix (color->g, PIXMAN_FORMAT_G (format));
507         color->b = round_pix (color->b, PIXMAN_FORMAT_B (format));
508     }
509
510     if (PIXMAN_FORMAT_A (format) == 0)
511         color->a = 1.0;
512     else
513         color->a = round_pix (color->a, PIXMAN_FORMAT_A (format));
514
515 #undef round_pix
516 #undef MASK
517 }
518
519 static void
520 get_pixel (pixman_image_t *image,
521            pixman_format_code_t format,
522            color_t *color)
523 {
524 #define MASK(N) ((1UL << (N))-1)
525
526     unsigned long rs, gs, bs, as;
527     int a, r, g, b;
528     unsigned long val;
529
530     val = *(unsigned long *) pixman_image_get_data (image);
531 #ifdef WORDS_BIGENDIAN
532     val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format);
533 #endif
534
535     /* Number of bits in each channel */
536     a = PIXMAN_FORMAT_A (format);
537     r = PIXMAN_FORMAT_R (format);
538     g = PIXMAN_FORMAT_G (format);
539     b = PIXMAN_FORMAT_B (format);
540
541     switch (PIXMAN_FORMAT_TYPE (format))
542     {
543     case PIXMAN_TYPE_ARGB:
544         bs = 0;
545         gs = b + bs;
546         rs = g + gs;
547         as = r + rs;
548         break;
549
550     case PIXMAN_TYPE_ABGR:
551         rs = 0;
552         gs = r + rs;
553         bs = g + gs;
554         as = b + bs;
555         break;
556
557     case PIXMAN_TYPE_BGRA:
558         as = 0;
559         rs = PIXMAN_FORMAT_BPP (format) - (b + g + r);
560         gs = r + rs;
561         bs = g + gs;
562         break;
563
564     case PIXMAN_TYPE_A:
565         as = 0;
566         rs = 0;
567         gs = 0;
568         bs = 0;
569         break;
570
571     case PIXMAN_TYPE_OTHER:
572     case PIXMAN_TYPE_COLOR:
573     case PIXMAN_TYPE_GRAY:
574     case PIXMAN_TYPE_YUY2:
575     case PIXMAN_TYPE_YV12:
576     default:
577         abort ();
578         as = 0;
579         rs = 0;
580         gs = 0;
581         bs = 0;
582         break;
583     }
584
585     if (MASK (a) != 0)
586         color->a = ((val >> as) & MASK (a)) / (double) MASK (a);
587     else
588         color->a = 1.0;
589
590     if (MASK (r) != 0)
591     {
592         color->r = ((val >> rs) & MASK (r)) / (double) MASK (r);
593         color->g = ((val >> gs) & MASK (g)) / (double) MASK (g);
594         color->b = ((val >> bs) & MASK (b)) / (double) MASK (b);
595     }
596     else
597     {
598         color->r = 0.0;
599         color->g = 0.0;
600         color->b = 0.0;
601     }
602
603 #undef MASK
604 }
605
606 static double
607 eval_diff (color_t *expected, color_t *test)
608 {
609     double rscale, gscale, bscale, ascale;
610     double rdiff, gdiff, bdiff, adiff;
611
612     /* XXX: Need to be provided mask shifts so we can produce useful error
613      * values.
614      */
615     rscale = 1.0 * (1 << 5);
616     gscale = 1.0 * (1 << 6);
617     bscale = 1.0 * (1 << 5);
618     ascale = 1.0 * 32;
619
620     rdiff = fabs (test->r - expected->r) * rscale;
621     bdiff = fabs (test->g - expected->g) * gscale;
622     gdiff = fabs (test->b - expected->b) * bscale;
623     adiff = fabs (test->a - expected->a) * ascale;
624
625     return max (max (max (rdiff, gdiff), bdiff), adiff);
626 }
627
628 static char *
629 describe_image (image_t *info, char *buf, int buflen)
630 {
631     if (info->size)
632     {
633         snprintf (buf, buflen, "%s %dx%d%s",
634                   info->format->name,
635                   info->size, info->size,
636                   info->repeat ? "R" :"");
637     }
638     else
639     {
640         snprintf (buf, buflen, "solid");
641     }
642
643     return buf;
644 }
645
646 /* Test a composite of a given operation, source, mask, and destination
647  * picture.
648  * Fills the window, and samples from the 0,0 pixel corner.
649  */
650 static pixman_bool_t
651 composite_test (image_t *dst,
652                 const operator_t *op,
653                 image_t *src,
654                 image_t *mask,
655                 pixman_bool_t component_alpha)
656 {
657     pixman_color_t fill;
658     pixman_rectangle16_t rect;
659     color_t expected, result, tdst, tsrc, tmsk;
660     double diff;
661     pixman_bool_t success = TRUE;
662
663     compute_pixman_color (dst->color, &fill);
664     rect.x = rect.y = 0;
665     rect.width = rect.height = dst->size;
666     pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image,
667                                   &fill, 1, &rect);
668
669     if (mask != NULL)
670     {
671         pixman_image_set_component_alpha (mask->image, component_alpha);
672         pixman_image_composite (op->op, src->image, mask->image, dst->image,
673                                 0, 0,
674                                 0, 0,
675                                 0, 0,
676                                 dst->size, dst->size);
677
678         tmsk = *mask->color;
679         if (mask->size)
680         {
681             color_correct (mask->format->format, &tmsk);
682
683             if (component_alpha &&
684                 PIXMAN_FORMAT_R (mask->format->format) == 0)
685             {
686                 /* Ax component-alpha masks expand alpha into
687                  * all color channels.
688                  */
689                 tmsk.r = tmsk.g = tmsk.b = tmsk.a;
690             }
691         }
692     }
693     else
694     {
695         pixman_image_composite (op->op, src->image, NULL, dst->image,
696                                 0, 0,
697                                 0, 0,
698                                 0, 0,
699                                 dst->size, dst->size);
700     }
701     get_pixel (dst->image, dst->format->format, &result);
702
703     tdst = *dst->color;
704     color_correct (dst->format->format, &tdst);
705     tsrc = *src->color;
706     if (src->size)
707         color_correct (src->format->format, &tsrc);
708     do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst,
709                   &expected, component_alpha);
710     color_correct (dst->format->format, &expected);
711
712     diff = eval_diff (&expected, &result);
713     if (diff > 3.0)
714     {
715         char buf[40];
716
717         snprintf (buf, sizeof (buf),
718                   "%s %scomposite",
719                   op->name,
720                   component_alpha ? "CA " : "");
721
722         printf ("%s test error of %.4f --\n"
723                 "           R    G    B    A\n"
724                 "got:       %.2f %.2f %.2f %.2f [%08lx]\n"
725                 "expected:  %.2f %.2f %.2f %.2f\n",
726                 buf, diff,
727                 result.r, result.g, result.b, result.a,
728                 *(unsigned long *) pixman_image_get_data (dst->image),
729                 expected.r, expected.g, expected.b, expected.a);
730         
731         if (mask != NULL)
732         {
733             printf ("src color: %.2f %.2f %.2f %.2f\n"
734                     "msk color: %.2f %.2f %.2f %.2f\n"
735                     "dst color: %.2f %.2f %.2f %.2f\n",
736                     src->color->r, src->color->g,
737                     src->color->b, src->color->a,
738                     mask->color->r, mask->color->g,
739                     mask->color->b, mask->color->a,
740                     dst->color->r, dst->color->g,
741                     dst->color->b, dst->color->a);
742             printf ("src: %s, ", describe_image (src, buf, sizeof (buf)));
743             printf ("mask: %s, ", describe_image (mask, buf, sizeof (buf)));
744             printf ("dst: %s\n\n", describe_image (dst, buf, sizeof (buf)));
745         }
746         else
747         {
748             printf ("src color: %.2f %.2f %.2f %.2f\n"
749                     "dst color: %.2f %.2f %.2f %.2f\n",
750                     src->color->r, src->color->g,
751                     src->color->b, src->color->a,
752                     dst->color->r, dst->color->g,
753                     dst->color->b, dst->color->a);
754             printf ("src: %s, ", describe_image (src, buf, sizeof (buf)));
755             printf ("dst: %s\n\n", describe_image (dst, buf, sizeof (buf)));
756         }
757
758         success = FALSE;
759     }
760
761     return success;
762 }
763
764 #define REPEAT 0x01000000
765 #define FLAGS  0xff000000
766
767 static void
768 image_init (image_t *info,
769             int color,
770             int format,
771             int size)
772 {
773     pixman_color_t fill;
774
775     info->color = &colors[color];
776     compute_pixman_color (info->color, &fill);
777
778     info->format = &formats[format];
779     info->size = size & ~FLAGS;
780     info->repeat = PIXMAN_REPEAT_NONE;
781
782     if (info->size)
783     {
784         pixman_rectangle16_t rect;
785
786         info->image = pixman_image_create_bits (info->format->format,
787                                                 info->size, info->size,
788                                                 NULL, 0);
789
790         rect.x = rect.y = 0;
791         rect.width = rect.height = info->size;
792         pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill,
793                                       1, &rect);
794
795         if (size & REPEAT)
796         {
797             pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
798             info->repeat = PIXMAN_REPEAT_NORMAL;
799         }
800     }
801     else
802     {
803         info->image = pixman_image_create_solid_fill (&fill);
804     }
805 }
806
807 static void
808 image_fini (image_t *info)
809 {
810     pixman_image_unref (info->image);
811 }
812
813 int
814 main (void)
815 {
816     pixman_bool_t ok, group_ok = TRUE, ca;
817     int i, d, m, s;
818     int tests_passed = 0, tests_total = 0;
819     int sizes[] = { 1, 1 | REPEAT, 10 };
820     int num_tests;
821
822     for (i = 0; i < ARRAY_LENGTH (colors); i++)
823     {
824         colors[i].r *= colors[i].a;
825         colors[i].g *= colors[i].a;
826         colors[i].b *= colors[i].a;
827     }
828
829     num_tests = ARRAY_LENGTH (colors) * ARRAY_LENGTH (formats);
830
831     for (d = 0; d < num_tests; d++)
832     {
833         image_t dst;
834
835         image_init (
836             &dst, d / ARRAY_LENGTH (formats), d % ARRAY_LENGTH (formats), 1);
837
838
839         for (s = -ARRAY_LENGTH (colors);
840              s < ARRAY_LENGTH (sizes) * num_tests;
841              s++)
842         {
843             image_t src;
844
845             if (s < 0)
846             {
847                 image_init (&src, -s - 1, 0, 0);
848             }
849             else
850             {
851                 image_init (&src,
852                             s / ARRAY_LENGTH (sizes) / ARRAY_LENGTH (formats),
853                             s / ARRAY_LENGTH (sizes) % ARRAY_LENGTH (formats),
854                             sizes[s % ARRAY_LENGTH (sizes)]);
855             }
856
857             for (m = -ARRAY_LENGTH (colors);
858                  m < ARRAY_LENGTH (sizes) * num_tests;
859                  m++)
860             {
861                 image_t mask;
862
863                 if (m < 0)
864                 {
865                     image_init (&mask, -m - 1, 0, 0);
866                 }
867                 else
868                 {
869                     image_init (
870                         &mask,
871                         m / ARRAY_LENGTH (sizes) / ARRAY_LENGTH (formats),
872                         m / ARRAY_LENGTH (sizes) % ARRAY_LENGTH (formats),
873                         sizes[m % ARRAY_LENGTH (sizes)]);
874                 }
875
876                 for (ca = -1; ca <= 1; ca++)
877                 {
878                     for (i = 0; i < ARRAY_LENGTH (operators); i++)
879                     {
880                         const operator_t *op = &operators[i];
881
882                         switch (ca)
883                         {
884                         case -1:
885                             ok = composite_test (&dst, op, &src, NULL, FALSE);
886                             break;
887                         case 0:
888                             ok = composite_test (&dst, op, &src, &mask, FALSE);
889                             break;
890                         case 1:
891                             ok = composite_test (&dst, op, &src, &mask,
892                                                  mask.size? TRUE : FALSE);
893                             break;
894                         default:
895                             ok = FALSE; /* Silence GCC */
896                             break;
897                         }
898                         group_ok = group_ok && ok;
899                         tests_passed += ok;
900                         tests_total++;
901                     }
902                 }
903
904                 image_fini (&mask);
905             }
906             image_fini (&src);
907         }
908         image_fini (&dst);
909     }
910
911     return group_ok == FALSE;
912 }