Bug Summary

File:test/composite.c
Location:line 539, column 14
Description:The right operand to '+' is always 0

Annotated Source Code

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 REPEAT0x01000000 0x01000000
84#define FLAGS0xff000000 0xff000000
85
86static const int sizes[] =
87{
88 0,
89 1,
90 1 | REPEAT0x01000000,
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)(((src) * (Fa) + (dst) * (Fb) < 1.0) ? (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)((1.0 < (1.0 - dsta) / srca) ? 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)((1.0 < (1.0 - srca) / dsta) ? 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)((0.0 > 1.0 - (1.0 - dsta) / srca) ? 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)((0.0 > 1.0 - (1.0 - srca) / dsta) ? 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)((1.0 < (1.0 - dsta) / srca) ? 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)((1.0 < (1.0 - srca) / dsta) ? 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)((0.0 > 1.0 - (1.0 - dsta) / srca) ? 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)((1.0 < (1.0 - srca) / dsta) ? 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)((1.0 < (1.0 - dsta) / srca) ? 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)((0.0 > 1.0 - (1.0 - srca) / dsta) ? 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)((1.0 < (1.0 - dsta) / srca) ? 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)((1.0 < (1.0 - srca) / dsta) ? 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)((0.0 > 1.0 - srca / dsta) ? 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)((0.0 > 1.0 - dsta / srca) ? 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)((1.0 < dsta / srca) ? 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)((1.0 < srca / dsta) ? 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)((0.0 > 1.0 - dsta / srca) ? 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)((0.0 > 1.0 - srca / dsta) ? 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)((1.0 < dsta / srca) ? 1.0 : dsta / srca);
384 if (dsta == 0.0)
385 Fb = 0.0;
386 else
387 Fb = MAX (0.0, 1.0 - srca / dsta)((0.0 > 1.0 - srca / dsta) ? 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)((0.0 > 1.0 - dsta / srca) ? 0.0 : 1.0 - dsta / srca);
395 if (dsta == 0.0)
396 Fb = 1.0;
397 else
398 Fb = MIN (1.0, srca / dsta)((1.0 < srca / dsta) ? 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)((0.0 > 1.0 - dsta / srca) ? 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)((0.0 > 1.0 - srca / dsta) ? 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((void*)0))
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)(((format) >> 8) & 0x0f) == 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)(((format) >> 8) & 0x0f));
500 color->g = round_pix (color->g, PIXMAN_FORMAT_G (format)(((format) >> 4) & 0x0f));
501 color->b = round_pix (color->b, PIXMAN_FORMAT_B (format)(((format) ) & 0x0f));
502 }
503
504 if (PIXMAN_FORMAT_A (format)(((format) >> 12) & 0x0f) == 0)
505 color->a = 1.0;
506 else
507 color->a = round_pix (color->a, PIXMAN_FORMAT_A (format)(((format) >> 12) & 0x0f));
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)(((format) >> 24) );
527#endif
528
529 /* Number of bits in each channel */
530 a = PIXMAN_FORMAT_A (format)(((format) >> 12) & 0x0f);
531 r = PIXMAN_FORMAT_R (format)(((format) >> 8) & 0x0f);
532 g = PIXMAN_FORMAT_G (format)(((format) >> 4) & 0x0f);
533 b = PIXMAN_FORMAT_B (format)(((format) ) & 0x0f);
534
535 switch (PIXMAN_FORMAT_TYPE (format)(((format) >> 16) & 0xff))
1
Control jumps to 'case 2:' at line 537
536 {
537 case PIXMAN_TYPE_ARGB2:
538 bs = 0;
2
The value 0 is assigned to 'bs'
539 gs = b + bs;
3
The right operand to '+' is always 0
540 rs = g + gs;
541 as = r + rs;
542 break;
543
544 case PIXMAN_TYPE_ABGR3:
545 rs = 0;
546 gs = r + rs;
547 bs = g + gs;
548 as = b + bs;
549 break;
550
551 case PIXMAN_TYPE_BGRA8:
552 as = 0;
553 rs = PIXMAN_FORMAT_BPP (format)(((format) >> 24) ) - (b + g + r);
554 gs = r + rs;
555 bs = g + gs;
556 break;
557
558 case PIXMAN_TYPE_A1:
559 as = 0;
560 rs = 0;
561 gs = 0;
562 bs = 0;
563 break;
564
565 case PIXMAN_TYPE_OTHER0:
566 case PIXMAN_TYPE_COLOR4:
567 case PIXMAN_TYPE_GRAY5:
568 case PIXMAN_TYPE_YUY26:
569 case PIXMAN_TYPE_YV127:
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)(((format) >> 8) & 0x0f)) - 1);
607 gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)(((format) >> 4) & 0x0f)) - 1);
608 bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)(((format) ) & 0x0f)) - 1);
609 ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)(((format) >> 12) & 0x0f)) - 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)((((((rdiff > gdiff) ? rdiff : gdiff) > bdiff) ? ((rdiff
> gdiff) ? rdiff : gdiff) : bdiff) > adiff) ? ((((rdiff
> gdiff) ? rdiff : gdiff) > bdiff) ? ((rdiff > gdiff
) ? 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 = TRUE1;
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((void*)0))
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)(((mask->format->format) >> 8) & 0x0f) == 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((void*)0), 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((void*)0), &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((void*)0))
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 = FALSE0;
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] & ~FLAGS0xff000000;
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((void*)0), 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 & REPEAT0x01000000)
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)((int) (sizeof (sizes) / sizeof ((sizes) [0]))));
810}
811
812static int
813random_color (void)
814{
815 return lcg_rand_n (ARRAY_LENGTH (colors)((int) (sizeof (colors) / sizeof ((colors) [0]))));
816}
817
818static int
819random_format (void)
820{
821 return lcg_rand_n (ARRAY_LENGTH (formats)((int) (sizeof (formats) / sizeof ((formats) [0]))));
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)((int) (sizeof (operators) / sizeof ((operators) [0]))))]);
839
840 ca = lcg_rand_n (3);
841
842 switch (ca)
843 {
844 case 0:
845 ok = composite_test (&dst, op, &src, NULL((void*)0), FALSE0);
846 break;
847 case 1:
848 ok = composite_test (&dst, op, &src, &mask, FALSE0);
849 break;
850 case 2:
851 ok = composite_test (&dst, op, &src, &mask,
852 mask.size? TRUE1 : FALSE0);
853 break;
854 default:
855 ok = FALSE0;
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) (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(8 * 1024 * 1024); ++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}