pixman: Branch 'master' - 8 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Mon Jan 16 13:03:02 PST 2012


 pixman/pixman-bits-image.c     |   53 +++++-
 pixman/pixman-general.c        |   16 -
 pixman/pixman-implementation.c |  119 +++-----------
 pixman/pixman-private.h        |   33 ----
 test/alphamap.c                |  144 +++++++++++++----
 test/composite.c               |  332 ++++++++++++-----------------------------
 test/utils.c                   |  175 +++++++++++++++++++++
 test/utils.h                   |   35 ++++
 8 files changed, 495 insertions(+), 412 deletions(-)

New commits:
commit 86ce1808829e3fa024acb0ebaa93ef9737ba51af
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Dec 19 19:31:25 2011 -0500

    test: Port composite test over to use new pixel_checker_t object.
    
    Also make some tweaks to the way the errors are printed.

diff --git a/test/composite.c b/test/composite.c
index 201c5b8..48bde9c 100644
--- a/test/composite.c
+++ b/test/composite.c
@@ -474,117 +474,19 @@ do_composite (pixman_op_t op,
     result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
 }
 
-static void
-get_pixel (pixman_image_t *image,
-	   pixman_format_code_t format,
-	   color_t *color)
+static uint32_t
+get_value (pixman_image_t *image)
 {
-#define MASK(N) ((1UL << (N))-1)
-
-    unsigned long rs, gs, bs, as;
-    int a, r, g, b;
-    unsigned long val;
+    uint32_t value = *(uint32_t *)pixman_image_get_data (image);
 
-    val = *(unsigned long *) pixman_image_get_data (image);
 #ifdef WORDS_BIGENDIAN
-    val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format);
-#endif
-
-    /* Number of bits in each channel */
-    a = PIXMAN_FORMAT_A (format);
-    r = PIXMAN_FORMAT_R (format);
-    g = PIXMAN_FORMAT_G (format);
-    b = PIXMAN_FORMAT_B (format);
-
-    switch (PIXMAN_FORMAT_TYPE (format))
-    {
-    case PIXMAN_TYPE_ARGB:
-        bs = 0;
-        gs = b + bs;
-        rs = g + gs;
-        as = r + rs;
-	break;
-
-    case PIXMAN_TYPE_ABGR:
-        rs = 0;
-        gs = r + rs;
-        bs = g + gs;
-        as = b + bs;
-	break;
-
-    case PIXMAN_TYPE_BGRA:
-        as = 0;
-	rs = PIXMAN_FORMAT_BPP (format) - (b + g + r);
-        gs = r + rs;
-        bs = g + gs;
-	break;
-
-    case PIXMAN_TYPE_RGBA:
-	as = 0;
-	bs = PIXMAN_FORMAT_BPP (format) - (b + g + r);
-	gs = b + bs;
-	rs = g + gs;
-	break;
-
-    case PIXMAN_TYPE_A:
-        as = 0;
-        rs = 0;
-        gs = 0;
-        bs = 0;
-	break;
-
-    case PIXMAN_TYPE_OTHER:
-    case PIXMAN_TYPE_COLOR:
-    case PIXMAN_TYPE_GRAY:
-    case PIXMAN_TYPE_YUY2:
-    case PIXMAN_TYPE_YV12:
-    default:
-	abort ();
-        as = 0;
-        rs = 0;
-        gs = 0;
-        bs = 0;
-	break;
-    }
-
-    if (MASK (a) != 0)
-	color->a = ((val >> as) & MASK (a)) / (double) MASK (a);
-    else
-	color->a = 1.0;
-
-    if (MASK (r) != 0)
-    {
-	color->r = ((val >> rs) & MASK (r)) / (double) MASK (r);
-	color->g = ((val >> gs) & MASK (g)) / (double) MASK (g);
-	color->b = ((val >> bs) & MASK (b)) / (double) MASK (b);
-    }
-    else
     {
-	color->r = 0.0;
-	color->g = 0.0;
-	color->b = 0.0;
+	pixman_format_code_t format = pixman_image_get_format (image);
+	value >>= 8 * sizeof(value) - PIXMAN_FORMAT_BPP (format);
     }
+#endif
 
-#undef MASK
-}
-
-static double
-eval_diff (color_t *expected, color_t *test, pixman_format_code_t format)
-{
-    double rscale, gscale, bscale, ascale;
-    double rdiff, gdiff, bdiff, adiff;
-
-    rscale = 1.0 * ((1 << PIXMAN_FORMAT_R (format)) - 1);
-    gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)) - 1);
-    bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)) - 1);
-    ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)) - 1);
-
-    rdiff = fabs (test->r - expected->r) * rscale;
-    bdiff = fabs (test->g - expected->g) * gscale;
-    gdiff = fabs (test->b - expected->b) * bscale;
-    adiff = fabs (test->a - expected->a) * ascale;
-
-    return MAX (MAX (MAX (rdiff, gdiff), bdiff), adiff);
+    return value;
 }
 
 static char *
