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.
28 #include <stdlib.h> /* abort() */
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))
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;
51 pixman_format_code_t format;
55 static color_t colors[] =
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 },
67 _color_double_to_short (double d)
71 i = (uint32_t) (d * 65536);
78 compute_pixman_color (const color_t *color,
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);
87 static const format_t formats[] =
89 #define P(x) { PIXMAN_##x, #x }
115 /* XXX: and here the errors begin!
117 * The formats below all have channels with 4 bits or less, and
118 * the eval_diff code doesn't deal correctly with that.
154 pixman_image_t *image;
155 const format_t *format;
156 const color_t *color;
157 pixman_repeat_t repeat;
167 static const operator_t operators[] =
169 #define P(x) { PIXMAN_OP_##x, #x }
189 P(DISJOINT_OVER_REVERSE),
191 P(DISJOINT_IN_REVERSE),
193 P(DISJOINT_OUT_REVERSE),
195 P(DISJOINT_ATOP_REVERSE),
202 P(CONJOINT_OVER_REVERSE),
204 P(CONJOINT_IN_REVERSE),
206 P(CONJOINT_OUT_REVERSE),
208 P(CONJOINT_ATOP_REVERSE),
214 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
216 #define mult_chan(src, dst, Fa, Fb) min ((src) * (Fa) + (dst) * (Fb), 1.0)
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);
228 case PIXMAN_OP_DISJOINT_SRC:
229 case PIXMAN_OP_CONJOINT_SRC:
230 return mult_chan (src, dst, 1.0, 0.0);
233 case PIXMAN_OP_DISJOINT_DST:
234 case PIXMAN_OP_CONJOINT_DST:
235 return mult_chan (src, dst, 0.0, 1.0);
238 return mult_chan (src, dst, 1.0, 1.0 - srca);
240 case PIXMAN_OP_OVER_REVERSE:
241 return mult_chan (src, dst, 1.0 - dsta, 1.0);
244 return mult_chan (src, dst, dsta, 0.0);
246 case PIXMAN_OP_IN_REVERSE:
247 return mult_chan (src, dst, 0.0, srca);
250 return mult_chan (src, dst, 1.0 - dsta, 0.0);
252 case PIXMAN_OP_OUT_REVERSE:
253 return mult_chan (src, dst, 0.0, 1.0 - srca);
256 return mult_chan (src, dst, dsta, 1.0 - srca);
258 case PIXMAN_OP_ATOP_REVERSE:
259 return mult_chan (src, dst, 1.0 - dsta, srca);
262 return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
265 return mult_chan (src, dst, 1.0, 1.0);
267 case PIXMAN_OP_SATURATE:
268 case PIXMAN_OP_DISJOINT_OVER_REVERSE:
272 Fa = min (1.0, (1.0 - dsta) / srca);
273 return mult_chan (src, dst, Fa, 1.0);
275 case PIXMAN_OP_DISJOINT_OVER:
279 Fb = min (1.0, (1.0 - srca) / dsta);
280 return mult_chan (src, dst, 1.0, Fb);
282 case PIXMAN_OP_DISJOINT_IN:
286 Fa = max (0.0, 1.0 - (1.0 - dsta) / srca);
287 return mult_chan (src, dst, Fa, 0.0);
289 case PIXMAN_OP_DISJOINT_IN_REVERSE:
293 Fb = max (0.0, 1.0 - (1.0 - srca) / dsta);
294 return mult_chan (src, dst, 0.0, Fb);
296 case PIXMAN_OP_DISJOINT_OUT:
300 Fa = min (1.0, (1.0 - dsta) / srca);
301 return mult_chan (src, dst, Fa, 0.0);
303 case PIXMAN_OP_DISJOINT_OUT_REVERSE:
307 Fb = min (1.0, (1.0 - srca) / dsta);
308 return mult_chan (src, dst, 0.0, Fb);
310 case PIXMAN_OP_DISJOINT_ATOP:
314 Fa = max (0.0, 1.0 - (1.0 - dsta) / srca);
318 Fb = min (1.0, (1.0 - srca) / dsta);
319 return mult_chan (src, dst, Fa, Fb);
321 case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
325 Fa = min (1.0, (1.0 - dsta) / srca);
329 Fb = max (0.0, 1.0 - (1.0 - srca) / dsta);
330 return mult_chan (src, dst, Fa, Fb);
332 case PIXMAN_OP_DISJOINT_XOR:
336 Fa = min (1.0, (1.0 - dsta) / srca);
340 Fb = min (1.0, (1.0 - srca) / dsta);
341 return mult_chan (src, dst, Fa, Fb);
343 case PIXMAN_OP_CONJOINT_OVER:
347 Fb = max (0.0, 1.0 - srca / dsta);
348 return mult_chan (src, dst, 1.0, Fb);
350 case PIXMAN_OP_CONJOINT_OVER_REVERSE:
354 Fa = max (0.0, 1.0 - dsta / srca);
355 return mult_chan (src, dst, Fa, 1.0);
357 case PIXMAN_OP_CONJOINT_IN:
361 Fa = min (1.0, dsta / srca);
362 return mult_chan (src, dst, Fa, 0.0);
364 case PIXMAN_OP_CONJOINT_IN_REVERSE:
368 Fb = min (1.0, srca / dsta);
369 return mult_chan (src, dst, 0.0, Fb);
371 case PIXMAN_OP_CONJOINT_OUT:
375 Fa = max (0.0, 1.0 - dsta / srca);
376 return mult_chan (src, dst, Fa, 0.0);
378 case PIXMAN_OP_CONJOINT_OUT_REVERSE:
382 Fb = max (0.0, 1.0 - srca / dsta);
383 return mult_chan (src, dst, 0.0, Fb);
385 case PIXMAN_OP_CONJOINT_ATOP:
389 Fa = min (1.0, dsta / srca);
393 Fb = max (0.0, 1.0 - srca / dsta);
394 return mult_chan (src, dst, Fa, Fb);
396 case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
400 Fa = max (0.0, 1.0 - dsta / srca);
404 Fb = min (1.0, srca / dsta);
405 return mult_chan (src, dst, Fa, Fb);
407 case PIXMAN_OP_CONJOINT_XOR:
411 Fa = max (0.0, 1.0 - dsta / srca);
415 Fb = max (0.0, 1.0 - srca / dsta);
416 return mult_chan (src, dst, Fa, Fb);
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:
440 do_composite (pixman_op_t op,
445 pixman_bool_t component_alpha)
447 color_t srcval, srcalpha;
458 else if (component_alpha)
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;
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;
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;
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;
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);
490 color_correct (pixman_format_code_t format,
493 #define MASK(x) ((1 << (x)) - 1)
494 #define round_pix(pix, m) \
495 ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m)))
497 if (PIXMAN_FORMAT_R (format) == 0)
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));
510 if (PIXMAN_FORMAT_A (format) == 0)
513 color->a = round_pix (color->a, PIXMAN_FORMAT_A (format));
520 get_pixel (pixman_image_t *image,
521 pixman_format_code_t format,
524 #define MASK(N) ((1UL << (N))-1)
526 unsigned long rs, gs, bs, as;
530 val = *(unsigned long *) pixman_image_get_data (image);
531 #ifdef WORDS_BIGENDIAN
532 val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format);
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);
541 switch (PIXMAN_FORMAT_TYPE (format))
543 case PIXMAN_TYPE_ARGB:
550 case PIXMAN_TYPE_ABGR:
557 case PIXMAN_TYPE_BGRA:
559 rs = PIXMAN_FORMAT_BPP (format) - (b + g + r);
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:
586 color->a = ((val >> as) & MASK (a)) / (double) MASK (a);
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);
607 eval_diff (color_t *expected, color_t *test)
609 double rscale, gscale, bscale, ascale;
610 double rdiff, gdiff, bdiff, adiff;
612 /* XXX: Need to be provided mask shifts so we can produce useful error
615 rscale = 1.0 * (1 << 5);
616 gscale = 1.0 * (1 << 6);
617 bscale = 1.0 * (1 << 5);
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;
625 return max (max (max (rdiff, gdiff), bdiff), adiff);
629 describe_image (image_t *info, char *buf, int buflen)
633 snprintf (buf, buflen, "%s %dx%d%s",
635 info->size, info->size,
636 info->repeat ? "R" :"");
640 snprintf (buf, buflen, "solid");
646 /* Test a composite of a given operation, source, mask, and destination
648 * Fills the window, and samples from the 0,0 pixel corner.
651 composite_test (image_t *dst,
652 const operator_t *op,
655 pixman_bool_t component_alpha)
658 pixman_rectangle16_t rect;
659 color_t expected, result, tdst, tsrc, tmsk;
661 pixman_bool_t success = TRUE;
663 compute_pixman_color (dst->color, &fill);
665 rect.width = rect.height = dst->size;
666 pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image,
671 pixman_image_set_component_alpha (mask->image, component_alpha);
672 pixman_image_composite (op->op, src->image, mask->image, dst->image,
676 dst->size, dst->size);
681 color_correct (mask->format->format, &tmsk);
683 if (component_alpha &&
684 PIXMAN_FORMAT_R (mask->format->format) == 0)
686 /* Ax component-alpha masks expand alpha into
687 * all color channels.
689 tmsk.r = tmsk.g = tmsk.b = tmsk.a;
695 pixman_image_composite (op->op, src->image, NULL, dst->image,
699 dst->size, dst->size);
701 get_pixel (dst->image, dst->format->format, &result);
704 color_correct (dst->format->format, &tdst);
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);
712 diff = eval_diff (&expected, &result);
717 snprintf (buf, sizeof (buf),
720 component_alpha ? "CA " : "");
722 printf ("%s test error of %.4f --\n"
724 "got: %.2f %.2f %.2f %.2f [%08lx]\n"
725 "expected: %.2f %.2f %.2f %.2f\n",
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);
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)));
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)));
764 #define REPEAT 0x01000000
765 #define FLAGS 0xff000000
768 image_init (image_t *info,
775 info->color = &colors[color];
776 compute_pixman_color (info->color, &fill);
778 info->format = &formats[format];
779 info->size = size & ~FLAGS;
780 info->repeat = PIXMAN_REPEAT_NONE;
784 pixman_rectangle16_t rect;
786 info->image = pixman_image_create_bits (info->format->format,
787 info->size, info->size,
791 rect.width = rect.height = info->size;
792 pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill,
797 pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
798 info->repeat = PIXMAN_REPEAT_NORMAL;
803 info->image = pixman_image_create_solid_fill (&fill);
808 image_fini (image_t *info)
810 pixman_image_unref (info->image);
816 pixman_bool_t ok, group_ok = TRUE, ca;
818 int tests_passed = 0, tests_total = 0;
819 int sizes[] = { 1, 1 | REPEAT, 10 };
822 for (i = 0; i < ARRAY_LENGTH (colors); i++)
824 colors[i].r *= colors[i].a;
825 colors[i].g *= colors[i].a;
826 colors[i].b *= colors[i].a;
829 num_tests = ARRAY_LENGTH (colors) * ARRAY_LENGTH (formats);
831 for (d = 0; d < num_tests; d++)
836 &dst, d / ARRAY_LENGTH (formats), d % ARRAY_LENGTH (formats), 1);
839 for (s = -ARRAY_LENGTH (colors);
840 s < ARRAY_LENGTH (sizes) * num_tests;
847 image_init (&src, -s - 1, 0, 0);
852 s / ARRAY_LENGTH (sizes) / ARRAY_LENGTH (formats),
853 s / ARRAY_LENGTH (sizes) % ARRAY_LENGTH (formats),
854 sizes[s % ARRAY_LENGTH (sizes)]);
857 for (m = -ARRAY_LENGTH (colors);
858 m < ARRAY_LENGTH (sizes) * num_tests;
865 image_init (&mask, -m - 1, 0, 0);
871 m / ARRAY_LENGTH (sizes) / ARRAY_LENGTH (formats),
872 m / ARRAY_LENGTH (sizes) % ARRAY_LENGTH (formats),
873 sizes[m % ARRAY_LENGTH (sizes)]);
876 for (ca = -1; ca <= 1; ca++)
878 for (i = 0; i < ARRAY_LENGTH (operators); i++)
880 const operator_t *op = &operators[i];
885 ok = composite_test (&dst, op, &src, NULL, FALSE);
888 ok = composite_test (&dst, op, &src, &mask, FALSE);
891 ok = composite_test (&dst, op, &src, &mask,
892 mask.size? TRUE : FALSE);
895 ok = FALSE; /* Silence GCC */
898 group_ok = group_ok && ok;
911 return group_ok == FALSE;