2 * Copyright © 2005 Eric Anholt
3 * Copyright © 2009 Chris Wilson
4 * Copyright © 2010 Soeren Sandmann
5 * Copyright © 2010 Red Hat, Inc.
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.
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.
26 #include <stdlib.h> /* abort() */
31 typedef struct format_t format_t;
32 typedef struct image_t image_t;
33 typedef struct operator_t operator_t;
37 pixman_format_code_t format;
41 static const color_t colors[] =
43 { 1.0, 1.0, 1.0, 1.0 },
44 { 1.0, 1.0, 1.0, 0.0 },
45 { 0.0, 0.0, 0.0, 1.0 },
46 { 0.0, 0.0, 0.0, 0.0 },
47 { 1.0, 0.0, 0.0, 1.0 },
48 { 0.0, 1.0, 0.0, 1.0 },
49 { 0.0, 0.0, 1.0, 1.0 },
50 { 0.5, 0.0, 0.0, 0.5 },
54 _color_double_to_short (double d)
58 i = (uint32_t) (d * 65536);
65 compute_pixman_color (const color_t *color,
68 out->red = _color_double_to_short (color->r);
69 out->green = _color_double_to_short (color->g);
70 out->blue = _color_double_to_short (color->b);
71 out->alpha = _color_double_to_short (color->a);
74 #define REPEAT 0x01000000
75 #define FLAGS 0xff000000
77 static const int sizes[] =
85 static const format_t formats[] =
87 #define P(x) { PIXMAN_##x, #x }
141 pixman_image_t *image;
142 const format_t *format;
143 const color_t *color;
144 pixman_repeat_t repeat;
154 static const operator_t operators[] =
156 #define P(x) { PIXMAN_OP_##x, #x }
176 P(DISJOINT_OVER_REVERSE),
178 P(DISJOINT_IN_REVERSE),
180 P(DISJOINT_OUT_REVERSE),
182 P(DISJOINT_ATOP_REVERSE),
189 P(CONJOINT_OVER_REVERSE),
191 P(CONJOINT_IN_REVERSE),
193 P(CONJOINT_OUT_REVERSE),
195 P(CONJOINT_ATOP_REVERSE),
201 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
203 #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
209 case PIXMAN_OP_CLEAR:
210 case PIXMAN_OP_DISJOINT_CLEAR:
211 case PIXMAN_OP_CONJOINT_CLEAR:
212 return mult_chan (src, dst, 0.0, 0.0);
215 case PIXMAN_OP_DISJOINT_SRC:
216 case PIXMAN_OP_CONJOINT_SRC:
217 return mult_chan (src, dst, 1.0, 0.0);
220 case PIXMAN_OP_DISJOINT_DST:
221 case PIXMAN_OP_CONJOINT_DST:
222 return mult_chan (src, dst, 0.0, 1.0);
225 return mult_chan (src, dst, 1.0, 1.0 - srca);
227 case PIXMAN_OP_OVER_REVERSE:
228 return mult_chan (src, dst, 1.0 - dsta, 1.0);
231 return mult_chan (src, dst, dsta, 0.0);
233 case PIXMAN_OP_IN_REVERSE:
234 return mult_chan (src, dst, 0.0, srca);
237 return mult_chan (src, dst, 1.0 - dsta, 0.0);
239 case PIXMAN_OP_OUT_REVERSE:
240 return mult_chan (src, dst, 0.0, 1.0 - srca);
243 return mult_chan (src, dst, dsta, 1.0 - srca);
245 case PIXMAN_OP_ATOP_REVERSE:
246 return mult_chan (src, dst, 1.0 - dsta, srca);
249 return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
252 return mult_chan (src, dst, 1.0, 1.0);
254 case PIXMAN_OP_SATURATE:
255 case PIXMAN_OP_DISJOINT_OVER_REVERSE:
259 Fa = MIN (1.0, (1.0 - dsta) / srca);
260 return mult_chan (src, dst, Fa, 1.0);
262 case PIXMAN_OP_DISJOINT_OVER:
266 Fb = MIN (1.0, (1.0 - srca) / dsta);
267 return mult_chan (src, dst, 1.0, Fb);
269 case PIXMAN_OP_DISJOINT_IN:
273 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
274 return mult_chan (src, dst, Fa, 0.0);
276 case PIXMAN_OP_DISJOINT_IN_REVERSE:
280 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
281 return mult_chan (src, dst, 0.0, Fb);
283 case PIXMAN_OP_DISJOINT_OUT:
287 Fa = MIN (1.0, (1.0 - dsta) / srca);
288 return mult_chan (src, dst, Fa, 0.0);
290 case PIXMAN_OP_DISJOINT_OUT_REVERSE:
294 Fb = MIN (1.0, (1.0 - srca) / dsta);
295 return mult_chan (src, dst, 0.0, Fb);
297 case PIXMAN_OP_DISJOINT_ATOP:
301 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
305 Fb = MIN (1.0, (1.0 - srca) / dsta);
306 return mult_chan (src, dst, Fa, Fb);
308 case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
312 Fa = MIN (1.0, (1.0 - dsta) / srca);
316 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
317 return mult_chan (src, dst, Fa, Fb);
319 case PIXMAN_OP_DISJOINT_XOR:
323 Fa = MIN (1.0, (1.0 - dsta) / srca);
327 Fb = MIN (1.0, (1.0 - srca) / dsta);
328 return mult_chan (src, dst, Fa, Fb);
330 case PIXMAN_OP_CONJOINT_OVER:
334 Fb = MAX (0.0, 1.0 - srca / dsta);
335 return mult_chan (src, dst, 1.0, Fb);
337 case PIXMAN_OP_CONJOINT_OVER_REVERSE:
341 Fa = MAX (0.0, 1.0 - dsta / srca);
342 return mult_chan (src, dst, Fa, 1.0);
344 case PIXMAN_OP_CONJOINT_IN:
348 Fa = MIN (1.0, dsta / srca);
349 return mult_chan (src, dst, Fa, 0.0);
351 case PIXMAN_OP_CONJOINT_IN_REVERSE:
355 Fb = MIN (1.0, srca / dsta);
356 return mult_chan (src, dst, 0.0, Fb);
358 case PIXMAN_OP_CONJOINT_OUT:
362 Fa = MAX (0.0, 1.0 - dsta / srca);
363 return mult_chan (src, dst, Fa, 0.0);
365 case PIXMAN_OP_CONJOINT_OUT_REVERSE:
369 Fb = MAX (0.0, 1.0 - srca / dsta);
370 return mult_chan (src, dst, 0.0, Fb);
372 case PIXMAN_OP_CONJOINT_ATOP:
376 Fa = MIN (1.0, dsta / srca);
380 Fb = MAX (0.0, 1.0 - srca / dsta);
381 return mult_chan (src, dst, Fa, Fb);
383 case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
387 Fa = MAX (0.0, 1.0 - dsta / srca);
391 Fb = MIN (1.0, srca / dsta);
392 return mult_chan (src, dst, Fa, Fb);
394 case PIXMAN_OP_CONJOINT_XOR:
398 Fa = MAX (0.0, 1.0 - dsta / srca);
402 Fb = MAX (0.0, 1.0 - srca / dsta);
403 return mult_chan (src, dst, Fa, Fb);
405 case PIXMAN_OP_MULTIPLY:
406 case PIXMAN_OP_SCREEN:
407 case PIXMAN_OP_OVERLAY:
408 case PIXMAN_OP_DARKEN:
409 case PIXMAN_OP_LIGHTEN:
410 case PIXMAN_OP_COLOR_DODGE:
411 case PIXMAN_OP_COLOR_BURN:
412 case PIXMAN_OP_HARD_LIGHT:
413 case PIXMAN_OP_SOFT_LIGHT:
414 case PIXMAN_OP_DIFFERENCE:
415 case PIXMAN_OP_EXCLUSION:
416 case PIXMAN_OP_HSL_HUE:
417 case PIXMAN_OP_HSL_SATURATION:
418 case PIXMAN_OP_HSL_COLOR:
419 case PIXMAN_OP_HSL_LUMINOSITY:
422 return 0; /* silence MSVC */
428 do_composite (pixman_op_t op,
433 pixman_bool_t component_alpha)
435 color_t srcval, srcalpha;
446 else if (component_alpha)
448 srcval.r = src->r * mask->r;
449 srcval.g = src->g * mask->g;
450 srcval.b = src->b * mask->b;
451 srcval.a = src->a * mask->a;
453 srcalpha.r = src->a * mask->r;
454 srcalpha.g = src->a * mask->g;
455 srcalpha.b = src->a * mask->b;
456 srcalpha.a = src->a * mask->a;
460 srcval.r = src->r * mask->a;
461 srcval.g = src->g * mask->a;
462 srcval.b = src->b * mask->a;
463 srcval.a = src->a * mask->a;
465 srcalpha.r = src->a * mask->a;
466 srcalpha.g = src->a * mask->a;
467 srcalpha.b = src->a * mask->a;
468 srcalpha.a = src->a * mask->a;
471 result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
472 result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
473 result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
474 result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
478 get_value (pixman_image_t *image)
480 uint32_t value = *(uint32_t *)pixman_image_get_data (image);
482 #ifdef WORDS_BIGENDIAN
484 pixman_format_code_t format = pixman_image_get_format (image);
485 value >>= 8 * sizeof(value) - PIXMAN_FORMAT_BPP (format);
493 describe_image (image_t *info, char *buf)
497 sprintf (buf, "%s, %dx%d%s",
499 info->size, info->size,
500 info->repeat ? " R" :"");
504 sprintf (buf, "solid");
511 describe_color (const color_t *color, char *buf)
513 sprintf (buf, "%.3f %.3f %.3f %.3f",
514 color->r, color->g, color->b, color->a);
520 composite_test (image_t *dst,
521 const operator_t *op,
524 pixman_bool_t component_alpha,
528 pixman_rectangle16_t rect;
529 color_t expected, tdst, tsrc, tmsk;
530 pixel_checker_t checker;
533 compute_pixman_color (dst->color, &fill);
535 rect.width = rect.height = dst->size;
536 pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, &fill, 1, &rect);
540 pixman_image_set_component_alpha (mask->image, component_alpha);
542 pixman_image_composite (op->op, src->image, mask->image, dst->image,
543 0, 0, 0, 0, 0, 0, dst->size, dst->size);
547 pixman_image_composite (op->op, src->image, NULL, dst->image,
551 dst->size, dst->size);
555 round_color (dst->format->format, &tdst);
559 round_color (src->format->format, &tsrc);
565 round_color (mask->format->format, &tmsk);
566 if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0)
568 /* Ax component-alpha masks expand alpha into
569 * all color channels.
571 tmsk.r = tmsk.g = tmsk.b = tmsk.a;
575 do_composite (op->op,
582 pixel_checker_init (&checker, dst->format->format);
584 if (!pixel_checker_check (&checker, get_value (dst->image), &expected))
586 char buf[40], buf2[40];
590 printf ("---- Test %d failed ----\n", testno);
591 printf ("Operator: %s %s\n",
592 op->name, component_alpha ? "CA" : "");
594 printf ("Source: %s\n", describe_image (src, buf));
596 printf ("Mask: %s\n", describe_image (mask, buf));
598 printf ("Destination: %s\n\n", describe_image (dst, buf));
599 printf (" R G B A Rounded\n");
600 printf ("Source color: %s %s\n",
601 describe_color (src->color, buf),
602 describe_color (&tsrc, buf2));
605 printf ("Mask color: %s %s\n",
606 describe_color (mask->color, buf),
607 describe_color (&tmsk, buf2));
609 printf ("Dest. color: %s %s\n",
610 describe_color (dst->color, buf),
611 describe_color (&tdst, buf2));
613 pixel = get_value (dst->image);
615 printf ("Expected: %s\n", describe_color (&expected, buf));
617 pixel_checker_split_pixel (&checker, pixel, &a, &r, &g, &b);
619 printf ("Got: %5d %5d %5d %5d [pixel: 0x%08x]\n", r, g, b, a, pixel);
620 pixel_checker_get_min (&checker, &expected, &a, &r, &g, &b);
621 printf ("Min accepted: %5d %5d %5d %5d\n", r, g, b, a);
622 pixel_checker_get_max (&checker, &expected, &a, &r, &g, &b);
623 printf ("Max accepted: %5d %5d %5d %5d\n", r, g, b, a);
631 image_init (image_t *info,
638 info->color = &colors[color];
639 compute_pixman_color (info->color, &fill);
641 info->format = &formats[format];
642 info->size = sizes[size] & ~FLAGS;
643 info->repeat = PIXMAN_REPEAT_NONE;
647 pixman_rectangle16_t rect;
649 info->image = pixman_image_create_bits (info->format->format,
650 info->size, info->size,
654 rect.width = rect.height = info->size;
655 pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill,
658 if (sizes[size] & REPEAT)
660 pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
661 info->repeat = PIXMAN_REPEAT_NORMAL;
666 info->image = pixman_image_create_solid_fill (&fill);
671 image_fini (image_t *info)
673 pixman_image_unref (info->image);
679 return lcg_rand_n (ARRAY_LENGTH (sizes));
685 return lcg_rand_n (ARRAY_LENGTH (colors));
691 return lcg_rand_n (ARRAY_LENGTH (formats));
695 run_test (uint32_t seed)
697 image_t src, mask, dst;
698 const operator_t *op;
704 image_init (&dst, random_color(), random_format(), 1);
705 image_init (&src, random_color(), random_format(), random_size());
706 image_init (&mask, random_color(), random_format(), random_size());
708 op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]);
715 ok = composite_test (&dst, op, &src, NULL, FALSE, seed);
718 ok = composite_test (&dst, op, &src, &mask, FALSE, seed);
721 ok = composite_test (&dst, op, &src, &mask,
722 mask.size? TRUE : FALSE, seed);
737 main (int argc, char **argv)
739 #define N_TESTS (8 * 1024 * 1024)
747 i = strtol (argv[1], &end, 0);
758 printf ("Usage:\n\n %s <number>\n\n", argv[0]);
763 if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
764 seed = get_random_seed();
769 # pragma omp parallel for default(none) shared(result, argv, seed)
771 for (i = 0; i <= N_TESTS; ++i)
773 if (!result && !run_test (i + seed))
775 printf ("Test 0x%08X failed.\n", seed + i);