@@ -592,10 +494,10 @@ describe_image (image_t *info, char *buf)
 {
     if (info->size)
     {
-	sprintf (buf, "%s %dx%d%s",
+	sprintf (buf, "%s, %dx%d%s",
 		 info->format->name,
 		 info->size, info->size,
-		 info->repeat ? "R" :"");
+		 info->repeat ? " R" :"");
     }
     else
     {
@@ -605,52 +507,40 @@ describe_image (image_t *info, char *buf)
     return buf;
 }
 
-/* Test a composite of a given operation, source, mask, and destination
- * picture.
- * Fills the window, and samples from the 0,0 pixel corner.
- */
+static char *
+describe_color (const color_t *color, char *buf)
+{
+    sprintf (buf, "%.3f %.3f %.3f %.3f",
+	     color->r, color->g, color->b, color->a);
+
+    return buf;
+}
+
 static pixman_bool_t
 composite_test (image_t *dst,
 		const operator_t *op,
 		image_t *src,
 		image_t *mask,
-		pixman_bool_t component_alpha)
+		pixman_bool_t component_alpha,
+		int testno)
 {
     pixman_color_t fill;
     pixman_rectangle16_t rect;
-    color_t expected, result, tdst, tsrc, tmsk;
-    double diff;
-    pixman_bool_t success = TRUE;
+    color_t expected, tdst, tsrc, tmsk;
+    pixel_checker_t checker;
 
+    /* Initialize dst */
     compute_pixman_color (dst->color, &fill);
     rect.x = rect.y = 0;
     rect.width = rect.height = dst->size;
-    pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image,
-				  &fill, 1, &rect);
+    pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, &fill, 1, &rect);
 
-    if (mask != NULL)
+    if (mask)
     {
 	pixman_image_set_component_alpha (mask->image, component_alpha);
-	pixman_image_composite (op->op, src->image, mask->image, dst->image,
-				0, 0,
-				0, 0,
-				0, 0,
-				dst->size, dst->size);
 
-	tmsk = *mask->color;
-	if (mask->size)
-	{
-	    round_color (mask->format->format, &tmsk);
-
-	    if (component_alpha &&
-		PIXMAN_FORMAT_R (mask->format->format) == 0)
-	    {
-		/* Ax component-alpha masks expand alpha into
-		 * all color channels.
-		 */
-		tmsk.r = tmsk.g = tmsk.b = tmsk.a;
-	    }
-	}
+	pixman_image_composite (op->op, src->image, mask->image, dst->image,
+				0, 0, 0, 0, 0, 0, dst->size, dst->size);
     }
     else
     {
@@ -660,71 +550,81 @@ composite_test (image_t *dst,
 				0, 0,
 				dst->size, dst->size);
     }
-    get_pixel (dst->image, dst->format->format, &result);
 
     tdst = *dst->color;
     round_color (dst->format->format, &tdst);
+
     tsrc = *src->color;
     if (src->size)
 	round_color (src->format->format, &tsrc);
-    do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst,
-		  &expected, component_alpha);
-    round_color (dst->format->format, &expected);
 
-    diff = eval_diff (&expected, &result, dst->format->format);
-
-    /* FIXME: We should find out what deviation is acceptable. 3.0
-     * is clearly absurd for 2 bit formats for example. On the other
-     * hand currently 1.0 does not work.
-     */
-    if (diff > 3.0)
+    if (mask)
     {
-	char buf[40];
+	tmsk = *mask->color;
+	if (mask->size)
+	    round_color (mask->format->format, &tmsk);
+	if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0)
+	{
+	    /* Ax component-alpha masks expand alpha into
+	     * all color channels.
+	     */
+	    tmsk.r = tmsk.g = tmsk.b = tmsk.a;
+	}
+    }
+
+    do_composite (op->op,
+		  &tsrc,
+		  mask? &tmsk : NULL,
+		  &tdst,
+		  &expected,
+		  component_alpha);
+
+    pixel_checker_init (&checker, dst->format->format);
 
-	sprintf (buf, "%s %scomposite",
-		 op->name,
-		 component_alpha ? "CA " : "");
+    if (!pixel_checker_check (&checker, get_value (dst->image), &expected))
+    {
+	char buf[40], buf2[40];
+	int a, r, g, b;
+	uint32_t pixel;
 
-	printf ("%s test error of %.4f --\n"
-		"           R    G    B    A\n"
-		"got:       %.2f %.2f %.2f %.2f [%08lx]\n"
-		"expected:  %.2f %.2f %.2f %.2f\n",
-		buf, diff,
-		result.r, result.g, result.b, result.a,
-		*(unsigned long *) pixman_image_get_data (dst->image),
-		expected.r, expected.g, expected.b, expected.a);
+	printf ("---- Test %d failed ----\n", testno);
+	printf ("Operator:      %s %s\n",
+		 op->name, component_alpha ? "CA" : "");
 
+	printf ("Source:        %s\n", describe_image (src, buf));
 	if (mask != NULL)
+	    printf ("Mask:          %s\n", describe_image (mask, buf));
+
+	printf ("Destination:   %s\n\n", describe_image (dst, buf));
+	printf ("               R     G     B     A         Rounded\n");
+	printf ("Source color:  %s     %s\n",
+		describe_color (src->color, buf),
+		describe_color (&tsrc, buf2));
+	if (mask)
 	{
-	    printf ("src color: %.2f %.2f %.2f %.2f\n"
-		    "msk color: %.2f %.2f %.2f %.2f\n"
-		    "dst color: %.2f %.2f %.2f %.2f\n",
-		    src->color->r, src->color->g,
-		    src->color->b, src->color->a,
-		    mask->color->r, mask->color->g,
-		    mask->color->b, mask->color->a,
-		    dst->color->r, dst->color->g,
-		    dst->color->b, dst->color->a);
-	    printf ("src: %s, ", describe_image (src, buf));
-	    printf ("mask: %s, ", describe_image (mask, buf));
-	    printf ("dst: %s\n\n", describe_image (dst, buf));
-	}
-	else
-	{
-	    printf ("src color: %.2f %.2f %.2f %.2f\n"
-		    "dst color: %.2f %.2f %.2f %.2f\n",
-		    src->color->r, src->color->g,
-		    src->color->b, src->color->a,
-		    dst->color->r, dst->color->g,
-		    dst->color->b, dst->color->a);
-	    printf ("src: %s, ", describe_image (src, buf));
-	    printf ("dst: %s\n\n", describe_image (dst, buf));
+	    printf ("Mask color:    %s     %s\n",
+		    describe_color (mask->color, buf),
+		    describe_color (&tmsk, buf2));
 	}
+	printf ("Dest. color:   %s     %s\n",
+		describe_color (dst->color, buf),
+		describe_color (&tdst, buf2));
 
-	success = FALSE;
-    }
+	pixel = get_value (dst->image);
 
