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