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