-    return success;
+	printf ("Expected:      %s\n", describe_color (&expected, buf));
+
+	pixel_checker_split_pixel (&checker, pixel, &a, &r, &g, &b);
+
+	printf ("Got:           %5d %5d %5d %5d  [pixel: 0x%08x]\n", r, g, b, a, pixel);
+	pixel_checker_get_min (&checker, &expected, &a, &r, &g, &b);
+	printf ("Min accepted:  %5d %5d %5d %5d\n", r, g, b, a);
+	pixel_checker_get_max (&checker, &expected, &a, &r, &g, &b);
+	printf ("Max accepted:  %5d %5d %5d %5d\n", r, g, b, a);
+
+	return FALSE;
+    }
+    return TRUE;
 }
 
 static void
@@ -755,7 +655,7 @@ image_init (image_t *info,
 	pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill,
 				      1, &rect);
 
-	if (size & REPEAT)
+	if (sizes[size] & REPEAT)
 	{
 	    pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
 	    info->repeat = PIXMAN_REPEAT_NORMAL;
@@ -800,7 +700,7 @@ run_test (uint32_t seed)
     int ok;
 
     lcg_srand (seed);
-    
+
     image_init (&dst, random_color(), random_format(), 1);
     image_init (&src, random_color(), random_format(), random_size());
     image_init (&mask, random_color(), random_format(), random_size());
@@ -812,14 +712,14 @@ run_test (uint32_t seed)
     switch (ca)
     {
     case 0:
-	ok = composite_test (&dst, op, &src, NULL, FALSE);
+	ok = composite_test (&dst, op, &src, NULL, FALSE, seed);
 	break;
     case 1:
-	ok = composite_test (&dst, op, &src, &mask, FALSE);
+	ok = composite_test (&dst, op, &src, &mask, FALSE, seed);
 	break;
     case 2:
 	ok = composite_test (&dst, op, &src, &mask,
-			     mask.size? TRUE : FALSE);
+			     mask.size? TRUE : FALSE, seed);
 	break;
     default:
 	ok = FALSE;
@@ -843,7 +743,7 @@ main (int argc, char **argv)
     if (argc > 1)
     {
 	char *end;
-	
+
 	i = strtol (argv[1], &end, 0);
 
 	if (end != argv[1])
@@ -864,7 +764,7 @@ main (int argc, char **argv)
 	seed = get_random_seed();
     else
 	seed = 1;
-    
+
 #ifdef USE_OPENMP
 #   pragma omp parallel for default(none) shared(result, argv, seed)
 #endif
@@ -873,10 +773,10 @@ main (int argc, char **argv)
 	if (!result && !run_test (i + seed))
 	{
 	    printf ("Test 0x%08X failed.\n", seed + i);
-	    
+
 	    result = seed + i;
 	}
     }
-    
+
     return result;
 }
commit f57034f678b419c3737b888f643e5bdfcaf727f9
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Dec 19 17:31:06 2011 -0500

    test: Add a new "pixel_checker_t" object.
    
    Add a new pixel_checker_t object to test/utils.[ch]. This object
    should be initialized with a format and can then be used to check
    whether a given "real" pixel in that format is close enough to a
    "perfect" pixel given as a double precision ARGB struct.
    
    The acceptable deviation is calcuated as follows. Each channel of the
    perfect pixel has 0.004 subtracted from it and is then converted to
    the format. The resulting value is the minimum value that will be
    accepted. Similarly, to compute the maximum value, the channel has
    0.004 added to it and is then converted to the given format. Checking
    a pixel is then a matter of splitting it into channels and checking
    that each is within the computed bounds.
    
    The value of 0.004 was chosen because it is the minimum one that will
    make the existing composite test pass (see next commit). A problem
    with this value is that it causes 0xFE to be acceptable when the
    correct value is 1.0, and 0x01 to be acceptable when the correct value
    is 0. It would be better if, when the result is exactly 0 or exactly
    1, an a8r8g8b8 pixel were required to produce exactly 0x00 or 0xff to
    preserve full black and full white. A deviation value of 0.003 would
    produce this, but currently this would cause tests with operators that
    involve divisions to fail.

diff --git a/test/utils.c b/test/utils.c
index 17bca28..379bd71 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -739,3 +739,142 @@ round_color (pixman_format_code_t format, color_t *color)
     else
 	color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
 }
+
+/* Check whether @pixel is a valid quantization of the a, r, g, b
+ * parameters. Some slack is permitted.
+ */
+void
+pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
+{
+    assert (PIXMAN_FORMAT_VIS (format));
+
+    checker->format = format;
+
+    switch (PIXMAN_FORMAT_TYPE (format))
+    {
+    case PIXMAN_TYPE_A:
+	checker->bs = 0;
+	checker->gs = 0;
+	checker->rs = 0;
+	checker->as = 0;
+	break;
+
+    case PIXMAN_TYPE_ARGB:
+	checker->bs = 0;
+	checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
+	checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
+	checker->as = checker->rs + PIXMAN_FORMAT_R (format);
+	break;
+
+    case PIXMAN_TYPE_ABGR:
+	checker->rs = 0;
+	checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
+	checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
+	checker->as = checker->bs + PIXMAN_FORMAT_B (format);
+	break;
+
+    case PIXMAN_TYPE_BGRA:
+	/* With BGRA formats we start counting at the high end of the pixel */
+	checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
+	checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
+	checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
+	checker->as = checker->rs - PIXMAN_FORMAT_R (format);
+	break;
+
+    case PIXMAN_TYPE_RGBA:
+	/* With BGRA formats we start counting at the high end of the pixel */
+	checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
+	checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
+	checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
+	checker->as = checker->bs - PIXMAN_FORMAT_B (format);
+	break;
+
+    default:
+	assert (0);
+	break;
+    }
+
+    checker->am = ((1 << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
+    checker->rm = ((1 << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
+    checker->gm = ((1 << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
+    checker->bm = ((1 << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
+
+    checker->aw = PIXMAN_FORMAT_A (format);
+    checker->rw = PIXMAN_FORMAT_R (format);
+    checker->gw = PIXMAN_FORMAT_G (format);
+    checker->bw = PIXMAN_FORMAT_B (format);
+}
+
+void
+pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
+			   int *a, int *r, int *g, int *b)
+{
+    *a = (pixel & checker->am) >> checker->as;
+    *r = (pixel & checker->rm) >> checker->rs;
+    *g = (pixel & checker->gm) >> checker->gs;
+    *b = (pixel & checker->bm) >> checker->bs;
+}
+
+static int32_t
+convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
+{
+    int32_t r;
+
+    if (!mask)
+	v = def;
+
+    r = (v * ((mask >> shift) + 1));
+    r -= r >> width;
+
+    return r;
+}
+
+static void
+get_limits (const pixel_checker_t *checker, double limit,
+	    color_t *color,
+	    int *ao, int *ro, int *go, int *bo)
+{
+    *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0);
+    *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0);
+    *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0);
+    *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0);
+}
+
+/* The acceptable deviation in units of [0.0, 1.0]
+ */
+#define DEVIATION (0.004)
+
+void
+pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
+		       int *am, int *rm, int *gm, int *bm)
+{
+    get_limits (checker, DEVIATION, color, am, rm, gm, bm);
+}
+
+void
+pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
+		       int *am, int *rm, int *gm, int *bm)
+{
+    get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
+}
+
+pixman_bool_t
+pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
+		     color_t *color)
+{
+    int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
+    int32_t ai, ri, gi, bi;
+    pixman_bool_t result;
+
+    pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
+    pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
+    pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
+
+    result =
+	a_lo <= ai && ai <= a_hi	&&
+	r_lo <= ri && ri <= r_hi	&&
+	g_lo <= gi && gi <= g_hi	&&
+	b_lo <= bi && bi <= b_hi;
+
+    return result;
+}
diff --git a/test/utils.h b/test/utils.h
index 22abbc2..3c0647b 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -159,3 +159,30 @@ typedef struct
 
 void
 round_color (pixman_format_code_t format, color_t *color);
+
+typedef struct
+{
+    pixman_format_code_t format;
+    uint32_t am, rm, gm, bm;
+    uint32_t as, rs, gs, bs;
+    uint32_t aw, rw, gw, bw;
+} pixel_checker_t;
+
+void
+pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format);
+
+void
+pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
+			   int *a, int *r, int *g, int *b);
+
+void
+pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
+		       int *a, int *r, int *g, int *b);
+
+void
+pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
+		       int *a, int *r, int *g, int *b);
+
+pixman_bool_t
+pixel_checker_check (const pixel_checker_t *checker,
+		     uint32_t pixel, color_t *color);
commit 0053a9f8694c837388b78ae26fe81979d0327d28
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Dec 19 19:53:28 2011 -0500

    Rename color_correct() to round_color()
    
    And do the rounding from float to int in the same way cairo does: by
    multiplying with (1 << width), then subtracting one when the input was 1.0.

diff --git a/test/composite.c b/test/composite.c
index edf7257..201c5b8 100644
--- a/test/composite.c
+++ b/test/composite.c
@@ -640,7 +640,7 @@ composite_test (image_t *dst,
 	tmsk = *mask->color;
 	if (mask->size)
 	{
-	    color_correct (mask->format->format, &tmsk);
+	    round_color (mask->format->format, &tmsk);
 
 	    if (component_alpha &&
 		PIXMAN_FORMAT_R (mask->format->format) == 0)
@@ -663,13 +663,13 @@ composite_test (image_t *dst,
     get_pixel (dst->image, dst->format->format, &result);
 
     tdst = *dst->color;
-    color_correct (dst->format->format, &tdst);
+    round_color (dst->format->format, &tdst);
     tsrc = *src->color;
     if (src->size)
-	color_correct (src->format->format, &tsrc);
+	round_color (src->format->format, &tsrc);
     do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst,
 		  &expected, component_alpha);
-    color_correct (dst->format->format, &expected);
+    round_color (dst->format->format, &expected);
 
     diff = eval_diff (&expected, &result, dst->format->format);
 
diff --git a/test/utils.c b/test/utils.c
index 038fd2b..17bca28 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -704,14 +704,23 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
     }
 }
 
-void
-color_correct (pixman_format_code_t format,
-	       color_t *color)
+static double
+round_channel (double p, int m)
 {
-#define MASK(x) ((1 << (x)) - 1)
-#define round_pix(pix, m)						\
-    ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m)))
+    int t;
+    double r;
+
+    t = p * ((1 << m));
+    t -= t >> m;
+
+    r = t / (double)((1 << m) - 1);
+
+    return r;
+}
 
+void
+round_color (pixman_format_code_t format, color_t *color)
+{
     if (PIXMAN_FORMAT_R (format) == 0)
     {
 	color->r = 0.0;
@@ -720,16 +729,13 @@ color_correct (pixman_format_code_t format,
     }
     else
     {
-	color->r = round_pix (color->r, PIXMAN_FORMAT_R (format));
-	color->g = round_pix (color->g, PIXMAN_FORMAT_G (format));
-	color->b = round_pix (color->b, PIXMAN_FORMAT_B (format));
+	color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
+	color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
+	color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
     }
 
     if (PIXMAN_FORMAT_A (format) == 0)
-	color->a = 1.0;
+	color->a = 1;
     else
-	color->a = round_pix (color->a, PIXMAN_FORMAT_A (format));
-
-#undef round_pix
-#undef MASK
+	color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
 }
diff --git a/test/utils.h b/test/utils.h
index fbbd30b..22abbc2 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -158,5 +158,4 @@ typedef struct
 } color_t;
 
 void
-color_correct (pixman_format_code_t format,
-	       color_t *color);
+round_color (pixman_format_code_t format, color_t *color);
commit 55a010bf31d2eaf71126bdf93eca99fc02037535
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Dec 22 18:15:02 2011 -0500

    Move the color_correct() function from composite.c to utils.c

diff --git a/test/composite.c b/test/composite.c
index fe59eae..edf7257 100644
--- a/test/composite.c
+++ b/test/composite.c
@@ -28,16 +28,10 @@
 #include <time.h>
 #include "utils.h"
 
-typedef struct color_t color_t;
 typedef struct format_t format_t;
 typedef struct image_t image_t;
 typedef struct operator_t operator_t;
 
-struct color_t
-{
-    double r, g, b, a;
-};
-
 struct format_t
 {
     pixman_format_code_t format;
@@ -481,36 +475,6 @@ do_composite (pixman_op_t op,
 }
 
 static void
-color_correct (pixman_format_code_t format,
-	       color_t *color)
-{
-#define MASK(x) ((1 << (x)) - 1)
-#define round_pix(pix, m)						\
-    ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m)))
-
-    if (PIXMAN_FORMAT_R (format) == 0)
-    {
-	color->r = 0.0;
-	color->g = 0.0;
-	color->b = 0.0;
-    }
-    else
-    {
-	color->r = round_pix (color->r, PIXMAN_FORMAT_R (format));
-	color->g = round_pix (color->g, PIXMAN_FORMAT_G (format));
-	color->b = round_pix (color->b, PIXMAN_FORMAT_B (format));
-    }
-
-    if (PIXMAN_FORMAT_A (format) == 0)
-	color->a = 1.0;
-    else
-	color->a = round_pix (color->a, PIXMAN_FORMAT_A (format));
-
-#undef round_pix
-#undef MASK
-}
-
-static void
 get_pixel (pixman_image_t *image,
 	   pixman_format_code_t format,
 	   color_t *color)
diff --git a/test/utils.c b/test/utils.c
index 204066f..038fd2b 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -703,3 +703,33 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
 	assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
     }
 }
+
+void
+color_correct (pixman_format_code_t format,
+	       color_t *color)
+{
+#define MASK(x) ((1 << (x)) - 1)
+#define round_pix(pix, m)						\
+    ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m)))
+
+    if (PIXMAN_FORMAT_R (format) == 0)
+    {
+	color->r = 0.0;
+	color->g = 0.0;
+	color->b = 0.0;
+    }
+    else
+    {
+	color->r = round_pix (color->r, PIXMAN_FORMAT_R (format));
+	color->g = round_pix (color->g, PIXMAN_FORMAT_G (format));
+	color->b = round_pix (color->b, PIXMAN_FORMAT_B (format));
+    }
+
+    if (PIXMAN_FORMAT_A (format) == 0)
+	color->a = 1.0;
+    else
+	color->a = round_pix (color->a, PIXMAN_FORMAT_A (format));
+
+#undef round_pix
+#undef MASK
+}
diff --git a/test/utils.h b/test/utils.h
index 3bff78e..fbbd30b 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -151,3 +151,12 @@ aligned_malloc (size_t align, size_t size);
 
 void
 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb);
+
+typedef struct
+{
+    double r, g, b, a;
+} color_t;
+
+void
+color_correct (pixman_format_code_t format,
+	       color_t *color);
commit 065666f33c414582425e4ac0ec9f694e93c2baf1
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Jan 8 10:32:47 2012 -0500

    Get rid of delegates for combiners
    
    Add a new function _pixman_implementation_lookup_combiner() that will
    find a usable combiner given an operator and information about whether
    the combiner should apply component alpha and whether it should be 64
    bit.
    
    In pixman-general.c use this function to look up a combiner up front
    instead of walking the delegate chain for every scanline.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 2ccdfcd..27fa3ab 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -171,20 +171,8 @@ general_composite_rect  (pixman_implementation_t *imp,
 	imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
 	dest_buffer, narrow | op_flags[op].dst);
 
-    if (narrow)
-    {
-	if (component_alpha)
-	    compose = _pixman_implementation_combine_32_ca;
-	else
-	    compose = _pixman_implementation_combine_32;
-    }
-    else
-    {
-	if (component_alpha)
-	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
-	else
-	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
-    }
+    compose = _pixman_implementation_lookup_combiner (
+	imp->toplevel, op, component_alpha, narrow);
 
     if (!compose)
 	return;
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index 2b7b19d..b0a2959 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -27,54 +27,6 @@
 #include <stdlib.h>
 #include "pixman-private.h"
 
-static void
-delegate_combine_32 (pixman_implementation_t * imp,
-                     pixman_op_t               op,
-                     uint32_t *                dest,
-                     const uint32_t *          src,
-                     const uint32_t *          mask,
-                     int                       width)
-{
-    _pixman_implementation_combine_32 (imp->delegate,
-                                       op, dest, src, mask, width);
-}
-
-static void
-delegate_combine_64 (pixman_implementation_t * imp,
-                     pixman_op_t               op,
-                     uint64_t *                dest,
-                     const uint64_t *          src,
-                     const uint64_t *          mask,
-                     int                       width)
-{
-    _pixman_implementation_combine_64 (imp->delegate,
-                                       op, dest, src, mask, width);
-}
-
-static void
-delegate_combine_32_ca (pixman_implementation_t * imp,
-                        pixman_op_t               op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                       width)
-{
-    _pixman_implementation_combine_32_ca (imp->delegate,
-                                          op, dest, src, mask, width);
-}
-
-static void
-delegate_combine_64_ca (pixman_implementation_t * imp,
-                        pixman_op_t               op,
-                        uint64_t *                dest,
-                        const uint64_t *          src,
-                        const uint64_t *          mask,
-                        int                       width)
-{
-    _pixman_implementation_combine_64_ca (imp->delegate,
-                                          op, dest, src, mask, width);
-}
-
 static pixman_bool_t
 delegate_blt (pixman_implementation_t * imp,
               uint32_t *                src_bits,
@@ -150,61 +102,44 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
     imp->src_iter_init = delegate_src_iter_init;
     imp->dest_iter_init = delegate_dest_iter_init;
 
+    imp->fast_paths = fast_paths;
+
     for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
     {
-	imp->combine_32[i] = delegate_combine_32;
-	imp->combine_64[i] = delegate_combine_64;
-	imp->combine_32_ca[i] = delegate_combine_32_ca;
-	imp->combine_64_ca[i] = delegate_combine_64_ca;
+	imp->combine_32[i] = NULL;
+	imp->combine_64[i] = NULL;
+	imp->combine_32_ca[i] = NULL;
+	imp->combine_64_ca[i] = NULL;
     }
 
-    imp->fast_paths = fast_paths;
-
     return imp;
 }
 
-void
-_pixman_implementation_combine_32 (pixman_implementation_t * imp,
-                                   pixman_op_t               op,
-                                   uint32_t *                dest,
-                                   const uint32_t *          src,
-                                   const uint32_t *          mask,
-                                   int                       width)
+pixman_combine_32_func_t
+_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
+					pixman_op_t		 op,
+					pixman_bool_t		 component_alpha,
+					pixman_bool_t		 narrow)
 {
-    (*imp->combine_32[op]) (imp, op, dest, src, mask, width);
-}
+    pixman_combine_32_func_t f;
 
-void
-_pixman_implementation_combine_64 (pixman_implementation_t * imp,
-                                   pixman_op_t               op,
-                                   uint64_t *                dest,
-                                   const uint64_t *          src,
-                                   const uint64_t *          mask,
-                                   int                       width)
-{
-    (*imp->combine_64[op]) (imp, op, dest, src, mask, width);
-}
+    do
+    {
+	pixman_combine_32_func_t (*combiners[]) =
+	{
+	    (pixman_combine_32_func_t *)imp->combine_64,
+	    (pixman_combine_32_func_t *)imp->combine_64_ca,
+	    imp->combine_32,
+	    imp->combine_32_ca,
+	};
 
-void
-_pixman_implementation_combine_32_ca (pixman_implementation_t * imp,
-                                      pixman_op_t               op,
-                                      uint32_t *                dest,
-                                      const uint32_t *          src,
-                                      const uint32_t *          mask,
-                                      int                       width)
-{
-    (*imp->combine_32_ca[op]) (imp, op, dest, src, mask, width);
-}
+	f = combiners[component_alpha | (narrow << 1)][op];
 
-void
-_pixman_implementation_combine_64_ca (pixman_implementation_t * imp,
-                                      pixman_op_t               op,
-                                      uint64_t *                dest,
-                                      const uint64_t *          src,
-                                      const uint64_t *          mask,
-                                      int                       width)
-{
-    (*imp->combine_64_ca[op]) (imp, op, dest, src, mask, width);
+	imp = imp->delegate;
+    }
+    while (!f);
+
+    return f;
 }
 
 pixman_bool_t
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 1443bfb..8560385 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -475,34 +475,11 @@ pixman_implementation_t *
 _pixman_implementation_create (pixman_implementation_t *delegate,
 			       const pixman_fast_path_t *fast_paths);
 
-void
-_pixman_implementation_combine_32 (pixman_implementation_t *imp,
-                                   pixman_op_t              op,
-                                   uint32_t *               dest,
-                                   const uint32_t *         src,
-                                   const uint32_t *         mask,
-                                   int                      width);
-void
-_pixman_implementation_combine_64 (pixman_implementation_t *imp,
-                                   pixman_op_t              op,
-                                   uint64_t *               dest,
-                                   const uint64_t *         src,
-                                   const uint64_t *         mask,
-                                   int                      width);
-void
-_pixman_implementation_combine_32_ca (pixman_implementation_t *imp,
-                                      pixman_op_t              op,
-                                      uint32_t *               dest,
-                                      const uint32_t *         src,
-                                      const uint32_t *         mask,
-                                      int                      width);
-void
-_pixman_implementation_combine_64_ca (pixman_implementation_t *imp,
-                                      pixman_op_t              op,
-                                      uint64_t *               dest,
-                                      const uint64_t *         src,
-                                      const uint64_t *         mask,
-                                      int                      width);
+pixman_combine_32_func_t
+_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
+					pixman_op_t		 op,
+					pixman_bool_t		 component_alpha,
+					pixman_bool_t		 wide);
 
 pixman_bool_t
 _pixman_implementation_blt (pixman_implementation_t *imp,
commit ab584ab500b4e7011a5b82051a90e2eea6744270
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Jan 7 17:11:45 2012 -0500

    test/alphamap.c: Make dst and orig_dst more independent of each other
    
    When making the copy of the destination, do so separately for the
    image and the alpha map. This ensures that the alpha channel of the
    alpha map will be different from the alpha channel of the actual
    image.
    
    Previously, orig_dst would be copied onto dst along with its alpha
    map, which mean that the alpha map of orig_dst would become the new
    alpha channel of *both* dst and dst's alpha map. This meant that test
    didn't actually test that the alpha maps alpha channel was actually
    fetched.

diff --git a/test/alphamap.c b/test/alphamap.c
index 4435ad0..0c5757e 100644
--- a/test/alphamap.c
+++ b/test/alphamap.c
@@ -2,8 +2,8 @@
 #include <stdlib.h>
 #include "utils.h"
 
-#define WIDTH 100
-#define HEIGHT 100
+#define WIDTH 48
+#define HEIGHT 48
 
 static const pixman_format_code_t formats[] =
 {
@@ -70,24 +70,6 @@ make_image (pixman_format_code_t format)
     return image;
 }
 
-static pixman_image_t *
-create_image (pixman_format_code_t format, pixman_format_code_t alpha_format,
-	      int alpha_origin_x, int alpha_origin_y)
-{
-    pixman_image_t *image = make_image (format);
-
-    if (alpha_format != PIXMAN_null)
-    {
-	pixman_image_t *alpha = make_image (alpha_format);
-
-	pixman_image_set_alpha_map (image, alpha,
-				    alpha_origin_x, alpha_origin_y);
-	pixman_image_unref (alpha);
-    }
-
-    return image;
-}
-
 static uint8_t
 get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
 {
@@ -185,7 +167,7 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     pixman_format_code_t df = formats[d];
     pixman_format_code_t saf = alpha_formats[sa];
     pixman_format_code_t daf = alpha_formats[da];
-    pixman_image_t *src, *dst, *orig_dst;
+    pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
     pixman_transform_t t1;
     int j, k;
     int n_alpha_bits, n_red_bits;
@@ -199,9 +181,35 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
 
     n_red_bits = PIXMAN_FORMAT_R (df);
 
-    src = create_image (sf, saf, soff, soff);
-    orig_dst = create_image (df, daf, doff, doff);
-    dst = create_image (df, daf, doff, doff);
+    /* Source */
+    src = make_image (sf);
+    if (saf != PIXMAN_null)
+    {
+	alpha = make_image (saf);
+	pixman_image_set_alpha_map (src, alpha, soff, soff);
+	pixman_image_unref (alpha);
+    }
+
+    /* Destination */
+    orig_dst = make_image (df);
+    dst = make_image (df);
+    pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
+			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+    if (daf != PIXMAN_null)
+    {
+	orig_alpha = make_image (daf);
+	alpha = make_image (daf);
+
+	pixman_image_composite (PIXMAN_OP_SRC, orig_alpha, NULL, alpha,
+				0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+	pixman_image_set_alpha_map (orig_dst, orig_alpha, doff, doff);
+	pixman_image_set_alpha_map (dst, alpha, doff, doff);
+
+	pixman_image_unref (orig_alpha);
+	pixman_image_unref (alpha);
+    }
 
     /* Transformations, repeats and filters on destinations should be ignored,
      * so just set some random ones.
@@ -215,9 +223,6 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
     pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
 
-    pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
-			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
-
     pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
 
commit 4613f2caac595b3fa1298ac49f9c9fdcd907f14a
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Jan 7 16:48:00 2012 -0500

    Fix bugs with alpha maps
    
    The alpha channel from the alpha map must be inserted as the new alpha
    channel when a scanline is fetched from an image. Previously the alpha
    map would overwrite the buffer instead. This wasn't caught be the
    alpha map test because it would only verify that the resulting alpha
    channel was correct, and not pay attention to incorrect color
    channels.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 99c0dfe..2f56de3 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1294,12 +1294,27 @@ dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
     image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
     if (image->common.alpha_map)
     {
-	x -= image->common.alpha_origin_x;
-	y -= image->common.alpha_origin_y;
+	uint32_t *alpha;
+
+	if ((alpha = malloc (width * sizeof (uint32_t))))
+	{
+	    int i;
+
+	    x -= image->common.alpha_origin_x;
+	    y -= image->common.alpha_origin_y;
+
+	    image->common.alpha_map->fetch_scanline_32 (
+		(pixman_image_t *)image->common.alpha_map,
+		x, y, width, alpha, mask);
 
-	image->common.alpha_map->fetch_scanline_32 (
-	    (pixman_image_t *)image->common.alpha_map,
-	    x, y, width, buffer, mask);
+	    for (i = 0; i < width; ++i)
+	    {
+		buffer[i] &= ~0xff000000;
+		buffer[i] |= (alpha[i] & 0xff000000);
+	    }
+
+	    free (alpha);
+	}
     }
 
     return iter->buffer;
@@ -1312,17 +1327,33 @@ dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
     int             x      = iter->x;
     int             y      = iter->y;
     int             width  = iter->width;
-    uint32_t *	    buffer = iter->buffer;
+    uint64_t *	    buffer = (uint64_t *)iter->buffer;
 
     image->fetch_scanline_64 (
-	(pixman_image_t *)image, x, y, width, buffer, mask);
+	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
     if (image->common.alpha_map)
     {
-	x -= image->common.alpha_origin_x;
-	y -= image->common.alpha_origin_y;
+	uint64_t *alpha;
+
+	if ((alpha = malloc (width * sizeof (uint64_t))))
+	{
+	    int i;
+
+	    x -= image->common.alpha_origin_x;
+	    y -= image->common.alpha_origin_y;
 
-	image->common.alpha_map->fetch_scanline_64 (
-	    (pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
+	    image->common.alpha_map->fetch_scanline_64 (
+		(pixman_image_t *)image->common.alpha_map,
+		x, y, width, (uint32_t *)alpha, mask);
+
+	    for (i = 0; i < width; ++i)
+	    {
+		buffer[i] &= ~0xffff000000000000ULL;
+		buffer[i] |= (alpha[i] & 0xffff000000000000ULL);
+	    }
+
+	    free (alpha);
+	}
     }
 
     return iter->buffer;
commit 8bd63634cd2b2d92145b1d52b54b91ebcb9fb1b4
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Jan 7 14:32:08 2012 -0500

    test: In the alphamap test, also test that we get the right red value
    
    There is a bug where the red channel of the alpha map of the
    destination image is used instead of the red channel of the
    destination image itself.

diff --git a/test/alphamap.c b/test/alphamap.c
index 24a350e..4435ad0 100644
--- a/test/alphamap.c
+++ b/test/alphamap.c
@@ -139,6 +139,45 @@ get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
     return r;
 }
 
+static uint16_t
+get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
+{
+    uint8_t *bits;
+    uint16_t r;
+
+    bits = (uint8_t *)image->bits.bits;
+
+    if (image->bits.format == PIXMAN_a8)
+    {
+	r = 0x00;
+    }
+    else if (image->bits.format == PIXMAN_a2r10g10b10)
+    {
+	r = ((uint32_t *)bits)[y * WIDTH + x] >> 14;
+	r &= 0xffc0;
+	r |= (r >> 10);
+    }
+    else if (image->bits.format == PIXMAN_a8r8g8b8)
+    {
+	r = ((uint32_t *)bits)[y * WIDTH + x] >> 16;
+	r &= 0xff;
+	r |= r << 8;
+    }
+    else if (image->bits.format == PIXMAN_a4r4g4b4)
+    {
+	r = ((uint16_t *)bits)[y * WIDTH + x] >> 8;
+	r &= 0xf;
+	r |= r << 4;
+	r |= r << 8;
+    }
+    else
+    {
+	assert (0);
+    }
+
+    return r;
+}
+
 static int
 run_test (int s, int d, int sa, int da, int soff, int doff)
 {
@@ -149,7 +188,7 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     pixman_image_t *src, *dst, *orig_dst;
     pixman_transform_t t1;
     int j, k;
-    int n_alpha_bits;
+    int n_alpha_bits, n_red_bits;
 
     soff = origins[soff];
     doff = origins[doff];
@@ -158,6 +197,7 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     if (daf != PIXMAN_null)
 	n_alpha_bits = PIXMAN_FORMAT_A (daf);
 
+    n_red_bits = PIXMAN_FORMAT_R (df);
 
     src = create_image (sf, saf, soff, soff);
     orig_dst = create_image (df, daf, doff, doff);
@@ -185,21 +225,22 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     {
 	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
 	{
-	    uint8_t sa, da, oda, ref;
+	    uint8_t sa, da, oda, refa;
+	    uint16_t sr, dr, odr, refr;
 
 	    sa = get_alpha (src, k, j, soff, soff);
 	    da = get_alpha (dst, k, j, doff, doff);
 	    oda = get_alpha (orig_dst, k, j, doff, doff);
 
 	    if (sa + oda > 255)
-		ref = 255;
+		refa = 255;
 	    else
-		ref = sa + oda;
+		refa = sa + oda;
 
-	    if (da >> (8 - n_alpha_bits) != ref >> (8 - n_alpha_bits))
+	    if (da >> (8 - n_alpha_bits) != refa >> (8 - n_alpha_bits))
 	    {
 		printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
-			k, j, ref, da, sa, oda);
+			k, j, refa, da, sa, oda);
 
 		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
 			format_name (sf),
@@ -210,6 +251,38 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
 			doff, doff);
 		return 1;
 	    }
+
+	    /* There are cases where we go through the 8 bit compositing
+	     * path even with 10bpc formats. This results in incorrect
+	     * results here, so only do the red check for narrow formats
+	     */
+	    if (n_red_bits <= 8)
+	    {
+		sr = get_red (src, k, j, soff, soff);
+		dr = get_red (dst, k, j, doff, doff);
+		odr = get_red (orig_dst, k, j, doff, doff);
+
+		if (sr + odr > 0xffff)
+		    refr = 0xffff;
+		else
+		    refr = sr + odr;
+
+		if (abs ((dr >> (16 - n_red_bits)) - (refr >> (16 - n_red_bits))) > 1)
+		{
+		    printf ("%d red bits\n", n_red_bits);
+		    printf ("\nWrong red value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
+			    k, j, refr, dr, sr, odr);
+
+		    printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
+			    format_name (sf),
+			    format_name (saf),
+			    soff, soff,
+			    format_name (df),
+			    format_name (daf),
+			    doff, doff);
+		    return 1;
+		}
+	    }
 	}
     }
 


More information about the xorg-commit mailing list