pixman: Branch 'master' - 13 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Sat Jan 4 13:18:44 PST 2014


 pixman/pixman-combine-float.c |  336 +++--
 pixman/pixman-combine32.c     | 1686 ++-----------------------
 pixman/pixman-general.c       |   21 
 test/Makefile.sources         |    1 
 test/blitters-test.c          |   20 
 test/check-formats.c          |   16 
 test/pixel-test.c             | 2780 +++++++++++++++++++++++++++++++++++++++++-
 test/thread-test.c            |   29 
 test/tolerance-test.c         |  360 +++++
 test/utils.c                  |  184 ++
 10 files changed, 3739 insertions(+), 1694 deletions(-)

New commits:
commit 82d094654a46bd97d47f1f132a01ae0a74b986f3
Author: Søren Sandmann <ssp at redhat.com>
Date:   Sun Dec 8 09:08:45 2013 -0500

    Remove all the operators that use division from pixman-combine32.c
    
    These are now handled by floating point combiners.

diff --git a/pixman/pixman-combine32.c b/pixman/pixman-combine32.c
index d4425ac..4c484d3 100644
--- a/pixman/pixman-combine32.c
+++ b/pixman/pixman-combine32.c
@@ -434,36 +434,6 @@ combine_add_u (pixman_implementation_t *imp,
     }
 }
 
-static void
-combine_saturate_u (pixman_implementation_t *imp,
-                    pixman_op_t              op,
-                    uint32_t *               dest,
-                    const uint32_t *         src,
-                    const uint32_t *         mask,
-                    int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = combine_mask (src, mask, i);
-	uint32_t d = *(dest + i);
-	uint16_t sa, da;
-
-	sa = s >> A_SHIFT;
-	da = ~d >> A_SHIFT;
-	if (sa > da)
-	{
-	    sa = DIV_UN8 (da, sa);
-	    UN8x4_MUL_UN8 (s, sa);
-	}
-	;
-	UN8x4_ADD_UN8x4 (d, s);
-	*(dest + i) = d;
-    }
-}
-
-
 /*
  * PDF blend modes:
  *
@@ -760,74 +730,6 @@ blend_lighten (int32_t d, int32_t ad, int32_t s, int32_t as)
 PDF_SEPARABLE_BLEND_MODE (lighten)
 
 /*
- * Color dodge
- *
- *     ad * as * B(d/ad, s/as)
- *   = if d/ad = 0
- *         ad * as * 0
- *     else if (d/ad >= (1 - s/as)
- *         ad * as * 1
- *     else
- *         ad * as * ((d/ad) / (1 - s/as))
- *   = if d = 0
- *         0
- *     elif as * d >= ad * (as - s)
- *         ad * as
- *     else
- *         as * (as * d / (as - s))
- *
- */
-static inline int32_t
-blend_color_dodge (int32_t d, int32_t ad, int32_t s, int32_t as)
-{
-    if (d == 0)
-        return 0;
-    else if (as * d >= ad * (as - s))
-	return as * ad;
-    else if (as - s == 0)
-        return as * ad;
-    else
-        return as * ((d * as) / ((as - s)));
-}
-
-PDF_SEPARABLE_BLEND_MODE (color_dodge)
-
-/*
- * Color burn
- *
- * We modify the first clause "if d = 1" to "if d >= 1" since with
- * premultiplied colors d > 1 can actually happen.
- *
- *     ad * as * B(d/ad, s/as)
- *   = if d/ad >= 1
- *         ad * as * 1
- *     elif (1 - d/ad) >= s/as
- *         ad * as * 0
- *     else
- *         ad * as * (1 - ((1 - d/ad) / (s/as)))
- *   = if d >= ad
- *         ad * as
- *     elif as * ad - as * d >= ad * s
- *         0
- *     else
- *         ad * as  - as * as * (ad - d) / s
- */
-static inline uint32_t
-blend_color_burn (int32_t d, int32_t ad, int32_t s, int32_t as)
-{
-    if (d >= ad)
-	return ad * as;
-    else if (as * ad - as * d >= ad * s)
-	return 0;
-    else if (s == 0)
-	return 0;
-    else
-	return ad * as - (as * as * (ad - d)) / s;
-}
-
-PDF_SEPARABLE_BLEND_MODE (color_burn)
-
-/*
  * Hard light
  *
  *     ad * as * B(d/ad, s/as)
@@ -856,61 +758,6 @@ blend_hard_light (int32_t d, int32_t ad, int32_t s, int32_t as)
 PDF_SEPARABLE_BLEND_MODE (hard_light)
 
 /*
- * Soft light
- *
- *     ad * as * B(d/ad, s/as)
- *   = if (s/as <= 0.5)
- *         ad * as * (d/ad - (1 - 2 * s/as) * d/ad * (1 - d/ad))
- *     else if (d/ad <= 0.25)
- *         ad * as * (d/ad + (2 * s/as - 1) * ((((16 * d/ad - 12) * d/ad + 4) * d/ad) - d/ad))
- *     else
- *         ad * as * (d/ad + (2 * s/as - 1) * sqrt (d/ad))
- *   = if (2 * s <= as)
- *         d * as - d * (ad - d) * (as - 2 * s) / ad;
- *     else if (4 * d <= ad)
- *         (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
- *     else
- *         d * as + (sqrt (d * ad) - d) * (2 * s - as);
- */
-static inline int32_t
-blend_soft_light (int32_t d_org,
-		  int32_t ad_org,
-		  int32_t s_org,
-		  int32_t as_org)
-{
-    double d = d_org * (1.0 / MASK);
-    double ad = ad_org * (1.0 / MASK);
-    double s = s_org * (1.0 / MASK);
-    double as = as_org * (1.0 / MASK);
-    double r;
-
-    if (2 * s <= as)
-    {
-	if (ad == 0)
-	    r = d * as;
-	else
-	    r = d * as - d * (ad - d) * (as - 2 * s) / ad;
-    }
-    else if (ad == 0)
-    {
-	r = d * as;
-    }
-    else if (4 * d <= ad)
-    {
-	r = d * as +
-	    (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
-    }
-    else
-    {
-	r = d * as + (sqrt (d * ad) - d) * (2 * s - as);
-    }
-
-    return r * MASK * MASK + 0.5;
-}
-
-PDF_SEPARABLE_BLEND_MODE (soft_light)
-
-/*
  * Difference
  *
  *     ad * as * B(s/as, d/ad)
@@ -959,900 +806,120 @@ PDF_SEPARABLE_BLEND_MODE (exclusion)
 
 #undef PDF_SEPARABLE_BLEND_MODE
 
-/*
- * PDF nonseperable blend modes are implemented using the following functions
- * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
- * and min value of the red, green and blue components.
- *
- * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
- *
- * clip_color (C):
- *     l = LUM (C)
- *     min = Cmin
- *     max = Cmax
- *     if n < 0.0
- *         C = l + (((C – l) × l) ⁄ (l – min))
- *     if x > 1.0
- *         C = l + (((C – l) × (1 – l) ) ⁄ (max – l))
- *     return C
- *
- * set_lum (C, l):
- *     d = l – LUM (C)
- *     C += d
- *     return clip_color (C)
- *
- * SAT (C) = CH_MAX (C) - CH_MIN (C)
- *
- * set_sat (C, s):
- *     if Cmax > Cmin
- *         Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
- *         Cmax = s
- *     else
- *         Cmid = Cmax = 0.0
- *         Cmin = 0.0
- *     return C
- */
-
-/* For premultiplied colors, we need to know what happens when C is
- * multiplied by a real number. LUM and SAT are linear:
- *
- *     LUM (r × C) = r × LUM (C)	SAT (r * C) = r * SAT (C)
- *
- * If we extend clip_color with an extra argument a and change
- *
- *     if x >= 1.0
- *
- * into
- *
- *     if x >= a
- *
- * then clip_color is also linear:
- *
- *     r * clip_color (C, a) = clip_color (r * C, r * a);
- *
- * for positive r.
- *
- * Similarly, we can extend set_lum with an extra argument that is just passed
- * on to clip_color:
- *
- *       r * set_lum (C, l, a)
- *
- *     = r × clip_color (C + l - LUM (C), a)
- *
- *     = clip_color (r * C + r × l - r * LUM (C), r * a)
- *
- *     = set_lum (r * C, r * l, r * a)
- *
- * Finally, set_sat:
- *
- *       r * set_sat (C, s) = set_sat (x * C, r * s)
- *
- * The above holds for all non-zero x, because the x'es in the fraction for
- * C_mid cancel out. Specifically, it holds for x = r:
- *
- *       r * set_sat (C, s) = set_sat (r * C, r * s)
- *
- */
-
-#define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
-#define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
-#define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
-#define SAT(c) (CH_MAX (c) - CH_MIN (c))
-
-#define PDF_NON_SEPARABLE_BLEND_MODE(name)				\
-    static void								\
-    combine_ ## name ## _u (pixman_implementation_t *imp,		\
-			    pixman_op_t		     op,		\
-                            uint32_t *               dest,		\
-			    const uint32_t *         src,		\
-			    const uint32_t *         mask,		\
-			    int                      width)		\
-    {									\
-	int i;								\
-	for (i = 0; i < width; ++i)					\
-	{								\
-	    uint32_t s = combine_mask (src, mask, i);			\
-	    uint32_t d = *(dest + i);					\
-	    uint8_t sa = ALPHA_8 (s);					\
-	    uint8_t isa = ~sa;						\
-	    uint8_t da = ALPHA_8 (d);					\
-	    uint8_t ida = ~da;						\
-	    uint32_t result;						\
-	    uint32_t sc[3], dc[3], c[3];				\
-            								\
-	    result = d;							\
-	    UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida);	\
-	    dc[0] = RED_8 (d);						\
-	    sc[0] = RED_8 (s);						\
-	    dc[1] = GREEN_8 (d);					\
-	    sc[1] = GREEN_8 (s);					\
-	    dc[2] = BLUE_8 (d);						\
-	    sc[2] = BLUE_8 (s);						\
-	    blend_ ## name (c, dc, da, sc, sa);				\
-            								\
-	    *(dest + i) = result +					\
-		(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) +		\
-		(DIV_ONE_UN8 (c[0]) << R_SHIFT) +			\
-		(DIV_ONE_UN8 (c[1]) << G_SHIFT) +			\
-		(DIV_ONE_UN8 (c[2]));					\
-	}								\
-    }
+/* Component alpha combiners */
 
 static void
-set_lum (uint32_t dest[3], uint32_t src[3], uint32_t sa, uint32_t lum)
+combine_clear_ca (pixman_implementation_t *imp,
+                  pixman_op_t              op,
+                  uint32_t *                dest,
+                  const uint32_t *          src,
+                  const uint32_t *          mask,
+                  int                      width)
 {
-    double a, l, min, max;
-    double tmp[3];
-
-    a = sa * (1.0 / MASK);
+    memset (dest, 0, width * sizeof(uint32_t));
+}
 
-    l = lum * (1.0 / MASK);
-    tmp[0] = src[0] * (1.0 / MASK);
-    tmp[1] = src[1] * (1.0 / MASK);
-    tmp[2] = src[2] * (1.0 / MASK);
+static void
+combine_src_ca (pixman_implementation_t *imp,
+                pixman_op_t              op,
+                uint32_t *                dest,
+                const uint32_t *          src,
+                const uint32_t *          mask,
+                int                      width)
+{
+    int i;
 
-    l = l - LUM (tmp);
-    tmp[0] += l;
-    tmp[1] += l;
-    tmp[2] += l;
+    for (i = 0; i < width; ++i)
+    {
+	uint32_t s = *(src + i);
+	uint32_t m = *(mask + i);
 
-    /* clip_color */
-    l = LUM (tmp);
-    min = CH_MIN (tmp);
-    max = CH_MAX (tmp);
+	combine_mask_value_ca (&s, &m);
 
-    if (min < 0)
-    {
-	if (l - min == 0.0)
-	{
-	    tmp[0] = 0;
-	    tmp[1] = 0;
-	    tmp[2] = 0;
-	}
-	else
-	{
-	    tmp[0] = l + (tmp[0] - l) * l / (l - min);
-	    tmp[1] = l + (tmp[1] - l) * l / (l - min);
-	    tmp[2] = l + (tmp[2] - l) * l / (l - min);
-	}
-    }
-    if (max > a)
-    {
-	if (max - l == 0.0)
-	{
-	    tmp[0] = a;
-	    tmp[1] = a;
-	    tmp[2] = a;
-	}
-	else
-	{
-	    tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
-	    tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
-	    tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
-	}
+	*(dest + i) = s;
     }
-
-    dest[0] = tmp[0] * MASK + 0.5;
-    dest[1] = tmp[1] * MASK + 0.5;
-    dest[2] = tmp[2] * MASK + 0.5;
 }
 
 static void
-set_sat (uint32_t dest[3], uint32_t src[3], uint32_t sat)
+combine_over_ca (pixman_implementation_t *imp,
+                 pixman_op_t              op,
+                 uint32_t *                dest,
+                 const uint32_t *          src,
+                 const uint32_t *          mask,
+                 int                      width)
 {
-    int id[3];
-    uint32_t min, max;
+    int i;
 
-    if (src[0] > src[1])
-    {
-	if (src[0] > src[2])
-	{
-	    id[0] = 0;
-	    if (src[1] > src[2])
-	    {
-		id[1] = 1;
-		id[2] = 2;
-	    }
-	    else
-	    {
-		id[1] = 2;
-		id[2] = 1;
-	    }
-	}
-	else
-	{
-	    id[0] = 2;
-	    id[1] = 0;
-	    id[2] = 1;
-	}
-    }
-    else
+    for (i = 0; i < width; ++i)
     {
-	if (src[0] > src[2])
-	{
-	    id[0] = 1;
-	    id[1] = 0;
-	    id[2] = 2;
-	}
-	else
+	uint32_t s = *(src + i);
+	uint32_t m = *(mask + i);
+	uint32_t a;
+
+	combine_mask_ca (&s, &m);
+
+	a = ~m;
+	if (a)
 	{
-	    id[2] = 0;
-	    if (src[1] > src[2])
-	    {
-		id[0] = 1;
-		id[1] = 2;
-	    }
-	    else
-	    {
-		id[0] = 2;
-		id[1] = 1;
-	    }
+	    uint32_t d = *(dest + i);
+	    UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s);
+	    s = d;
 	}
-    }
 
-    max = dest[id[0]];
-    min = dest[id[2]];
-    if (max > min)
-    {
-	dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
-	dest[id[0]] = sat;
-	dest[id[2]] = 0;
-    }
-    else
-    {
-	dest[0] = dest[1] = dest[2] = 0;
+	*(dest + i) = s;
     }
 }
 
-/* Hue:
- *
- *       as * ad * B(s/as, d/as)
- *     = as * ad * set_lum (set_sat (s/as, SAT (d/ad)), LUM (d/ad), 1)
- *     = set_lum (set_sat (ad * s, as * SAT (d)), as * LUM (d), as * ad)
- *
- */
-static inline void
-blend_hsl_hue (uint32_t r[3],
-               uint32_t d[3],
-               uint32_t ad,
-               uint32_t s[3],
-               uint32_t as)
+static void
+combine_over_reverse_ca (pixman_implementation_t *imp,
+                         pixman_op_t              op,
+                         uint32_t *                dest,
+                         const uint32_t *          src,
+                         const uint32_t *          mask,
+                         int                      width)
 {
-    r[0] = s[0] * ad;
-    r[1] = s[1] * ad;
-    r[2] = s[2] * ad;
-    set_sat (r, r, SAT (d) * as);
-    set_lum (r, r, as * ad, LUM (d) * as);
-}
+    int i;
 
-PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
+    for (i = 0; i < width; ++i)
+    {
+	uint32_t d = *(dest + i);
+	uint32_t a = ~d >> A_SHIFT;
 
-/* 
- * Saturation
- *
- *     as * ad * B(s/as, d/ad)
- *   = as * ad * set_lum (set_sat (d/ad, SAT (s/as)), LUM (d/ad), 1)
- *   = set_lum (as * ad * set_sat (d/ad, SAT (s/as)),
- *                                       as * LUM (d), as * ad)
- *   = set_lum (set_sat (as * d, ad * SAT (s), as * LUM (d), as * ad))
- */
-static inline void
-blend_hsl_saturation (uint32_t r[3],
-                      uint32_t d[3],
-                      uint32_t ad,
-                      uint32_t s[3],
-                      uint32_t as)
-{
-    r[0] = d[0] * as;
-    r[1] = d[1] * as;
-    r[2] = d[2] * as;
-    set_sat (r, r, SAT (s) * ad);
-    set_lum (r, r, as * ad, LUM (d) * as);
-}
+	if (a)
+	{
+	    uint32_t s = *(src + i);
+	    uint32_t m = *(mask + i);
 
-PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
+	    UN8x4_MUL_UN8x4 (s, m);
+	    UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d);
 
-/* 
- * Color
- *
- *     as * ad * B(s/as, d/as)
- *   = as * ad * set_lum (s/as, LUM (d/ad), 1)
- *   = set_lum (s * ad, as * LUM (d), as * ad)
- */
-static inline void
-blend_hsl_color (uint32_t r[3],
-                 uint32_t d[3],
-                 uint32_t ad,
-                 uint32_t s[3],
-                 uint32_t as)
-{
-    r[0] = s[0] * ad;
-    r[1] = s[1] * ad;
-    r[2] = s[2] * ad;
-    set_lum (r, r, as * ad, LUM (d) * as);
+	    *(dest + i) = s;
+	}
+    }
 }
 
-PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
-
-/*
- * Luminosity
- *
- *     as * ad * B(s/as, d/ad)
- *   = as * ad * set_lum (d/ad, LUM (s/as), 1)
- *   = set_lum (as * d, ad * LUM (s), as * ad)
- */
-static inline void
-blend_hsl_luminosity (uint32_t r[3],
-                      uint32_t d[3],
-                      uint32_t ad,
-                      uint32_t s[3],
-                      uint32_t as)
+static void
+combine_in_ca (pixman_implementation_t *imp,
+               pixman_op_t              op,
+               uint32_t *                dest,
+               const uint32_t *          src,
+               const uint32_t *          mask,
+               int                      width)
 {
-    r[0] = d[0] * as;
-    r[1] = d[1] * as;
-    r[2] = d[2] * as;
-    set_lum (r, r, as * ad, LUM (s) * ad);
-}
+    int i;
 
-PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
+    for (i = 0; i < width; ++i)
+    {
+	uint32_t d = *(dest + i);
+	uint16_t a = d >> A_SHIFT;
+	uint32_t s = 0;
 
-#undef SAT
-#undef LUM
-#undef CH_MAX
-#undef CH_MIN
-#undef PDF_NON_SEPARABLE_BLEND_MODE
+	if (a)
+	{
+	    uint32_t m = *(mask + i);
 
-/* All of the disjoint/conjoint composing functions
- *
- * The four entries in the first column indicate what source contributions
- * come from each of the four areas of the picture -- areas covered by neither
- * A nor B, areas covered only by A, areas covered only by B and finally
- * areas covered by both A and B.
- *
- * Disjoint			Conjoint
- * Fa		Fb		Fa		Fb
- * (0,0,0,0)	0		0		0		0
- * (0,A,0,A)	1		0		1		0
- * (0,0,B,B)	0		1		0		1
- * (0,A,B,A)	1		min((1-a)/b,1)	1		max(1-a/b,0)
- * (0,A,B,B)	min((1-b)/a,1)	1		max(1-b/a,0)	1
- * (0,0,0,A)	max(1-(1-b)/a,0) 0		min(1,b/a)	0
- * (0,0,0,B)	0		max(1-(1-a)/b,0) 0		min(a/b,1)
- * (0,A,0,0)	min(1,(1-b)/a)	0		max(1-b/a,0)	0
- * (0,0,B,0)	0		min(1,(1-a)/b)	0		max(1-a/b,0)
- * (0,0,B,A)	max(1-(1-b)/a,0) min(1,(1-a)/b)	 min(1,b/a)	max(1-a/b,0)
- * (0,A,0,B)	min(1,(1-b)/a)	max(1-(1-a)/b,0) max(1-b/a,0)	min(1,a/b)
- * (0,A,B,0)	min(1,(1-b)/a)	min(1,(1-a)/b)	max(1-b/a,0)	max(1-a/b,0)
- *
- * See  http://marc.info/?l=xfree-render&m=99792000027857&w=2  for more
- * information about these operators.
- */
-
-#define COMBINE_A_OUT 1
-#define COMBINE_A_IN  2
-#define COMBINE_B_OUT 4
-#define COMBINE_B_IN  8
-
-#define COMBINE_CLEAR   0
-#define COMBINE_A       (COMBINE_A_OUT | COMBINE_A_IN)
-#define COMBINE_B       (COMBINE_B_OUT | COMBINE_B_IN)
-#define COMBINE_A_OVER  (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)
-#define COMBINE_B_OVER  (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)
-#define COMBINE_A_ATOP  (COMBINE_B_OUT | COMBINE_A_IN)
-#define COMBINE_B_ATOP  (COMBINE_A_OUT | COMBINE_B_IN)
-#define COMBINE_XOR     (COMBINE_A_OUT | COMBINE_B_OUT)
-
-/* portion covered by a but not b */
-static uint8_t
-combine_disjoint_out_part (uint8_t a, uint8_t b)
-{
-    /* min (1, (1-b) / a) */
-
-    b = ~b;                 /* 1 - b */
-    if (b >= a)             /* 1 - b >= a -> (1-b)/a >= 1 */
-	return MASK;        /* 1 */
-    return DIV_UN8 (b, a);     /* (1-b) / a */
-}
-
-/* portion covered by both a and b */
-static uint8_t
-combine_disjoint_in_part (uint8_t a, uint8_t b)
-{
-    /* max (1-(1-b)/a,0) */
-    /*  = - min ((1-b)/a - 1, 0) */
-    /*  = 1 - min (1, (1-b)/a) */
-
-    b = ~b;                 /* 1 - b */
-    if (b >= a)             /* 1 - b >= a -> (1-b)/a >= 1 */
-	return 0;           /* 1 - 1 */
-    return ~DIV_UN8(b, a);    /* 1 - (1-b) / a */
-}
-
-/* portion covered by a but not b */
-static uint8_t
-combine_conjoint_out_part (uint8_t a, uint8_t b)
-{
-    /* max (1-b/a,0) */
-    /* = 1-min(b/a,1) */
-
-    /* min (1, (1-b) / a) */
-
-    if (b >= a)             /* b >= a -> b/a >= 1 */
-	return 0x00;        /* 0 */
-    return ~DIV_UN8(b, a);    /* 1 - b/a */
-}
-
-/* portion covered by both a and b */
-static uint8_t
-combine_conjoint_in_part (uint8_t a, uint8_t b)
-{
-    /* min (1,b/a) */
-
-    if (b >= a)             /* b >= a -> b/a >= 1 */
-	return MASK;        /* 1 */
-    return DIV_UN8 (b, a);     /* b/a */
-}
-
-#define GET_COMP(v, i)   ((uint16_t) (uint8_t) ((v) >> i))
-
-#define ADD(x, y, i, t)							\
-    ((t) = GET_COMP (x, i) + GET_COMP (y, i),				\
-     (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
-
-#define GENERIC(x, y, i, ax, ay, t, u, v)				\
-    ((t) = (MUL_UN8 (GET_COMP (y, i), ay, (u)) +			\
-            MUL_UN8 (GET_COMP (x, i), ax, (v))),			\
-     (uint32_t) ((uint8_t) ((t) |					\
-                           (0 - ((t) >> G_SHIFT)))) << (i))
-
-static void
-combine_disjoint_general_u (uint32_t *      dest,
-                            const uint32_t *src,
-                            const uint32_t *mask,
-                            int            width,
-                            uint8_t        combine)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = combine_mask (src, mask, i);
-	uint32_t d = *(dest + i);
-	uint32_t m, n, o, p;
-	uint16_t Fa, Fb, t, u, v;
-	uint8_t sa = s >> A_SHIFT;
-	uint8_t da = d >> A_SHIFT;
-
-	switch (combine & COMBINE_A)
-	{
-	default:
-	    Fa = 0;
-	    break;
-
-	case COMBINE_A_OUT:
-	    Fa = combine_disjoint_out_part (sa, da);
-	    break;
-
-	case COMBINE_A_IN:
-	    Fa = combine_disjoint_in_part (sa, da);
-	    break;
-
-	case COMBINE_A:
-	    Fa = MASK;
-	    break;
-	}
-
-	switch (combine & COMBINE_B)
-	{
-	default:
-	    Fb = 0;
-	    break;
-
-	case COMBINE_B_OUT:
-	    Fb = combine_disjoint_out_part (da, sa);
-	    break;
-
-	case COMBINE_B_IN:
-	    Fb = combine_disjoint_in_part (da, sa);
-	    break;
-
-	case COMBINE_B:
-	    Fb = MASK;
-	    break;
-	}
-	m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
-	n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
-	o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
-	p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
-	s = m | n | o | p;
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_disjoint_over_u (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = combine_mask (src, mask, i);
-	uint16_t a = s >> A_SHIFT;
-
-	if (s != 0x00)
-	{
-	    uint32_t d = *(dest + i);
-	    a = combine_disjoint_out_part (d >> A_SHIFT, a);
-	    UN8x4_MUL_UN8_ADD_UN8x4 (d, a, s);
-
-	    *(dest + i) = d;
-	}
-    }
-}
-
-static void
-combine_disjoint_in_u (pixman_implementation_t *imp,
-                       pixman_op_t              op,
-                       uint32_t *                dest,
-                       const uint32_t *          src,
-                       const uint32_t *          mask,
-                       int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
-}
-
-static void
-combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
-                               pixman_op_t              op,
-                               uint32_t *                dest,
-                               const uint32_t *          src,
-                               const uint32_t *          mask,
-                               int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
-}
-
-static void
-combine_disjoint_out_u (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
-}
-
-static void
-combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
-                                pixman_op_t              op,
-                                uint32_t *                dest,
-                                const uint32_t *          src,
-                                const uint32_t *          mask,
-                                int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
-}
-
-static void
-combine_disjoint_atop_u (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
-}
-
-static void
-combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
-                                 pixman_op_t              op,
-                                 uint32_t *                dest,
-                                 const uint32_t *          src,
-                                 const uint32_t *          mask,
-                                 int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
-}
-
-static void
-combine_disjoint_xor_u (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
-}
-
-static void
-combine_conjoint_general_u (uint32_t *      dest,
-                            const uint32_t *src,
-                            const uint32_t *mask,
-                            int            width,
-                            uint8_t        combine)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = combine_mask (src, mask, i);
-	uint32_t d = *(dest + i);
-	uint32_t m, n, o, p;
-	uint16_t Fa, Fb, t, u, v;
-	uint8_t sa = s >> A_SHIFT;
-	uint8_t da = d >> A_SHIFT;
-
-	switch (combine & COMBINE_A)
-	{
-	default:
-	    Fa = 0;
-	    break;
-
-	case COMBINE_A_OUT:
-	    Fa = combine_conjoint_out_part (sa, da);
-	    break;
-
-	case COMBINE_A_IN:
-	    Fa = combine_conjoint_in_part (sa, da);
-	    break;
-
-	case COMBINE_A:
-	    Fa = MASK;
-	    break;
-	}
-
-	switch (combine & COMBINE_B)
-	{
-	default:
-	    Fb = 0;
-	    break;
-
-	case COMBINE_B_OUT:
-	    Fb = combine_conjoint_out_part (da, sa);
-	    break;
-
-	case COMBINE_B_IN:
-	    Fb = combine_conjoint_in_part (da, sa);
-	    break;
-
-	case COMBINE_B:
-	    Fb = MASK;
-	    break;
-	}
-
-	m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
-	n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
-	o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
-	p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
-
-	s = m | n | o | p;
-
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_conjoint_over_u (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
-}
-
-static void
-combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
-                                 pixman_op_t              op,
-                                 uint32_t *                dest,
-                                 const uint32_t *          src,
-                                 const uint32_t *          mask,
-                                 int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
-}
-
-static void
-combine_conjoint_in_u (pixman_implementation_t *imp,
-                       pixman_op_t              op,
-                       uint32_t *                dest,
-                       const uint32_t *          src,
-                       const uint32_t *          mask,
-                       int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
-}
-
-static void
-combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
-                               pixman_op_t              op,
-                               uint32_t *                dest,
-                               const uint32_t *          src,
-                               const uint32_t *          mask,
-                               int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
-}
-
-static void
-combine_conjoint_out_u (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
-}
-
-static void
-combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
-                                pixman_op_t              op,
-                                uint32_t *                dest,
-                                const uint32_t *          src,
-                                const uint32_t *          mask,
-                                int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
-}
-
-static void
-combine_conjoint_atop_u (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
-}
-
-static void
-combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
-                                 pixman_op_t              op,
-                                 uint32_t *                dest,
-                                 const uint32_t *          src,
-                                 const uint32_t *          mask,
-                                 int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
-}
-
-static void
-combine_conjoint_xor_u (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
-}
-
-
-/* Component alpha combiners */
-
-static void
-combine_clear_ca (pixman_implementation_t *imp,
-                  pixman_op_t              op,
-                  uint32_t *                dest,
-                  const uint32_t *          src,
-                  const uint32_t *          mask,
-                  int                      width)
-{
-    memset (dest, 0, width * sizeof(uint32_t));
-}
-
-static void
-combine_src_ca (pixman_implementation_t *imp,
-                pixman_op_t              op,
-                uint32_t *                dest,
-                const uint32_t *          src,
-                const uint32_t *          mask,
-                int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = *(src + i);
-	uint32_t m = *(mask + i);
-
-	combine_mask_value_ca (&s, &m);
-
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_over_ca (pixman_implementation_t *imp,
-                 pixman_op_t              op,
-                 uint32_t *                dest,
-                 const uint32_t *          src,
-                 const uint32_t *          mask,
-                 int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s = *(src + i);
-	uint32_t m = *(mask + i);
-	uint32_t a;
-
-	combine_mask_ca (&s, &m);
-
-	a = ~m;
-	if (a)
-	{
-	    uint32_t d = *(dest + i);
-	    UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s);
-	    s = d;
-	}
-
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_over_reverse_ca (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t d = *(dest + i);
-	uint32_t a = ~d >> A_SHIFT;
-
-	if (a)
-	{
-	    uint32_t s = *(src + i);
-	    uint32_t m = *(mask + i);
-
-	    UN8x4_MUL_UN8x4 (s, m);
-	    UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d);
-
-	    *(dest + i) = s;
-	}
-    }
-}
-
-static void
-combine_in_ca (pixman_implementation_t *imp,
-               pixman_op_t              op,
-               uint32_t *                dest,
-               const uint32_t *          src,
-               const uint32_t *          mask,
-               int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t d = *(dest + i);
-	uint16_t a = d >> A_SHIFT;
-	uint32_t s = 0;
-
-	if (a)
-	{
-	    uint32_t m = *(mask + i);
-
-	    s = *(src + i);
-	    combine_mask_value_ca (&s, &m);
+	    s = *(src + i);
+	    combine_mask_value_ca (&s, &m);
 
 	    if (a != MASK)
 		UN8x4_MUL_UN8 (s, a);
@@ -2069,428 +1136,6 @@ combine_add_ca (pixman_implementation_t *imp,
     }
 }
 
-static void
-combine_saturate_ca (pixman_implementation_t *imp,
-                     pixman_op_t              op,
-                     uint32_t *                dest,
-                     const uint32_t *          src,
-                     const uint32_t *          mask,
-                     int                      width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s, d;
-	uint16_t sa, sr, sg, sb, da;
-	uint16_t t, u, v;
-	uint32_t m, n, o, p;
-
-	d = *(dest + i);
-	s = *(src + i);
-	m = *(mask + i);
-
-	combine_mask_ca (&s, &m);
-
-	sa = (m >> A_SHIFT);
-	sr = (m >> R_SHIFT) & MASK;
-	sg = (m >> G_SHIFT) & MASK;
-	sb =  m             & MASK;
-	da = ~d >> A_SHIFT;
-
-	if (sb <= da)
-	    m = ADD (s, d, 0, t);
-	else
-	    m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v);
-
-	if (sg <= da)
-	    n = ADD (s, d, G_SHIFT, t);
-	else
-	    n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v);
-
-	if (sr <= da)
-	    o = ADD (s, d, R_SHIFT, t);
-	else
-	    o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v);
-
-	if (sa <= da)
-	    p = ADD (s, d, A_SHIFT, t);
-	else
-	    p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v);
-
-	*(dest + i) = m | n | o | p;
-    }
-}
-
-static void
-combine_disjoint_general_ca (uint32_t *      dest,
-                             const uint32_t *src,
-                             const uint32_t *mask,
-                             int            width,
-                             uint8_t        combine)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s, d;
-	uint32_t m, n, o, p;
-	uint32_t Fa, Fb;
-	uint16_t t, u, v;
-	uint32_t sa;
-	uint8_t da;
-
-	s = *(src + i);
-	m = *(mask + i);
-	d = *(dest + i);
-	da = d >> A_SHIFT;
-
-	combine_mask_ca (&s, &m);
-
-	sa = m;
-
-	switch (combine & COMBINE_A)
-	{
-	default:
-	    Fa = 0;
-	    break;
-
-	case COMBINE_A_OUT:
-	    m = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> 0), da);
-	    n = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
-	    o = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
-	    p = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
-	    Fa = m | n | o | p;
-	    break;
-
-	case COMBINE_A_IN:
-	    m = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> 0), da);
-	    n = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
-	    o = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
-	    p = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
-	    Fa = m | n | o | p;
-	    break;
-
-	case COMBINE_A:
-	    Fa = ~0;
-	    break;
-	}
-
-	switch (combine & COMBINE_B)
-	{
-	default:
-	    Fb = 0;
-	    break;
-
-	case COMBINE_B_OUT:
-	    m = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> 0));
-	    n = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
-	    o = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
-	    p = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
-	    Fb = m | n | o | p;
-	    break;
-
-	case COMBINE_B_IN:
-	    m = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> 0));
-	    n = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
-	    o = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
-	    p = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
-	    Fb = m | n | o | p;
-	    break;
-
-	case COMBINE_B:
-	    Fb = ~0;
-	    break;
-	}
-	m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
-	n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
-	o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
-	p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
-
-	s = m | n | o | p;
-
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_disjoint_over_ca (pixman_implementation_t *imp,
-                          pixman_op_t              op,
-                          uint32_t *                dest,
-                          const uint32_t *          src,
-                          const uint32_t *          mask,
-                          int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
-}
-
-static void
-combine_disjoint_in_ca (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
-}
-
-static void
-combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
-                                pixman_op_t              op,
-                                uint32_t *                dest,
-                                const uint32_t *          src,
-                                const uint32_t *          mask,
-                                int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
-}
-
-static void
-combine_disjoint_out_ca (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
-}
-
-static void
-combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
-                                 pixman_op_t              op,
-                                 uint32_t *                dest,
-                                 const uint32_t *          src,
-                                 const uint32_t *          mask,
-                                 int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
-}
-
-static void
-combine_disjoint_atop_ca (pixman_implementation_t *imp,
-                          pixman_op_t              op,
-                          uint32_t *                dest,
-                          const uint32_t *          src,
-                          const uint32_t *          mask,
-                          int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
-}
-
-static void
-combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
-                                  pixman_op_t              op,
-                                  uint32_t *                dest,
-                                  const uint32_t *          src,
-                                  const uint32_t *          mask,
-                                  int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
-}
-
-static void
-combine_disjoint_xor_ca (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
-}
-
-static void
-combine_conjoint_general_ca (uint32_t *      dest,
-                             const uint32_t *src,
-                             const uint32_t *mask,
-                             int            width,
-                             uint8_t        combine)
-{
-    int i;
-
-    for (i = 0; i < width; ++i)
-    {
-	uint32_t s, d;
-	uint32_t m, n, o, p;
-	uint32_t Fa, Fb;
-	uint16_t t, u, v;
-	uint32_t sa;
-	uint8_t da;
-
-	s = *(src + i);
-	m = *(mask + i);
-	d = *(dest + i);
-	da = d >> A_SHIFT;
-
-	combine_mask_ca (&s, &m);
-
-	sa = m;
-
-	switch (combine & COMBINE_A)
-	{
-	default:
-	    Fa = 0;
-	    break;
-
-	case COMBINE_A_OUT:
-	    m = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> 0), da);
-	    n = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
-	    o = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
-	    p = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
-	    Fa = m | n | o | p;
-	    break;
-
-	case COMBINE_A_IN:
-	    m = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> 0), da);
-	    n = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
-	    o = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
-	    p = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
-	    Fa = m | n | o | p;
-	    break;
-
-	case COMBINE_A:
-	    Fa = ~0;
-	    break;
-	}
-
-	switch (combine & COMBINE_B)
-	{
-	default:
-	    Fb = 0;
-	    break;
-
-	case COMBINE_B_OUT:
-	    m = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> 0));
-	    n = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
-	    o = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
-	    p = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
-	    Fb = m | n | o | p;
-	    break;
-
-	case COMBINE_B_IN:
-	    m = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> 0));
-	    n = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
-	    o = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
-	    p = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
-	    Fb = m | n | o | p;
-	    break;
-
-	case COMBINE_B:
-	    Fb = ~0;
-	    break;
-	}
-	m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
-	n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
-	o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
-	p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
-
-	s = m | n | o | p;
-
-	*(dest + i) = s;
-    }
-}
-
-static void
-combine_conjoint_over_ca (pixman_implementation_t *imp,
-                          pixman_op_t              op,
-                          uint32_t *                dest,
-                          const uint32_t *          src,
-                          const uint32_t *          mask,
-                          int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
-}
-
-static void
-combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
-                                  pixman_op_t              op,
-                                  uint32_t *                dest,
-                                  const uint32_t *          src,
-                                  const uint32_t *          mask,
-                                  int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
-}
-
-static void
-combine_conjoint_in_ca (pixman_implementation_t *imp,
-                        pixman_op_t              op,
-                        uint32_t *                dest,
-                        const uint32_t *          src,
-                        const uint32_t *          mask,
-                        int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
-}
-
-static void
-combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
-                                pixman_op_t              op,
-                                uint32_t *                dest,
-                                const uint32_t *          src,
-                                const uint32_t *          mask,
-                                int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
-}
-
-static void
-combine_conjoint_out_ca (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
-}
-
-static void
-combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
-                                 pixman_op_t              op,
-                                 uint32_t *                dest,
-                                 const uint32_t *          src,
-                                 const uint32_t *          mask,
-                                 int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
-}
-
-static void
-combine_conjoint_atop_ca (pixman_implementation_t *imp,
-                          pixman_op_t              op,
-                          uint32_t *                dest,
-                          const uint32_t *          src,
-                          const uint32_t *          mask,
-                          int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
-}
-
-static void
-combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
-                                  pixman_op_t              op,
-                                  uint32_t *                dest,
-                                  const uint32_t *          src,
-                                  const uint32_t *          mask,
-                                  int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
-}
-
-static void
-combine_conjoint_xor_ca (pixman_implementation_t *imp,
-                         pixman_op_t              op,
-                         uint32_t *                dest,
-                         const uint32_t *          src,
-                         const uint32_t *          mask,
-                         int                      width)
-{
-    combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
-}
-
 void
 _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
 {
@@ -2508,51 +1153,15 @@ _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
     imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u;
     imp->combine_32[PIXMAN_OP_ADD] = combine_add_u;
-    imp->combine_32[PIXMAN_OP_SATURATE] = combine_saturate_u;
-
-    /* Disjoint, unified */
-    imp->combine_32[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear;
-    imp->combine_32[PIXMAN_OP_DISJOINT_SRC] = combine_src_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_DST] = combine_dst;
-    imp->combine_32[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u;
-    imp->combine_32[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u;
-
-    /* Conjoint, unified */
-    imp->combine_32[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear;
-    imp->combine_32[PIXMAN_OP_CONJOINT_SRC] = combine_src_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_DST] = combine_dst;
-    imp->combine_32[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u;
-    imp->combine_32[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u;
 
     imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
     imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u;
     imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u;
     imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u;
     imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
-    imp->combine_32[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u;
-    imp->combine_32[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u;
     imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
-    imp->combine_32[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u;
     imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
     imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
-    imp->combine_32[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u;
-    imp->combine_32[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u;
-    imp->combine_32[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u;
-    imp->combine_32[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u;
 
     /* Component alpha combiners */
     imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
@@ -2568,51 +1177,13 @@ _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
     imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca;
     imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca;
-    imp->combine_32_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca;
-
-    /* Disjoint CA */
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca;
-
-    /* Conjoint CA */
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca;
-    imp->combine_32_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca;
 
     imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
     imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
     imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
     imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
     imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
-    imp->combine_32_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca;
-    imp->combine_32_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca;
     imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
-    imp->combine_32_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca;
     imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
     imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
-
-    /* It is not clear that these make sense, so make them noops for now */
-    imp->combine_32_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
-    imp->combine_32_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
-    imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
-    imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
 }
commit ccb1df0c5e80736a0afc3482ec5268d729953d65
Author: Søren Sandmann <ssp at redhat.com>
Date:   Sun Dec 8 08:51:31 2013 -0500

    Copy the comments from pixman-combine32.c to pixman-combine-float.c
    
    An upcoming commit will delete many of the operators from
    pixman-combine32.c and rely on the ones in pixman-combine-float.c. The
    comments about how the operators were derived are still useful though,
    so copy them into pixman-combine-float.c before the deletion.

diff --git a/pixman/pixman-combine-float.c b/pixman/pixman-combine-float.c
index ff02105..f5145bc 100644
--- a/pixman/pixman-combine-float.c
+++ b/pixman/pixman-combine-float.c
@@ -319,23 +319,44 @@ MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
  *
  * The following blend modes have been taken from the PDF ISO 32000
  * specification, which at this point in time is available from
- * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
- * The relevant chapters are 11.3.5 and 11.3.6.
+ *
+ *     http://www.adobe.com/devnet/pdf/pdf_reference.html
+ *
+ * The specific documents of interest are the PDF spec itself:
+ *
+ *     http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
+ *
+ * chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat
+ * 9.1 and Reader 9.1:
+ *
+ *     http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf
+ *
+ * that clarifies the specifications for blend modes ColorDodge and
+ * ColorBurn.
+ *
  * The formula for computing the final pixel color given in 11.3.6 is:
- * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
- * with B() being the blend function.
- * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
- *
- * These blend modes should match the SVG filter draft specification, as
- * it has been designed to mirror ISO 32000. Note that at the current point
- * no released draft exists that shows this, as the formulas have not been
- * updated yet after the release of ISO 32000.
- *
- * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
- * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
- * argument. Note that this implementation operates on premultiplied colors,
- * while the PDF specification does not. Therefore the code uses the formula
- * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
+ *
+ *     αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
+ *
+ * with B() is the blend function. When B(Cb, Cs) = Cs, this formula
+ * reduces to the regular OVER operator.
+ *
+ * Cs and Cb are not premultiplied, so in our implementation we instead
+ * use:
+ *
+ *     cr = (1 – αs) × cb  +  (1 – αb) × cs  +  αb × αs × B (cb/αb, cs/αs)
+ *
+ * where cr, cs, and cb are premultiplied colors, and where the
+ *
+ *     αb × αs × B(cb/αb, cs/αs)
+ *
+ * part is first arithmetically simplified under the assumption that αb
+ * and αs are not 0, and then updated to produce a meaningful result when
+ * they are.
+ *
+ * For all the blend mode operators, the alpha channel is given by
+ *
+ *     αr = αs + αb + αb × αs
  */
 
 #define MAKE_SEPARABLE_PDF_COMBINERS(name)				\
@@ -355,18 +376,55 @@ MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
     									\
     MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
 
+/*
+ * Multiply
+ *
+ *      ad * as * B(d / ad, s / as)
+ *    = ad * as * d/ad * s/as
+ *    = d * s
+ *
+ */
 static force_inline float
 blend_multiply (float sa, float s, float da, float d)
 {
     return d * s;
 }
 
+/*
+ * Screen
+ *
+ *      ad * as * B(d/ad, s/as)
+ *    = ad * as * (d/ad + s/as - s/as * d/ad)
+ *    = ad * s + as * d - s * d
+ */
 static force_inline float
 blend_screen (float sa, float s, float da, float d)
 {
     return d * sa + s * da - s * d;
 }
 
+/*
+ * Overlay
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = ad * as * Hardlight (s, d)
+ *   = if (d / ad < 0.5)
+ *         as * ad * Multiply (s/as, 2 * d/ad)
+ *     else
+ *         as * ad * Screen (s/as, 2 * d / ad - 1)
+ *   = if (d < 0.5 * ad)
+ *         as * ad * s/as * 2 * d /ad
+ *     else
+ *         as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1))
+ *   = if (2 * d < ad)
+ *         2 * s * d
+ *     else
+ *         ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1)
+ *   = if (2 * d < ad)
+ *         2 * s * d
+ *     else
+ *         as * ad - 2 * (ad - d) * (as - s)
+ */
 static force_inline float
 blend_overlay (float sa, float s, float da, float d)
 {
@@ -376,6 +434,13 @@ blend_overlay (float sa, float s, float da, float d)
 	return sa * da - 2 * (da - d) * (sa - s);
 }
 
+/*
+ * Darken
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = ad * as * MIN(d/ad, s/as)
+ *   = MIN (as * d, ad * s)
+ */
 static force_inline float
 blend_darken (float sa, float s, float da, float d)
 {
@@ -388,6 +453,13 @@ blend_darken (float sa, float s, float da, float d)
 	return s;
 }
 
+/*
+ * Lighten
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = ad * as * MAX(d/ad, s/as)
+ *   = MAX (as * d, ad * s)
+ */
 static force_inline float
 blend_lighten (float sa, float s, float da, float d)
 {
@@ -400,6 +472,24 @@ blend_lighten (float sa, float s, float da, float d)
 	return d;
 }
 
+/*
+ * Color dodge
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = if d/ad = 0
+ *         ad * as * 0
+ *     else if (d/ad >= (1 - s/as)
+ *         ad * as * 1
+ *     else
+ *         ad * as * ((d/ad) / (1 - s/as))
+ *   = if d = 0
+ *         0
+ *     elif as * d >= ad * (as - s)
+ *         ad * as
+ *     else
+ *         as * (as * d / (as - s))
+ *
+ */
 static force_inline float
 blend_color_dodge (float sa, float s, float da, float d)
 {
@@ -413,6 +503,26 @@ blend_color_dodge (float sa, float s, float da, float d)
 	return sa * sa * d / (sa - s);
 }
 
+/*
+ * Color burn
+ *
+ * We modify the first clause "if d = 1" to "if d >= 1" since with
+ * premultiplied colors d > 1 can actually happen.
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = if d/ad >= 1
+ *         ad * as * 1
+ *     elif (1 - d/ad) >= s/as
+ *         ad * as * 0
+ *     else
+ *         ad * as * (1 - ((1 - d/ad) / (s/as)))
+ *   = if d >= ad
+ *         ad * as
+ *     elif as * ad - as * d >= ad * s
+ *         0
+ *     else
+ *         ad * as  - as * as * (ad - d) / s
+ */
 static force_inline float
 blend_color_burn (float sa, float s, float da, float d)
 {
@@ -426,6 +536,23 @@ blend_color_burn (float sa, float s, float da, float d)
 	return sa * (da - sa * (da - d) / s);
 }
 
+/*
+ * Hard light
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = if (s/as <= 0.5)
+ *         ad * as * Multiply (d/ad, 2 * s/as)
+ *     else
+ *         ad * as * Screen (d/ad, 2 * s/as - 1)
+ *   = if 2 * s <= as
+ *         ad * as * d/ad * 2 * s / as
+ *     else
+ *         ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1))
+ *   = if 2 * s <= as
+ *         2 * s * d
+ *     else
+ *         as * ad - 2 * (ad - d) * (as - s)
+ */
 static force_inline float
 blend_hard_light (float sa, float s, float da, float d)
 {
@@ -435,6 +562,23 @@ blend_hard_light (float sa, float s, float da, float d)
 	return sa * da - 2 * (da - d) * (sa - s);
 }
 
+/*
+ * Soft light
+ *
+ *     ad * as * B(d/ad, s/as)
+ *   = if (s/as <= 0.5)
+ *         ad * as * (d/ad - (1 - 2 * s/as) * d/ad * (1 - d/ad))
+ *     else if (d/ad <= 0.25)
+ *         ad * as * (d/ad + (2 * s/as - 1) * ((((16 * d/ad - 12) * d/ad + 4) * d/ad) - d/ad))
+ *     else
+ *         ad * as * (d/ad + (2 * s/as - 1) * sqrt (d/ad))
+ *   = if (2 * s <= as)
+ *         d * as - d * (ad - d) * (as - 2 * s) / ad;
+ *     else if (4 * d <= ad)
+ *         (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
+ *     else
+ *         d * as + (sqrt (d * ad) - d) * (2 * s - as);
+ */
 static force_inline float
 blend_soft_light (float sa, float s, float da, float d)
 {
@@ -461,6 +605,20 @@ blend_soft_light (float sa, float s, float da, float d)
     }
 }
 
+/*
+ * Difference
+ *
+ *     ad * as * B(s/as, d/ad)
+ *   = ad * as * abs (s/as - d/ad)
+ *   = if (s/as <= d/ad)
+ *         ad * as * (d/ad - s/as)
+ *     else
+ *         ad * as * (s/as - d/ad)
+ *   = if (ad * s <= as * d)
+ *        as * d - ad * s
+ *     else
+ *        ad * s - as * d
+ */
 static force_inline float
 blend_difference (float sa, float s, float da, float d)
 {
@@ -473,6 +631,13 @@ blend_difference (float sa, float s, float da, float d)
 	return sda - dsa;
 }
 
+/*
+ * Exclusion
+ *
+ *     ad * as * B(s/as, d/ad)
+ *   = ad * as * (d/ad + s/as - 2 * d/ad * s/as)
+ *   = as * d + ad * s - 2 * s * d
+ */
 static force_inline float
 blend_exclusion (float sa, float s, float da, float d)
 {
@@ -492,116 +657,79 @@ MAKE_SEPARABLE_PDF_COMBINERS (difference)
 MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
 
 /*
- * PDF nonseperable blend modes.
- *
- * These are implemented using the following functions to operate in Hsl
- * space, with Cmax, Cmid, Cmin referring to the max, mid and min value
- * of the red, green and blue components.
+ * PDF nonseperable blend modes are implemented using the following functions
+ * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
+ * and min value of the red, green and blue components.
  *
  * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
  *
  * clip_color (C):
- *   l = LUM (C)
- *   min = Cmin
- *   max = Cmax
- *   if n < 0.0
- *     C = l + (((C – l) × l) ⁄     (l – min))
- *   if x > 1.0
- *     C = l + (((C – l) × (1 – l)) (max – l))
- *   return C
+ *     l = LUM (C)
+ *     min = Cmin
+ *     max = Cmax
+ *     if n < 0.0
+ *         C = l + (((C – l) × l) ⁄ (l – min))
+ *     if x > 1.0
+ *         C = l + (((C – l) × (1 – l) ) ⁄ (max – l))
+ *     return C
  *
  * set_lum (C, l):
- *   d = l – LUM (C)
- *   C += d
- *   return clip_color (C)
+ *     d = l – LUM (C)
+ *     C += d
+ *     return clip_color (C)
  *
  * SAT (C) = CH_MAX (C) - CH_MIN (C)
  *
  * set_sat (C, s):
- *  if Cmax > Cmin
- *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
- *    Cmax = s
- *  else
- *    Cmid = Cmax = 0.0
- *  Cmin = 0.0
- *  return C
+ *     if Cmax > Cmin
+ *         Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
+ *         Cmax = s
+ *     else
+ *         Cmid = Cmax = 0.0
+ *         Cmin = 0.0
+ *     return C
  */
 
 /* For premultiplied colors, we need to know what happens when C is
  * multiplied by a real number. LUM and SAT are linear:
  *
- *    LUM (r × C) = r × LUM (C)		SAT (r × C) = r × SAT (C)
+ *     LUM (r × C) = r × LUM (C)	SAT (r * C) = r * SAT (C)
  *
  * If we extend clip_color with an extra argument a and change
  *
- *        if x >= 1.0
+ *     if x >= 1.0
  *
  * into
  *
- *        if x >= a
+ *     if x >= a
  *
  * then clip_color is also linear:
  *
- *     r * clip_color (C, a) = clip_color (r_c, ra);
+ *     r * clip_color (C, a) = clip_color (r * C, r * a);
  *
  * for positive r.
  *
  * Similarly, we can extend set_lum with an extra argument that is just passed
  * on to clip_color:
  *
- *     r × set_lum ( C, l, a)
+ *       r * set_lum (C, l, a)
  *
- *   = r × clip_color ( C + l - LUM (C), a)
+ *     = r × clip_color (C + l - LUM (C), a)
  *
- *   = clip_color ( r * C + r × l - LUM (r × C), r * a)
+ *     = clip_color (r * C + r × l - r * LUM (C), r * a)
  *
- *   = set_lum ( r * C, r * l, r * a)
+ *     = set_lum (r * C, r * l, r * a)
  *
  * Finally, set_sat:
  *
- *     r * set_sat (C, s) = set_sat (x * C, r * s)
+ *       r * set_sat (C, s) = set_sat (x * C, r * s)
  *
- * The above holds for all non-zero x because they x'es in the fraction for
+ * The above holds for all non-zero x, because the x'es in the fraction for
  * C_mid cancel out. Specifically, it holds for x = r:
  *
- *     r * set_sat (C, s) = set_sat (r_c, rs)
- *
- *
- *
- *
- * So, for the non-separable PDF blend modes, we have (using s, d for
- * non-premultiplied colors, and S, D for premultiplied:
- *
- *   Color:
- *
- *     a_s * a_d * B(s, d)
- *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
- *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
- *
- *
- *   Luminosity:
- *
- *     a_s * a_d * B(s, d)
- *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
- *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
- *
- *
- *   Saturation:
- *
- *     a_s * a_d * B(s, d)
- *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
- *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
- *                                        a_s * LUM (D), a_s * a_d)
- *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
- *
- *   Hue:
- *
- *     a_s * a_d * B(s, d)
- *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
- *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
+ *       r * set_sat (C, s) = set_sat (r * C, r * s)
  *
  */
-
 typedef struct
 {
     float	r;
@@ -769,9 +897,12 @@ set_sat (rgb_t *src, float sat)
     *min = 0.0f;
 }
 
-/*
- * Hue:
- * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
+/* Hue:
+ *
+ *       as * ad * B(s/as, d/as)
+ *     = as * ad * set_lum (set_sat (s/as, SAT (d/ad)), LUM (d/ad), 1)
+ *     = set_lum (set_sat (ad * s, as * SAT (d)), as * LUM (d), as * ad)
+ *
  */
 static force_inline void
 blend_hsl_hue (rgb_t *res,
@@ -786,9 +917,14 @@ blend_hsl_hue (rgb_t *res,
     set_lum (res, sa * da, get_lum (dest) * sa);
 }
 
-/*
- * Saturation:
- * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
+/* 
+ * Saturation
+ *
+ *     as * ad * B(s/as, d/ad)
+ *   = as * ad * set_lum (set_sat (d/ad, SAT (s/as)), LUM (d/ad), 1)
+ *   = set_lum (as * ad * set_sat (d/ad, SAT (s/as)),
+ *                                       as * LUM (d), as * ad)
+ *   = set_lum (set_sat (as * d, ad * SAT (s), as * LUM (d), as * ad))
  */
 static force_inline void
 blend_hsl_saturation (rgb_t *res,
@@ -803,9 +939,12 @@ blend_hsl_saturation (rgb_t *res,
     set_lum (res, sa * da, get_lum (dest) * sa);
 }
 
-/*
- * Color:
- * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
+/* 
+ * Color
+ *
+ *     as * ad * B(s/as, d/as)
+ *   = as * ad * set_lum (s/as, LUM (d/ad), 1)
+ *   = set_lum (s * ad, as * LUM (d), as * ad)
  */
 static force_inline void
 blend_hsl_color (rgb_t *res,
@@ -820,8 +959,11 @@ blend_hsl_color (rgb_t *res,
 }
 
 /*
- * Luminosity:
- * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
+ * Luminosity
+ *
+ *     as * ad * B(s/as, d/ad)
+ *   = as * ad * set_lum (d/ad, LUM (s/as), 1)
+ *   = set_lum (as * d, ad * LUM (s), as * ad)
  */
 static force_inline void
 blend_hsl_luminosity (rgb_t *res,
commit 94244b0c401f797835567a8bd165beef8f0dd820
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Sep 30 19:22:20 2013 -0400

    utils.c: Set DEVIATION to 0.0128
    
    Consider a HARD_LIGHT operation with the following pixels:
    
    - source:           15      (6 bits)
    - source alpha:     255     (8 bits)
    - mask alpha:       223     (8 bits)
    - dest              255     (8 bits)
    - dest alpha:       0       (8 bits)
    
    Since 2 times the source is less than source alpha, the first branch
    of the hard light blend mode is taken:
    
            (1 - sa) * d + (1 - da) * s + 2 * s * d
    
    Since da is 0 and d is 1, this degenerates to:
    
            (1 - sa) + 3 * s
    
    Taking (src IN mask) into account along with the fact that sa is 1,
    this becomes:
    
            (1 - ma) + 3 * s * ma
    
          = (1 - 223/255.0) + 3 * (15/63.0) * (223/255.0)
    
          = 0.7501400560224089
    
    When computed with the source converted by bit replication to eight
    bits, and additionally with the (src IN mask) part rounded to eight
    bits, we get:
    
            ma = 223/255.0
    
            s * ma = (60 / 255.0) * (223/255.0) which rounds to 52 / 255
    
    and the result is
    
            (1 - ma) + 3 * s * ma
    
          = (1 - 223/255.0) + 3 * 52/255.0
    
          = 0.7372549019607844
    
    so now we have an error of 0.012885.
    
    Without making changes to the way pixman does integer
    rounding/arithmetic, this error must then be considered
    acceptable. Due to conservative computations in the test suite we can
    however get away with 0.0128 as the acceptable deviation.
    
    This fixes the remaining failures in pixel-test.

diff --git a/test/utils.c b/test/utils.c
index d182710..1888417 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1754,7 +1754,7 @@ get_limits (const pixel_checker_t *checker, double limit,
 
 /* The acceptable deviation in units of [0.0, 1.0]
  */
-#define DEVIATION (0.0064)
+#define DEVIATION (0.0128)
 
 void
 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
commit 15aa37adeca79a22b393ff451e6d29f484c3b0ef
Author: Søren Sandmann <ssp at redhat.com>
Date:   Sat Nov 23 19:38:50 2013 -0500

    Use floating point combiners for all operators that involve divisions
    
    Consider a DISJOINT_ATOP operation with the following pixels:
    
    - source:	0xff (8 bits)
    - source alpha:	0x01 (8 bits)
    - mask alpha:	0x7b (8 bits)
    - dest:		0x00 (8 bits)
    - dest alpha:	0xff (8 bits)
    
    When (src IN mask) is computed in 8 bits, the resulting alpha channel
    is 0 due to rounding:
    
         floor ((0x01 * 0x7b) / 255.0 + 0.5) = floor (0.9823) = 0
    
    which means that since Render defines any division by zero as
    infinity, the Fa and Fb for this operator end up as follows:
    
         Fa = max (1 - (1 - 1) / 0, 0) = 0
    
         Fb = min (1, (1 - 0) / 1) = 1
    
    and so since dest is 0x00, the overall result is 0.
    
    However, when computed in full precision, the alpha value no longer
    rounds to 0, and so Fa ends up being
    
         Fa = max (1 - (1 - 1) / 0.0001, 0) = 1
    
    and so the result is now
    
         s * ma * Fa + d * Fb
    
       = (1.0 * (0x7b / 255.0) * 1) + d * 0
    
       = 0x7b / 255.0
    
       = 0.4823
    
    so the error in this case ends up being 0.48235294, which is clearly
    not something that can be considered acceptable.
    
    In order to avoid this problem, we need to do all arithmetic in such a
    way that a multiplication of two tiny numbers can never end up being
    zero unless one of the input numbers is itself zero.
    
    This patch makes all computations that involve divisions take place in
    floating point, which is sufficient to fix the test cases
    
    This brings the number of failures in pixel-test down to 14.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 8bce7c0..7cdea29 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -109,6 +109,20 @@ static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
 
 #define SCANLINE_BUFFER_LENGTH 8192
 
+static pixman_bool_t
+operator_needs_division (pixman_op_t op)
+{
+    static const uint8_t needs_division[] =
+    {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* SATURATE */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* DISJOINT */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* CONJOINT */
+	0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, /* blend ops */
+    };
+
+    return needs_division[op];
+}
+
 static void
 general_composite_rect  (pixman_implementation_t *imp,
                          pixman_composite_info_t *info)
@@ -124,9 +138,10 @@ general_composite_rect  (pixman_implementation_t *imp,
     int Bpp;
     int i;
 
-    if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT)		    &&
-	(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
-	(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
+    if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT)		     &&
+	(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT)  &&
+	(dest_image->common.flags & FAST_PATH_NARROW_FORMAT)		     &&
+	!(operator_needs_division (op)))
     {
 	width_flag = ITER_NARROW;
 	Bpp = 4;
diff --git a/test/blitters-test.c b/test/blitters-test.c
index e2a2e7f..026f4b0 100644
--- a/test/blitters-test.c
+++ b/test/blitters-test.c
@@ -122,6 +122,15 @@ static pixman_op_t op_list[] = {
     PIXMAN_OP_ATOP_REVERSE,
     PIXMAN_OP_XOR,
     PIXMAN_OP_ADD,
+    PIXMAN_OP_MULTIPLY,
+    PIXMAN_OP_SCREEN,
+    PIXMAN_OP_OVERLAY,
+    PIXMAN_OP_DARKEN,
+    PIXMAN_OP_LIGHTEN,
+    PIXMAN_OP_HARD_LIGHT,
+    PIXMAN_OP_DIFFERENCE,
+    PIXMAN_OP_EXCLUSION,
+#if 0 /* these use floating point math and are not always bitexact on different platforms */
     PIXMAN_OP_SATURATE,
     PIXMAN_OP_DISJOINT_CLEAR,
     PIXMAN_OP_DISJOINT_SRC,
@@ -147,17 +156,8 @@ static pixman_op_t op_list[] = {
     PIXMAN_OP_CONJOINT_ATOP,
     PIXMAN_OP_CONJOINT_ATOP_REVERSE,
     PIXMAN_OP_CONJOINT_XOR,
-    PIXMAN_OP_MULTIPLY,
-    PIXMAN_OP_SCREEN,
-    PIXMAN_OP_OVERLAY,
-    PIXMAN_OP_DARKEN,
-    PIXMAN_OP_LIGHTEN,
     PIXMAN_OP_COLOR_DODGE,
     PIXMAN_OP_COLOR_BURN,
-    PIXMAN_OP_HARD_LIGHT,
-    PIXMAN_OP_DIFFERENCE,
-    PIXMAN_OP_EXCLUSION,
-#if 0 /* these use floating point math and are not always bitexact on different platforms */
     PIXMAN_OP_SOFT_LIGHT,
     PIXMAN_OP_HSL_HUE,
     PIXMAN_OP_HSL_SATURATION,
@@ -394,6 +394,6 @@ main (int argc, const char *argv[])
     }
 
     return fuzzer_test_main("blitters", 2000000,
-			    0xB1D1F40E,
+			    0xCC21DDF0,
 			    test_composite, argc, argv);
 }
diff --git a/test/thread-test.c b/test/thread-test.c
index 8fa2098..1c2f040 100644
--- a/test/thread-test.c
+++ b/test/thread-test.c
@@ -38,38 +38,11 @@ static const pixman_op_t operators[] =
     PIXMAN_OP_ATOP_REVERSE,
     PIXMAN_OP_XOR,
     PIXMAN_OP_ADD,
-    PIXMAN_OP_SATURATE,
-    PIXMAN_OP_DISJOINT_CLEAR,
-    PIXMAN_OP_DISJOINT_SRC,
-    PIXMAN_OP_DISJOINT_DST,
-    PIXMAN_OP_DISJOINT_OVER,
-    PIXMAN_OP_DISJOINT_OVER_REVERSE,
-    PIXMAN_OP_DISJOINT_IN,
-    PIXMAN_OP_DISJOINT_IN_REVERSE,
-    PIXMAN_OP_DISJOINT_OUT,
-    PIXMAN_OP_DISJOINT_OUT_REVERSE,
-    PIXMAN_OP_DISJOINT_ATOP,
-    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
-    PIXMAN_OP_DISJOINT_XOR,
-    PIXMAN_OP_CONJOINT_CLEAR,
-    PIXMAN_OP_CONJOINT_SRC,
-    PIXMAN_OP_CONJOINT_DST,
-    PIXMAN_OP_CONJOINT_OVER,
-    PIXMAN_OP_CONJOINT_OVER_REVERSE,
-    PIXMAN_OP_CONJOINT_IN,
-    PIXMAN_OP_CONJOINT_IN_REVERSE,
-    PIXMAN_OP_CONJOINT_OUT,
-    PIXMAN_OP_CONJOINT_OUT_REVERSE,
-    PIXMAN_OP_CONJOINT_ATOP,
-    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
-    PIXMAN_OP_CONJOINT_XOR,
     PIXMAN_OP_MULTIPLY,
     PIXMAN_OP_SCREEN,
     PIXMAN_OP_OVERLAY,
     PIXMAN_OP_DARKEN,
     PIXMAN_OP_LIGHTEN,
-    PIXMAN_OP_COLOR_DODGE,
-    PIXMAN_OP_COLOR_BURN,
     PIXMAN_OP_HARD_LIGHT,
     PIXMAN_OP_DIFFERENCE,
     PIXMAN_OP_EXCLUSION,
@@ -183,7 +156,7 @@ main (void)
 
     crc32 = compute_crc32 (0, crc32s, sizeof crc32s);
 
-#define EXPECTED 0xE8D161DF
+#define EXPECTED 0x82C4D9FB
 
     if (crc32 != EXPECTED)
     {
commit 8f3824316300e257a3698daa13db802e32489236
Author: Søren Sandmann <ssp at redhat.com>
Date:   Mon Nov 18 13:26:33 2013 -0500

    Soft Light: Consistent approach to division by zero
    
    The Soft Light operator has several branches. One them is decided
    based on whether 2 * s is less than or equal to 2 * sa. In floating
    point implementations, when those two values are very close to each
    other, it may not be completely predictable which branch we hit.
    
    This is a problem because in one branch, when destination alpha is
    zero, we get the result
    
          r = d * as
    
    and in the other we get
    
          r = 0
    
    So when d and as are not 0, this causes two different results to be
    returned from essentially identical input values. In other words,
    there is a discontinuity in the current implementation.
    
    This patch randomly changes the second branch such that it now returns
    d * sa instead. There is no deep meaning behind this, because
    essentially this is an attempt to assign meaning to division by zero,
    and all that is requires is that that meaning doesn't depend on minute
    differences in input values.
    
    This makes the number of failed pixels in pixel-test go down to 347.

diff --git a/pixman/pixman-combine-float.c b/pixman/pixman-combine-float.c
index e9aab48..ff02105 100644
--- a/pixman/pixman-combine-float.c
+++ b/pixman/pixman-combine-float.c
@@ -449,7 +449,7 @@ blend_soft_light (float sa, float s, float da, float d)
     {
 	if (FLOAT_IS_ZERO (da))
 	{
-	    return 0.0f;
+	    return d * sa;
 	}
 	else
 	{
diff --git a/pixman/pixman-combine32.c b/pixman/pixman-combine32.c
index 01c2523..d4425ac 100644
--- a/pixman/pixman-combine32.c
+++ b/pixman/pixman-combine32.c
@@ -893,7 +893,7 @@ blend_soft_light (int32_t d_org,
     }
     else if (ad == 0)
     {
-	r = 0;
+	r = d * as;
     }
     else if (4 * d <= ad)
     {
diff --git a/test/utils.c b/test/utils.c
index c57ca64..d182710 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1198,7 +1198,7 @@ blend_soft_light (double sa, double s, double da, double d)
     {
         if (IS_ZERO (da))
         {
-            return 0.0f;
+	    return d * sa;
         }
         else
         {
commit 89662adf77c69c3f71ded9cd8818ac5626b68451
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Oct 18 16:39:38 2013 -0400

    pixman-combine32.c: Fix bugs related to integer promotion
    
    In the component alpha part of the PDF_SEPARABLE_BLEND_MODE macro, the
    expression ~RED_8 (m) is used. Because RED_8(m) gets promoted to int
    before ~ is applied, the whole expression typically becomes some
    negative value rather than (255 - RED_8(m)) as desired.
    
    Fix this by using unsigned temporary variables.
    
    This reduces the number of failures in pixel-test to 363.

diff --git a/pixman/pixman-combine32.c b/pixman/pixman-combine32.c
index 977c057..01c2523 100644
--- a/pixman/pixman-combine32.c
+++ b/pixman/pixman-combine32.c
@@ -640,13 +640,18 @@ combine_multiply_ca (pixman_implementation_t *imp,
 	    uint8_t da = ALPHA_8 (d);					\
 	    uint8_t ida = ~da;						\
 	    int32_t ra, rr, rg, rb;					\
+	    uint8_t ira, iga, iba;					\
 	    								\
 	    combine_mask_ca (&s, &m);					\
 	    								\
+	    ira = ~RED_8 (m);						\
+	    iga = ~GREEN_8 (m);						\
+	    iba = ~BLUE_8 (m);						\
+									\
 	    ra = da * 0xff + ALPHA_8 (s) * 0xff - ALPHA_8 (s) * da;	\
-	    rr = (~RED_8 (m)) * RED_8 (d) + ida * RED_8 (s);		\
-	    rg = (~GREEN_8 (m)) * GREEN_8 (d) + ida * GREEN_8 (s);	\
-	    rb = (~BLUE_8 (m)) * BLUE_8 (d) + ida * BLUE_8 (s);		\
+	    rr = ira * RED_8 (d) + ida * RED_8 (s);			\
+	    rg = iga * GREEN_8 (d) + ida * GREEN_8 (s);			\
+	    rb = iba * BLUE_8 (d) + ida * BLUE_8 (s);			\
 									\
 	    rr += blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m));	\
 	    rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)); \
diff --git a/test/blitters-test.c b/test/blitters-test.c
index ac8901f..e2a2e7f 100644
--- a/test/blitters-test.c
+++ b/test/blitters-test.c
@@ -394,6 +394,6 @@ main (int argc, const char *argv[])
     }
 
     return fuzzer_test_main("blitters", 2000000,
-			    0x613BBD64,
+			    0xB1D1F40E,
 			    test_composite, argc, argv);
 }
commit e7a99b3b0f605d3f9937bc79e4385c6b71df7845
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jan 18 22:25:36 2013 -0500

    pixman/pixman-combine32.c: Bug fixes for separable blend modes
    
    This commit fixes four separate bugs:
    
    1. In the computation
    
          (1 - sa) * d + (1 - da) * s + sa * da * B(s, d)
    
       we were using regular addition for all four channels, but for
       superluminescent pixels, the addition could overflow causing
       nonsensical results.
    
    2. The variables and return types used for the results of the blend
       mode calculations were unsigned, but for various blend modes (and
       especially with superluminescent pixels), the blend mode
       calculations could be negative, resulting in underflows.
    
    3. The blend mode computations were returned as 8-bit values, which is
       not sufficient precision (especially considering that we need
       signed results).
    
    4. The value before the final division by 255 was not properly clamped
       to [0, 255].
    
    This patch fixes all those bugs. The blend mode computations are now
    returned as signed 16 bit values with 1 represented as 255 * 255.
    
    With these fixes, the number of failing pixels in pixel-test goes down
    from 431 to 384.

diff --git a/pixman/pixman-combine32.c b/pixman/pixman-combine32.c
index 44ca7e8..977c057 100644
--- a/pixman/pixman-combine32.c
+++ b/pixman/pixman-combine32.c
@@ -571,6 +571,15 @@ combine_multiply_ca (pixman_implementation_t *imp,
     }
 }
 
+#define CLAMP(v, low, high)						\
+    do									\
+    {									\
+	if (v < (low))							\
+	    v = (low);							\
+	if (v > (high))							\
+	    v = (high);							\
+    } while (0)
+
 #define PDF_SEPARABLE_BLEND_MODE(name)					\
     static void								\
     combine_ ## name ## _u (pixman_implementation_t *imp,		\
@@ -589,16 +598,28 @@ combine_multiply_ca (pixman_implementation_t *imp,
 	    uint8_t isa = ~sa;						\
 	    uint8_t da = ALPHA_8 (d);					\
 	    uint8_t ida = ~da;						\
-	    uint32_t result;						\
-									\
-	    result = d;							\
-	    UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida);	\
+	    int32_t ra, rr, rg, rb;					\
 	    								\
-	    *(dest + i) = result +					\
-		(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) +		\
-		(blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \
-		(blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \
-		(blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa));	\
+	    ra = da * 0xff + sa * 0xff - sa * da;			\
+	    rr = isa * RED_8 (d) + ida * RED_8 (s);			\
+	    rg = isa * GREEN_8 (d) + ida * GREEN_8 (s);			\
+	    rb = isa * BLUE_8 (d) + ida * BLUE_8 (s);			\
+									\
+	    rr += blend_ ## name (RED_8 (d), da, RED_8 (s), sa);	\
+	    rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa);    \
+	    rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa);	\
+                                                                        \
+	    CLAMP (ra, 0, 255 * 255);				        \
+	    CLAMP (rr, 0, 255 * 255);				        \
+	    CLAMP (rg, 0, 255 * 255);				        \
+	    CLAMP (rb, 0, 255 * 255);				        \
+									\
+	    ra = DIV_ONE_UN8 (ra);					\
+	    rr = DIV_ONE_UN8 (rr);					\
+	    rg = DIV_ONE_UN8 (rg);					\
+	    rb = DIV_ONE_UN8 (rb);					\
+									\
+	    *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb;		\
 	}								\
     }									\
     									\
@@ -618,20 +639,30 @@ combine_multiply_ca (pixman_implementation_t *imp,
 	    uint32_t d = *(dest + i);					\
 	    uint8_t da = ALPHA_8 (d);					\
 	    uint8_t ida = ~da;						\
-	    uint32_t result;						\
-            								\
+	    int32_t ra, rr, rg, rb;					\
+	    								\
 	    combine_mask_ca (&s, &m);					\
-            								\
-	    result = d;							\
-	    UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida);     \
-            								\
-	    result +=							\
-	        (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) +	\
-	        (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \
-	        (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \
-	        (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \
 	    								\
-	    *(dest + i) = result;					\
+	    ra = da * 0xff + ALPHA_8 (s) * 0xff - ALPHA_8 (s) * da;	\
+	    rr = (~RED_8 (m)) * RED_8 (d) + ida * RED_8 (s);		\
+	    rg = (~GREEN_8 (m)) * GREEN_8 (d) + ida * GREEN_8 (s);	\
+	    rb = (~BLUE_8 (m)) * BLUE_8 (d) + ida * BLUE_8 (s);		\
+									\
+	    rr += blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m));	\
+	    rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)); \
+	    rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m)); \
+									\
+	    CLAMP (ra, 0, 255 * 255);				        \
+	    CLAMP (rr, 0, 255 * 255);				        \
+	    CLAMP (rg, 0, 255 * 255);				        \
+	    CLAMP (rb, 0, 255 * 255);				        \
+									\
+	    ra = DIV_ONE_UN8 (ra);					\
+	    rr = DIV_ONE_UN8 (rr);					\
+	    rg = DIV_ONE_UN8 (rg);					\
+	    rb = DIV_ONE_UN8 (rb);					\
+									\
+	    *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb;		\
 	}								\
     }
 
@@ -642,10 +673,10 @@ combine_multiply_ca (pixman_implementation_t *imp,
  *    = ad * as * (d/ad + s/as - s/as * d/ad)
  *    = ad * s + as * d - s * d
  */
-static inline uint32_t
-blend_screen (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_screen (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
-    return DIV_ONE_UN8 (s * ad + d * as - s * d);
+    return s * ad + d * as - s * d;
 }
 
 PDF_SEPARABLE_BLEND_MODE (screen)
@@ -672,8 +703,8 @@ PDF_SEPARABLE_BLEND_MODE (screen)
  *     else
  *         as * ad - 2 * (ad - d) * (as - s)
  */
-static inline uint32_t
-blend_overlay (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_overlay (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     uint32_t r;
 
@@ -682,7 +713,7 @@ blend_overlay (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
     else
 	r = as * ad - 2 * (ad - d) * (as - s);
 
-    return DIV_ONE_UN8 (r);
+    return r;
 }
 
 PDF_SEPARABLE_BLEND_MODE (overlay)
@@ -694,13 +725,13 @@ PDF_SEPARABLE_BLEND_MODE (overlay)
  *   = ad * as * MIN(d/ad, s/as)
  *   = MIN (as * d, ad * s)
  */
-static inline uint32_t
-blend_darken (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_darken (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     s = ad * s;
     d = as * d;
 
-    return DIV_ONE_UN8 (s > d ? d : s);
+    return s > d ? d : s;
 }
 
 PDF_SEPARABLE_BLEND_MODE (darken)
@@ -712,13 +743,13 @@ PDF_SEPARABLE_BLEND_MODE (darken)
  *   = ad * as * MAX(d/ad, s/as)
  *   = MAX (as * d, ad * s)
  */
-static inline uint32_t
-blend_lighten (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_lighten (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     s = ad * s;
     d = as * d;
     
-    return DIV_ONE_UN8 (s > d ? s : d);
+    return s > d ? s : d;
 }
 
 PDF_SEPARABLE_BLEND_MODE (lighten)
@@ -741,17 +772,17 @@ PDF_SEPARABLE_BLEND_MODE (lighten)
  *         as * (as * d / (as - s))
  *
  */
-static inline uint32_t
-blend_color_dodge (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_color_dodge (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     if (d == 0)
         return 0;
     else if (as * d >= ad * (as - s))
-	return DIV_ONE_UN8 (as * ad);
+	return as * ad;
     else if (as - s == 0)
-        return DIV_ONE_UN8 (as * ad);
+        return as * ad;
     else
-        return DIV_ONE_UN8 (as * ((d * as) / ((as - s))));
+        return as * ((d * as) / ((as - s)));
 }
 
 PDF_SEPARABLE_BLEND_MODE (color_dodge)
@@ -777,16 +808,16 @@ PDF_SEPARABLE_BLEND_MODE (color_dodge)
  *         ad * as  - as * as * (ad - d) / s
  */
 static inline uint32_t
-blend_color_burn (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+blend_color_burn (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     if (d >= ad)
-	return DIV_ONE_UN8 (ad * as);
+	return ad * as;
     else if (as * ad - as * d >= ad * s)
 	return 0;
     else if (s == 0)
 	return 0;
     else
-	return DIV_ONE_UN8 (ad * as - (as * as * (ad - d)) / s);
+	return ad * as - (as * as * (ad - d)) / s;
 }
 
 PDF_SEPARABLE_BLEND_MODE (color_burn)
@@ -808,13 +839,13 @@ PDF_SEPARABLE_BLEND_MODE (color_burn)
  *     else
  *         as * ad - 2 * (ad - d) * (as - s)
  */
-static inline uint32_t
-blend_hard_light (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_hard_light (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
     if (2 * s < as)
-	return DIV_ONE_UN8 (2 * s * d);
+	return 2 * s * d;
     else
-	return DIV_ONE_UN8 (as * ad - 2 * (ad - d) * (as - s));
+	return as * ad - 2 * (ad - d) * (as - s);
 }
 
 PDF_SEPARABLE_BLEND_MODE (hard_light)
@@ -836,11 +867,11 @@ PDF_SEPARABLE_BLEND_MODE (hard_light)
  *     else
  *         d * as + (sqrt (d * ad) - d) * (2 * s - as);
  */
-static inline uint32_t
-blend_soft_light (uint32_t d_org,
-		  uint32_t ad_org,
-		  uint32_t s_org,
-		  uint32_t as_org)
+static inline int32_t
+blend_soft_light (int32_t d_org,
+		  int32_t ad_org,
+		  int32_t s_org,
+		  int32_t as_org)
 {
     double d = d_org * (1.0 / MASK);
     double ad = ad_org * (1.0 / MASK);
@@ -868,7 +899,8 @@ blend_soft_light (uint32_t d_org,
     {
 	r = d * as + (sqrt (d * ad) - d) * (2 * s - as);
     }
-    return r * MASK + 0.5;
+
+    return r * MASK * MASK + 0.5;
 }
 
 PDF_SEPARABLE_BLEND_MODE (soft_light)
@@ -887,16 +919,16 @@ PDF_SEPARABLE_BLEND_MODE (soft_light)
  *     else
  *        ad * s - as * d
  */
-static inline uint32_t
-blend_difference (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_difference (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
-    uint32_t das = d * as;
-    uint32_t sad = s * ad;
+    int32_t das = d * as;
+    int32_t sad = s * ad;
 
     if (sad < das)
-	return DIV_ONE_UN8 (das - sad);
+	return das - sad;
     else
-	return DIV_ONE_UN8 (sad - das);
+	return sad - das;
 }
 
 PDF_SEPARABLE_BLEND_MODE (difference)
@@ -912,10 +944,10 @@ PDF_SEPARABLE_BLEND_MODE (difference)
 /* This can be made faster by writing it directly and not using
  * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
 
-static inline uint32_t
-blend_exclusion (uint32_t d, uint32_t ad, uint32_t s, uint32_t as)
+static inline int32_t
+blend_exclusion (int32_t d, int32_t ad, int32_t s, int32_t as)
 {
-    return DIV_ONE_UN8 (s * ad + d * as - 2 * d * s);
+    return s * ad + d * as - 2 * d * s;
 }
 
 PDF_SEPARABLE_BLEND_MODE (exclusion)
diff --git a/test/blitters-test.c b/test/blitters-test.c
index df82358..ac8901f 100644
--- a/test/blitters-test.c
+++ b/test/blitters-test.c
@@ -394,6 +394,6 @@ main (int argc, const char *argv[])
     }
 
     return fuzzer_test_main("blitters", 2000000,
-			    0x63B4E3F3,
+			    0x613BBD64,
 			    test_composite, argc, argv);
 }
diff --git a/test/thread-test.c b/test/thread-test.c
index 0b07b26..8fa2098 100644
--- a/test/thread-test.c
+++ b/test/thread-test.c
@@ -183,7 +183,7 @@ main (void)
 
     crc32 = compute_crc32 (0, crc32s, sizeof crc32s);
 
-#define EXPECTED 0xE299B18E
+#define EXPECTED 0xE8D161DF
 
     if (crc32 != EXPECTED)
     {
commit fe3504d03fafbd8462a34fbe6150254eeb1d0bcd
Author: Søren Sandmann <ssp at redhat.com>
Date:   Wed Dec 4 10:06:06 2013 -0500

    pixel-test.c: Add a number of pixels that have failed at some point
    
    This commit adds a large number of pixel regressions to
    pixel-test. All of these have at some point been failing in
    blend-mode-test, and most of them do fail currently.
    
    To be specific, with this commit, pixel-test reports 431 failed tests.

diff --git a/test/pixel-test.c b/test/pixel-test.c
index 9d2831d..7dc0eff 100644
--- a/test/pixel-test.c
+++ b/test/pixel-test.c
@@ -41,6 +41,2376 @@ struct pixel_combination_t
 
 static const pixel_combination_t regressions[] =
 {
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffc3ff,
+      PIXMAN_a8,	0x7b,
+      PIXMAN_a8r8g8b8,	0xff00c300,
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb5,
+      PIXMAN_a4r4g4b4,	0xe3ff,
+      PIXMAN_a2r2g2b2,	0x2e
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa6,
+      PIXMAN_a8r8g8b8,	0x2b00ff00,
+      PIXMAN_a4r4g4b4,	0x7e
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0x27000013,
+      PIXMAN_a2r2g2b2,	0x80,
+      PIXMAN_a4r4g4b4,	0x9d
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xe6f7,
+      PIXMAN_a2r2g2b2,	0xad,
+      PIXMAN_a4r4g4b4,	0x71
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0xff4f70ff,
+      PIXMAN_r5g6b5,	0xb828,
+      PIXMAN_a8r8g8b8,	0xcac400
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa9,
+      PIXMAN_a4r4g4b4,	0x41c2,
+      PIXMAN_a8r8g8b8,	0xffff2b
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x89,
+      PIXMAN_a8r8g8b8,	0x977cff61,
+      PIXMAN_a4r4g4b4,	0x36
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x81,
+      PIXMAN_r5g6b5,	0x6f9e,
+      PIXMAN_a4r4g4b4,	0x1eb
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb5,
+      PIXMAN_a4r4g4b4,	0xe247,
+      PIXMAN_a8r8g8b8,	0xffbaff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x97,
+      PIXMAN_a2r2g2b2,	0x9d,
+      PIXMAN_a2r2g2b2,	0x21
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb4,
+      PIXMAN_a2r2g2b2,	0x90,
+      PIXMAN_a8r8g8b8,	0xc0fd5c
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0xdf00ff70,
+      PIXMAN_a8r8g8b8,	0x2597ff27,
+      PIXMAN_a4r4g4b4,	0xf3
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb7,
+      PIXMAN_r3g3b2,	0xb1,
+      PIXMAN_a8r8g8b8,	0x9f4bcc
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xf39e,
+      PIXMAN_r5g6b5,	0x34,
+      PIXMAN_a8r8g8b8,	0xf6ae00
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0x3aff1dff,
+      PIXMAN_a2r2g2b2,	0x64,
+      PIXMAN_a8r8g8b8,	0x94ffb4
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa4,
+      PIXMAN_a2r2g2b2,	0x8a,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa5,
+      PIXMAN_a4r4g4b4,	0x1a,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb4,
+      PIXMAN_a2r2g2b2,	0xca,
+      PIXMAN_a4r4g4b4,	0x7b
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xbd,
+      PIXMAN_a4r4g4b4,	0xff37,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x96,
+      PIXMAN_a2r2g2b2,	0xbb,
+      PIXMAN_a8r8g8b8,	0x96ffff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x89,
+      PIXMAN_r3g3b2,	0x92,
+      PIXMAN_a4r4g4b4,	0xa8c
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xa95b,
+      PIXMAN_a2r2g2b2,	0x68,
+      PIXMAN_a8r8g8b8,	0x38ff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x90,
+      PIXMAN_a8r8g8b8,	0x53bd00ef,
+      PIXMAN_a8r8g8b8,	0xff0003
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1f5ffff,
+      PIXMAN_r3g3b2,	0x22,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x10000b6,
+      PIXMAN_a8r8g8b8,	0x9645,
+      PIXMAN_r5g6b5,	0x6
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x172ff00,
+      PIXMAN_a4r4g4b4,	0xff61,
+      PIXMAN_r3g3b2,	0xc
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x281ffc8,
+      PIXMAN_r5g6b5,	0x39b8,
+      PIXMAN_r5g6b5,	0x13
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100a2ff,
+      PIXMAN_a4r4g4b4,	0x6500,
+      PIXMAN_a2r2g2b2,	0x5
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff51,
+      PIXMAN_r5g6b5,	0x52ff,
+      PIXMAN_a2r2g2b2,	0x14
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x150d500,
+      PIXMAN_a8r8g8b8,	0x6200b7ff,
+      PIXMAN_a8r8g8b8,	0x1f5200
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2a9a700,
+      PIXMAN_a8r8g8b8,	0xf7003400,
+      PIXMAN_a8r8g8b8,	0x2200
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x200ffff,
+      PIXMAN_r5g6b5,	0x81ff,
+      PIXMAN_r5g6b5,	0x1f
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ff00ff,
+      PIXMAN_r5g6b5,	0x3f00,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3ff1aa4,
+      PIXMAN_a4r4g4b4,	0x2200,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x280ff2c,
+      PIXMAN_r3g3b2,	0xc6,
+      PIXMAN_a8r8g8b8,	0xfdfd44fe
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x13aff1d,
+      PIXMAN_a2r2g2b2,	0x4b,
+      PIXMAN_r5g6b5,	0x12a1
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2ffff88,
+      PIXMAN_a8r8g8b8,	0xff3a49,
+      PIXMAN_r5g6b5,	0xf7df
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1009700,
+      PIXMAN_a2r2g2b2,	0x56,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1aacbff,
+      PIXMAN_a4r4g4b4,	0x84,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x100b1ff,
+      PIXMAN_a2r2g2b2,	0xf5,
+      PIXMAN_a8r8g8b8,	0xfea89cff
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ff0000,
+      PIXMAN_r5g6b5,	0x6800,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x10064ff,
+      PIXMAN_r3g3b2,	0x61,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1bb00ff,
+      PIXMAN_r5g6b5,	0x76b5,
+      PIXMAN_a4r4g4b4,	0x500
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ffff41,
+      PIXMAN_r5g6b5,	0x7100,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ff1231,
+      PIXMAN_a8r8g8b8,	0x381089,
+      PIXMAN_r5g6b5,	0x38a5
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x16e5c49,
+      PIXMAN_a8r8g8b8,	0x4dfa3694,
+      PIXMAN_a8r8g8b8,	0x211c16
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x134ff62,
+      PIXMAN_a2r2g2b2,	0x14,
+      PIXMAN_r3g3b2,	0x8
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x300ffeb,
+      PIXMAN_r3g3b2,	0xc7,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x3ff8bff,
+      PIXMAN_r3g3b2,	0x3e,
+      PIXMAN_a8r8g8b8,	0x3008baa
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff00ff,
+      PIXMAN_a4r4g4b4,	0x3466,
+      PIXMAN_a4r4g4b4,	0x406
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ddc027,
+      PIXMAN_a4r4g4b4,	0x7d00,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2ffff00,
+      PIXMAN_a8r8g8b8,	0xc92cfb52,
+      PIXMAN_a4r4g4b4,	0x200
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ff116a,
+      PIXMAN_a4r4g4b4,	0x6000,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r5g6b5,	0x2f95,
+      PIXMAN_r5g6b5,	0x795
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffff00,
+      PIXMAN_a4r4g4b4,	0x354a,
+      PIXMAN_r5g6b5,	0x3180
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1d7ff00,
+      PIXMAN_a4r4g4b4,	0xd6ff,
+      PIXMAN_a8r8g8b8,	0xffff0700
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1bc5db7,
+      PIXMAN_r5g6b5,	0x944f,
+      PIXMAN_a4r4g4b4,	0xff05
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x185ffd9,
+      PIXMAN_a2r2g2b2,	0x9c,
+      PIXMAN_r5g6b5,	0x3c07
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1fa7f61,
+      PIXMAN_a8r8g8b8,	0xff31ff00,
+      PIXMAN_r3g3b2,	0xd2
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1c4ff00,
+      PIXMAN_r3g3b2,	0xb,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ff00ff,
+      PIXMAN_a8r8g8b8,	0x3f3caeda,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ff00,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_r5g6b5,	0xe0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff68ff,
+      PIXMAN_a4r4g4b4,	0x8046,
+      PIXMAN_r5g6b5,	0xec
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x100ff28,
+      PIXMAN_a8r8g8b8,	0x4c00,
+      PIXMAN_r5g6b5,	0x260
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_a4r4g4b4,	0xd92a,
+      PIXMAN_a8r8g8b8,	0x2200
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100289a,
+      PIXMAN_a8r8g8b8,	0x74ffb8ff,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1baff00,
+      PIXMAN_r5g6b5,	0x4e9d,
+      PIXMAN_r5g6b5,	0x3000
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1fcffad,
+      PIXMAN_r5g6b5,	0x42d7,
+      PIXMAN_a8r8g8b8,	0x1c6ffe5
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x183ff00,
+      PIXMAN_r3g3b2,	0x7e,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x2ff0076,
+      PIXMAN_a8r8g8b8,	0x2a0000,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3d8bbff,
+      PIXMAN_r5g6b5,	0x6900,
+      PIXMAN_a8r8g8b8,	0x35b0000
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x14f00ff,
+      PIXMAN_r5g6b5,	0xd48,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x28c72df,
+      PIXMAN_a8r8g8b8,	0xff5cff31,
+      PIXMAN_a4r4g4b4,	0x2
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffffff,
+      PIXMAN_a8r8g8b8,	0xffad8020,
+      PIXMAN_r5g6b5,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x100ff00,
+      PIXMAN_a2r2g2b2,	0x76,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1005d00,
+      PIXMAN_r5g6b5,	0x7b04,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x3cdfc3e,
+      PIXMAN_a8r8g8b8,	0x69ec21d3,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x200ffff,
+      PIXMAN_r5g6b5,	0x30ff,
+      PIXMAN_r5g6b5,	0x60ff
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x532fff4,
+      PIXMAN_r5g6b5,	0xcb,
+      PIXMAN_r5g6b5,	0xd9a1
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r3g3b2,	0x5f,
+      PIXMAN_a2r2g2b2,	0x10
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_a8r8g8b8,	0xffd60052,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ff6491,
+      PIXMAN_a8r8g8b8,	0x1e53ff00,
+      PIXMAN_r5g6b5,	0x1862
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_r3g3b2,	0xc7,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x29d0fff,
+      PIXMAN_a4r4g4b4,	0x25ff,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x141760a,
+      PIXMAN_a4r4g4b4,	0x7ec2,
+      PIXMAN_a4r4g4b4,	0x130
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1abedff,
+      PIXMAN_a8r8g8b8,	0x75520068,
+      PIXMAN_r3g3b2,	0x87
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x10000ff,
+      PIXMAN_a8r8g8b8,	0xff00e652,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x16006075,
+      PIXMAN_r5g6b5,	0xc00,
+      PIXMAN_a8r8g8b8,	0x27f0900
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x200ff00,
+      PIXMAN_a8r8g8b8,	0xd1b83f57,
+      PIXMAN_a4r4g4b4,	0xff75
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x14000c4,
+      PIXMAN_a4r4g4b4,	0x96,
+      PIXMAN_a2r2g2b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ff00d1,
+      PIXMAN_r3g3b2,	0x79,
+      PIXMAN_a2r2g2b2,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff00dc,
+      PIXMAN_a4r4g4b4,	0xc5ff,
+      PIXMAN_a2r2g2b2,	0x10
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffb2,
+      PIXMAN_a8r8g8b8,	0x4cff5700,
+      PIXMAN_r3g3b2,	0x48
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1327482,
+      PIXMAN_a8r8g8b8,	0x247ff,
+      PIXMAN_a8r8g8b8,	0x82
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1d0ff00,
+      PIXMAN_r3g3b2,	0xc9,
+      PIXMAN_r5g6b5,	0x240
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x13d35ff,
+      PIXMAN_a2r2g2b2,	0x6d,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffc6b2,
+      PIXMAN_a8r8g8b8,	0x5abe8e3c,
+      PIXMAN_r5g6b5,	0x5a27
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x15700ff,
+      PIXMAN_r3g3b2,	0xdd,
+      PIXMAN_a8r8g8b8,	0x55
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff11ff,
+      PIXMAN_r3g3b2,	0x30,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff00ff,
+      PIXMAN_a2r2g2b2,	0x6d,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1421d5f,
+      PIXMAN_a4r4g4b4,	0xff85,
+      PIXMAN_a8r8g8b8,	0x1420f00
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1d2ffff,
+      PIXMAN_r5g6b5,	0xfc,
+      PIXMAN_r5g6b5,	0x1c
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffff42,
+      PIXMAN_a4r4g4b4,	0x7100,
+      PIXMAN_a4r4g4b4,	0x771
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x25ae3d4,
+      PIXMAN_a8r8g8b8,	0x39ffc99a,
+      PIXMAN_a8r8g8b8,	0x14332f
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff0643,
+      PIXMAN_a8r8g8b8,	0x4c000000,
+      PIXMAN_r5g6b5,	0x4802
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1966a00,
+      PIXMAN_r3g3b2,	0x46,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x387ff59,
+      PIXMAN_r5g6b5,	0x512c,
+      PIXMAN_r5g6b5,	0x120
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1f7ffb0,
+      PIXMAN_r5g6b5,	0x63b8,
+      PIXMAN_a8r8g8b8,	0x1000089
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x185841c,
+      PIXMAN_a2r2g2b2,	0x5c,
+      PIXMAN_a8r8g8b8,	0x8400
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffc3ff,
+      PIXMAN_a8r8g8b8,	0xff7b,
+      PIXMAN_a8r8g8b8,	0xff00c300
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff7500,
+      PIXMAN_a2r2g2b2,	0x47,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1002361,
+      PIXMAN_a2r2g2b2,	0x7e,
+      PIXMAN_r5g6b5,	0x64
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x10000b6,
+      PIXMAN_a8r8g8b8,	0x59004463,
+      PIXMAN_a4r4g4b4,	0xffa7
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff5a49,
+      PIXMAN_a8r8g8b8,	0xff3fff2b,
+      PIXMAN_a8r8g8b8,	0x13f000c
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x3ffecfc,
+      PIXMAN_r3g3b2,	0x3c,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1630044,
+      PIXMAN_a2r2g2b2,	0x63,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1d2ff58,
+      PIXMAN_a8r8g8b8,	0x8f77ff,
+      PIXMAN_a4r4g4b4,	0x705
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x14dffff,
+      PIXMAN_a2r2g2b2,	0x9a,
+      PIXMAN_a8r8g8b8,	0x1a0000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ff92,
+      PIXMAN_a4r4g4b4,	0x540c,
+      PIXMAN_r5g6b5,	0x2a6
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_a4r4g4b4,	0xddd5,
+      PIXMAN_a4r4g4b4,	0xdd0
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r5g6b5,	0xff8c,
+      PIXMAN_a4r4g4b4,	0xff0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r3g3b2,	0x66,
+      PIXMAN_r5g6b5,	0x7d1f
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_a4r4g4b4,	0xff5b,
+      PIXMAN_a8r8g8b8,	0x5500
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2ed2dff,
+      PIXMAN_r5g6b5,	0x7ae7,
+      PIXMAN_r3g3b2,	0xce
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1b13205,
+      PIXMAN_a8r8g8b8,	0x35ffff00,
+      PIXMAN_r5g6b5,	0x2040
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1e60dff,
+      PIXMAN_a4r4g4b4,	0x760f,
+      PIXMAN_a2r2g2b2,	0x11
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x10000ff,
+      PIXMAN_a4r4g4b4,	0x3,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_a8r8g8b8,	0x6600,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x30000fa,
+      PIXMAN_a4r4g4b4,	0x23b7,
+      PIXMAN_a8r8g8b8,	0x21
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r3g3b2,	0x60,
+      PIXMAN_r3g3b2,	0x60
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3b31b30,
+      PIXMAN_r3g3b2,	0x2e,
+      PIXMAN_a8r8g8b8,	0x3000c20
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x160ffff,
+      PIXMAN_a4r4g4b4,	0xff42,
+      PIXMAN_r3g3b2,	0xed
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x172ffff,
+      PIXMAN_a4r4g4b4,	0x5100,
+      PIXMAN_r3g3b2,	0x29
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x16300ff,
+      PIXMAN_a4r4g4b4,	0x5007,
+      PIXMAN_a8r8g8b8,	0x77
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2ffff3a,
+      PIXMAN_a8r8g8b8,	0x26640083,
+      PIXMAN_a4r4g4b4,	0x220
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x106ff60,
+      PIXMAN_r5g6b5,	0xdce,
+      PIXMAN_a8r8g8b8,	0x100ba00
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100e7ff,
+      PIXMAN_r5g6b5,	0xa00,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2b500f1,
+      PIXMAN_a4r4g4b4,	0x7339,
+      PIXMAN_a8r8g8b8,	0x1000091
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff00ff,
+      PIXMAN_a4r4g4b4,	0xc863,
+      PIXMAN_r5g6b5,	0x6
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1ffffca,
+      PIXMAN_a8r8g8b8,	0x8b4cf000,
+      PIXMAN_r3g3b2,	0xd2
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1fffe00,
+      PIXMAN_r3g3b2,	0x88,
+      PIXMAN_r3g3b2,	0x8
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x16f0000,
+      PIXMAN_a2r2g2b2,	0x59,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x377ff43,
+      PIXMAN_a4r4g4b4,	0x2a,
+      PIXMAN_a8r8g8b8,	0x2d
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x11dffff,
+      PIXMAN_r3g3b2,	0xcb,
+      PIXMAN_r3g3b2,	0x8
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_r5g6b5,	0xbdab,
+      PIXMAN_a4r4g4b4,	0xbb0
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff3343,
+      PIXMAN_a8r8g8b8,	0x7a00ffff,
+      PIXMAN_a2r2g2b2,	0xd
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ebff4b,
+      PIXMAN_r3g3b2,	0x26,
+      PIXMAN_r3g3b2,	0x24
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2c1b3ff,
+      PIXMAN_a8r8g8b8,	0x3000152a,
+      PIXMAN_r3g3b2,	0x24
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1a7ffff,
+      PIXMAN_r3g3b2,	0x9,
+      PIXMAN_r5g6b5,	0x24a
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x4ff00ec,
+      PIXMAN_a8r8g8b8,	0x1da4961e,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff25ff,
+      PIXMAN_a8r8g8b8,	0x64b0ff00,
+      PIXMAN_r5g6b5,	0x606c
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1fd62ff,
+      PIXMAN_a4r4g4b4,	0x76b1,
+      PIXMAN_r5g6b5,	0x716e
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x194ffde,
+      PIXMAN_r5g6b5,	0x47ff,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x108ffff,
+      PIXMAN_a8r8g8b8,	0xffffff66,
+      PIXMAN_r5g6b5,	0xff0c
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x5ffffff,
+      PIXMAN_r5g6b5,	0xdf,
+      PIXMAN_r5g6b5,	0xc0
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ad31,
+      PIXMAN_a2r2g2b2,	0xc5,
+      PIXMAN_a4r4g4b4,	0x31
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff34,
+      PIXMAN_a8r8g8b8,	0x6a57c491,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1fffff1,
+      PIXMAN_r3g3b2,	0xaf,
+      PIXMAN_r5g6b5,	0xb01e
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff67ff,
+      PIXMAN_a4r4g4b4,	0x50ff,
+      PIXMAN_a8r8g8b8,	0x552255
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x11bffff,
+      PIXMAN_r5g6b5,	0xef0c,
+      PIXMAN_r5g6b5,	0xc
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x16cf37d,
+      PIXMAN_a4r4g4b4,	0xc561,
+      PIXMAN_r5g6b5,	0x2301
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffff9c,
+      PIXMAN_a4r4g4b4,	0x2700,
+      PIXMAN_a8r8g8b8,	0xffff
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x200f322,
+      PIXMAN_a8r8g8b8,	0xff3c7e,
+      PIXMAN_r5g6b5,	0x2
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1f14a33,
+      PIXMAN_a8r8g8b8,	0x26cff79,
+      PIXMAN_r3g3b2,	0xf9
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x11d922c,
+      PIXMAN_r3g3b2,	0xab,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_a2r2g2b2,	0xf5,
+      PIXMAN_r3g3b2,	0x9
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x18697ff,
+      PIXMAN_a4r4g4b4,	0x5700,
+      PIXMAN_r5g6b5,	0xfa6d
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x12000fc,
+      PIXMAN_a2r2g2b2,	0x41,
+      PIXMAN_a8r8g8b8,	0xb0054
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x100ccff,
+      PIXMAN_a4r4g4b4,	0x657e,
+      PIXMAN_r5g6b5,	0x3b1
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffff1f,
+      PIXMAN_a2r2g2b2,	0xa6,
+      PIXMAN_r5g6b5,	0x2a0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x11fff82,
+      PIXMAN_a4r4g4b4,	0xff94,
+      PIXMAN_a8r8g8b8,	0x1010123
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x154bd19,
+      PIXMAN_a4r4g4b4,	0xb600,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x10000ff,
+      PIXMAN_r5g6b5,	0x8e,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x21aff00,
+      PIXMAN_r5g6b5,	0x71ff,
+      PIXMAN_r3g3b2,	0xf2
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ad00a7,
+      PIXMAN_a4r4g4b4,	0x23,
+      PIXMAN_a8r8g8b8,	0x21
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x100ff00,
+      PIXMAN_r5g6b5,	0xb343,
+      PIXMAN_r3g3b2,	0xc
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x3ffa500,
+      PIXMAN_a8r8g8b8,	0x1af5b4,
+      PIXMAN_a8r8g8b8,	0xff1abc00
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ffff11,
+      PIXMAN_a8r8g8b8,	0x9f334f,
+      PIXMAN_a8r8g8b8,	0x9f0005
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2c75971,
+      PIXMAN_a4r4g4b4,	0x3900,
+      PIXMAN_a4r4g4b4,	0x211
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ff49,
+      PIXMAN_a8r8g8b8,	0x813dc25e,
+      PIXMAN_r5g6b5,	0x667d
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x10000ff,
+      PIXMAN_a4r4g4b4,	0x4bff,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x20ebcff,
+      PIXMAN_r5g6b5,	0xc9ff,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_r5g6b5,	0x51ff,
+      PIXMAN_r3g3b2,	0x44
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffd158,
+      PIXMAN_a8r8g8b8,	0x7d88ffce,
+      PIXMAN_r3g3b2,	0x6c
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1425e21,
+      PIXMAN_a2r2g2b2,	0xa5,
+      PIXMAN_r5g6b5,	0xe1
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x14b00ff,
+      PIXMAN_a8r8g8b8,	0xbe95004b,
+      PIXMAN_r5g6b5,	0x9
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x14fc0cd,
+      PIXMAN_a8r8g8b8,	0x2d12b78b,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff8230,
+      PIXMAN_a2r2g2b2,	0x4c,
+      PIXMAN_r3g3b2,	0x44
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff31ff,
+      PIXMAN_a2r2g2b2,	0x14,
+      PIXMAN_a8r8g8b8,	0x551000
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x17800ff,
+      PIXMAN_a4r4g4b4,	0x22,
+      PIXMAN_a8r8g8b8,	0x22
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x14500ff,
+      PIXMAN_a4r4g4b4,	0x6400,
+      PIXMAN_r5g6b5,	0xff78
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ff9d,
+      PIXMAN_r3g3b2,	0xcd,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x3ff00ff,
+      PIXMAN_a4r4g4b4,	0xf269,
+      PIXMAN_a4r4g4b4,	0x200
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ff28b8,
+      PIXMAN_a4r4g4b4,	0x33ff,
+      PIXMAN_r5g6b5,	0x3000
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1006278,
+      PIXMAN_a8r8g8b8,	0x8a7f18,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffcb00,
+      PIXMAN_a4r4g4b4,	0x7900,
+      PIXMAN_a2r2g2b2,	0x14
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x115ff00,
+      PIXMAN_a8r8g8b8,	0x508d,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x3ff30b5,
+      PIXMAN_r5g6b5,	0x2e60,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x182fffb,
+      PIXMAN_r3g3b2,	0x1,
+      PIXMAN_a8r8g8b8,	0x1000054
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x16fff00,
+      PIXMAN_r5g6b5,	0x7bc0,
+      PIXMAN_a8r8g8b8,	0x367900
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1d95dd8,
+      PIXMAN_a4r4g4b4,	0xfff5,
+      PIXMAN_r5g6b5,	0xff09
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ff3cdc,
+      PIXMAN_a8r8g8b8,	0x3bda45ff,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x13900f8,
+      PIXMAN_a8r8g8b8,	0x7e00ffff,
+      PIXMAN_a4r4g4b4,	0xff00
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x10ea9ff,
+      PIXMAN_a8r8g8b8,	0xff34ff22,
+      PIXMAN_r5g6b5,	0xff52
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2002e99,
+      PIXMAN_a4r4g4b4,	0x3000,
+      PIXMAN_r5g6b5,	0x43
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_r5g6b5,	0x19ff,
+      PIXMAN_r3g3b2,	0x3
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_a8r8g8b8,	0xffff4251,
+      PIXMAN_a2r2g2b2,	0x4
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x121c9ff,
+      PIXMAN_a4r4g4b4,	0xd2,
+      PIXMAN_a4r4g4b4,	0x2
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ff4d,
+      PIXMAN_a2r2g2b2,	0x5e,
+      PIXMAN_a2r2g2b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x29ab4ff,
+      PIXMAN_r3g3b2,	0x47,
+      PIXMAN_a8r8g8b8,	0x1900
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffc1ac,
+      PIXMAN_a8r8g8b8,	0xee4ed0ac,
+      PIXMAN_a8r8g8b8,	0x1009d74
+    },
+    { PIXMAN_OP_CONJOINT_IN_REVERSE,
+      PIXMAN_a8r8g8b8,	0x269dffdc,
+      PIXMAN_a8r8g8b8,	0xff0b00e0,
+      PIXMAN_a8r8g8b8,	0x2a200ff
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffffff,
+      PIXMAN_a4r4g4b4,	0x3200,
+      PIXMAN_r3g3b2,	0x24
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x100ffed,
+      PIXMAN_a8r8g8b8,	0x67004eff,
+      PIXMAN_a2r2g2b2,	0x5
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2fffd6a,
+      PIXMAN_a8r8g8b8,	0xc9003bff,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x253ff00,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_r5g6b5,	0xe0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x13600ad,
+      PIXMAN_r5g6b5,	0x35ae,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffa8ff,
+      PIXMAN_a8r8g8b8,	0xff5f00,
+      PIXMAN_r3g3b2,	0xe0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x10067ff,
+      PIXMAN_a4r4g4b4,	0x450d,
+      PIXMAN_a2r2g2b2,	0x1
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1ff01ff,
+      PIXMAN_r3g3b2,	0x77,
+      PIXMAN_r5g6b5,	0x6800
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x11da4ff,
+      PIXMAN_r5g6b5,	0x83c9,
+      PIXMAN_a4r4g4b4,	0x44
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffd4ff,
+      PIXMAN_r3g3b2,	0xaa,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ff0000,
+      PIXMAN_a8r8g8b8,	0x71002a,
+      PIXMAN_a4r4g4b4,	0x700
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1d7ffff,
+      PIXMAN_r5g6b5,	0x3696,
+      PIXMAN_a4r4g4b4,	0x200
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffffc8,
+      PIXMAN_r5g6b5,	0xe900,
+      PIXMAN_a8r8g8b8,	0x2000
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff004a,
+      PIXMAN_r3g3b2,	0x48,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x3ffe969,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_r5g6b5,	0xc0
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x300ff73,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_a8r8g8b8,	0x3000073
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ff93ff,
+      PIXMAN_a8r8g8b8,	0x61fc7d2b,
+      PIXMAN_a4r4g4b4,	0x2
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x11bffff,
+      PIXMAN_a4r4g4b4,	0xffb4,
+      PIXMAN_r5g6b5,	0x8
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1e9e100,
+      PIXMAN_a2r2g2b2,	0x56,
+      PIXMAN_a2r2g2b2,	0x14
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x3ffb656,
+      PIXMAN_r3g3b2,	0x4,
+      PIXMAN_a4r4g4b4,	0xff99
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ff00,
+      PIXMAN_r3g3b2,	0x68,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1006dff,
+      PIXMAN_a2r2g2b2,	0x5d,
+      PIXMAN_a8r8g8b8,	0xff00ff55
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x11c00cb,
+      PIXMAN_a2r2g2b2,	0x44,
+      PIXMAN_a4r4g4b4,	0x4
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1d0ff86,
+      PIXMAN_r3g3b2,	0x5c,
+      PIXMAN_a8r8g8b8,	0x3c0000
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2f25fff,
+      PIXMAN_r3g3b2,	0x36,
+      PIXMAN_a8r8g8b8,	0x2a444aa
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x134af85,
+      PIXMAN_r3g3b2,	0x29,
+      PIXMAN_r5g6b5,	0xf300
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x13398af,
+      PIXMAN_r3g3b2,	0xa5,
+      PIXMAN_a4r4g4b4,	0x13
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff57ff,
+      PIXMAN_a4r4g4b4,	0x252c,
+      PIXMAN_r3g3b2,	0x40
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x115ffff,
+      PIXMAN_r5g6b5,	0xffe3,
+      PIXMAN_r5g6b5,	0x3303
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffff00,
+      PIXMAN_r5g6b5,	0x6300,
+      PIXMAN_r3g3b2,	0x6c
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x4ccff9c,
+      PIXMAN_r5g6b5,	0xcc,
+      PIXMAN_a8r8g8b8,	0x400003d
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffc6dd,
+      PIXMAN_r5g6b5,	0x9bff,
+      PIXMAN_r5g6b5,	0x5bff
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x14fff95,
+      PIXMAN_r3g3b2,	0x46,
+      PIXMAN_a8r8g8b8,	0x1000063
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1e6b700,
+      PIXMAN_r5g6b5,	0xc1ff,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffff54,
+      PIXMAN_a8r8g8b8,	0x2e00ff,
+      PIXMAN_r5g6b5,	0x2800
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3ffffff,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_r5g6b5,	0xe0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1003550,
+      PIXMAN_r5g6b5,	0xffcc,
+      PIXMAN_r5g6b5,	0x1e0
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ffff74,
+      PIXMAN_r3g3b2,	0x28,
+      PIXMAN_a8r8g8b8,	0xfe2f49d7
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1e35100,
+      PIXMAN_r3g3b2,	0x57,
+      PIXMAN_r5g6b5,	0x4000
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x268ffa3,
+      PIXMAN_a4r4g4b4,	0x30,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x35700f8,
+      PIXMAN_r5g6b5,	0xa4,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x3ce1dff,
+      PIXMAN_r5g6b5,	0x2a5e,
+      PIXMAN_a8r8g8b8,	0x210000
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x494a7ff,
+      PIXMAN_a8r8g8b8,	0x1bffe400,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x10026d9,
+      PIXMAN_a8r8g8b8,	0xec00621f,
+      PIXMAN_r5g6b5,	0x63
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ff99,
+      PIXMAN_a8r8g8b8,	0xf334ff,
+      PIXMAN_a4r4g4b4,	0x30
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffc200,
+      PIXMAN_a8r8g8b8,	0x1e0000ff,
+      PIXMAN_a8r8g8b8,	0x1e1700
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff00ff,
+      PIXMAN_r3g3b2,	0x4b,
+      PIXMAN_r5g6b5,	0x4818
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2e800ff,
+      PIXMAN_a4r4g4b4,	0xd3,
+      PIXMAN_a4r4g4b4,	0xec
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x19a001f,
+      PIXMAN_r3g3b2,	0x76,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1cb00c3,
+      PIXMAN_a4r4g4b4,	0x5cff,
+      PIXMAN_r5g6b5,	0x4008
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff0000,
+      PIXMAN_r3g3b2,	0x2a,
+      PIXMAN_r5g6b5,	0xc5fb
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_a8r8g8b8,	0xea005a88,
+      PIXMAN_r3g3b2,	0xb3
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ffea,
+      PIXMAN_a4r4g4b4,	0x54eb,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x179ffff,
+      PIXMAN_r3g3b2,	0xa4,
+      PIXMAN_a8r8g8b8,	0x2400
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x17ad226,
+      PIXMAN_r3g3b2,	0xa4,
+      PIXMAN_r5g6b5,	0xe0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ff01,
+      PIXMAN_a2r2g2b2,	0x25,
+      PIXMAN_a4r4g4b4,	0x50
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x20000ff,
+      PIXMAN_a8r8g8b8,	0x2b00c127,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x200ff96,
+      PIXMAN_a4r4g4b4,	0x2300,
+      PIXMAN_r3g3b2,	0x6
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x200ffff,
+      PIXMAN_r3g3b2,	0x87,
+      PIXMAN_r5g6b5,	0x5bc8
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1fffff2,
+      PIXMAN_r3g3b2,	0x7e,
+      PIXMAN_a2r2g2b2,	0xe
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1ff8b00,
+      PIXMAN_a4r4g4b4,	0xd500,
+      PIXMAN_r3g3b2,	0x40
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ffffff,
+      PIXMAN_a8r8g8b8,	0x1bff38,
+      PIXMAN_a4r4g4b4,	0xf0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x158ff39,
+      PIXMAN_a4r4g4b4,	0x75dd,
+      PIXMAN_a8r8g8b8,	0xdd31
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1009b70,
+      PIXMAN_a4r4g4b4,	0xff40,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x12fb43f,
+      PIXMAN_a4r4g4b4,	0x69ff,
+      PIXMAN_a2r2g2b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff95,
+      PIXMAN_a2r2g2b2,	0x84,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x200d188,
+      PIXMAN_r5g6b5,	0xde6,
+      PIXMAN_r5g6b5,	0x3
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2c70000,
+      PIXMAN_r5g6b5,	0x24fa,
+      PIXMAN_a8r8g8b8,	0x21a0000
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x100ff24,
+      PIXMAN_a4r4g4b4,	0x835,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x10000cd,
+      PIXMAN_a2r2g2b2,	0x7f,
+      PIXMAN_a2r2g2b2,	0x1
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x379ffff,
+      PIXMAN_a8r8g8b8,	0x23ffff00,
+      PIXMAN_r5g6b5,	0x4eda
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x172e3ff,
+      PIXMAN_r3g3b2,	0xa6,
+      PIXMAN_r5g6b5,	0x100
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100f5ad,
+      PIXMAN_a4r4g4b4,	0x7908,
+      PIXMAN_a2r2g2b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100fff9,
+      PIXMAN_a2r2g2b2,	0xf1,
+      PIXMAN_r3g3b2,	0x1
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1abff00,
+      PIXMAN_r5g6b5,	0x31ff,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x112ffd1,
+      PIXMAN_r3g3b2,	0x9,
+      PIXMAN_a2r2g2b2,	0xdd
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ffbf,
+      PIXMAN_r3g3b2,	0x2c,
+      PIXMAN_a4r4g4b4,	0x60
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffb7ff,
+      PIXMAN_r3g3b2,	0x6b,
+      PIXMAN_a4r4g4b4,	0x630
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x20005ff,
+      PIXMAN_a4r4g4b4,	0x8462,
+      PIXMAN_r5g6b5,	0xb1e8
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff5b00,
+      PIXMAN_r5g6b5,	0x70ff,
+      PIXMAN_r3g3b2,	0x60
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffffc3,
+      PIXMAN_r3g3b2,	0x39,
+      PIXMAN_a8r8g8b8,	0x200db41
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x306ffff,
+      PIXMAN_a8r8g8b8,	0xdcffff1f,
+      PIXMAN_a8r8g8b8,	0x306ff00
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x193daff,
+      PIXMAN_a8r8g8b8,	0x69000000,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x2a200ff,
+      PIXMAN_a8r8g8b8,	0x183aff00,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100f1a5,
+      PIXMAN_a8r8g8b8,	0xb5fc21ff,
+      PIXMAN_r5g6b5,	0xfe00
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1630019,
+      PIXMAN_a8r8g8b8,	0x6affc400,
+      PIXMAN_r5g6b5,	0x56ff
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff8bc2,
+      PIXMAN_r3g3b2,	0xee,
+      PIXMAN_r5g6b5,	0x1c0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x260ffff,
+      PIXMAN_a4r4g4b4,	0x3f00,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x169ffed,
+      PIXMAN_a8r8g8b8,	0xffffff3f,
+      PIXMAN_a8r8g8b8,	0x169ff00
+    },
+    { PIXMAN_OP_CONJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x154c181,
+      PIXMAN_a4r4g4b4,	0x5100,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1e09c00,
+      PIXMAN_r5g6b5,	0xca00,
+      PIXMAN_a4r4g4b4,	0xb00
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ff8dff,
+      PIXMAN_a8r8g8b8,	0x610038ff,
+      PIXMAN_a8r8g8b8,	0x1001f02
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1e400ff,
+      PIXMAN_a4r4g4b4,	0x66bd,
+      PIXMAN_r3g3b2,	0x68
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x25362ff,
+      PIXMAN_a4r4g4b4,	0x31ff,
+      PIXMAN_a8r8g8b8,	0x111433
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3ad0039,
+      PIXMAN_r3g3b2,	0x26,
+      PIXMAN_a8r8g8b8,	0x3000026
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2e442ef,
+      PIXMAN_r3g3b2,	0x32,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1720000,
+      PIXMAN_a8r8g8b8,	0x55fdea00,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x14bb0d7,
+      PIXMAN_a8r8g8b8,	0x7fffff47,
+      PIXMAN_a2r2g2b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x13dffff,
+      PIXMAN_a8r8g8b8,	0xa3860672,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x120495a,
+      PIXMAN_a4r4g4b4,	0x407e,
+      PIXMAN_a8r8g8b8,	0x54
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff8fff,
+      PIXMAN_a2r2g2b2,	0x29,
+      PIXMAN_r5g6b5,	0xa
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100a31a,
+      PIXMAN_a4r4g4b4,	0xde4c,
+      PIXMAN_a4r4g4b4,	0x1
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1d4008c,
+      PIXMAN_r3g3b2,	0x79,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ff0000,
+      PIXMAN_a4r4g4b4,	0x7de4,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1b27e62,
+      PIXMAN_a4r4g4b4,	0x7941,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x300ff00,
+      PIXMAN_a8r8g8b8,	0xfcff255e,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x2ff00b8,
+      PIXMAN_a8r8g8b8,	0x19ff718d,
+      PIXMAN_r5g6b5,	0x1802
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x235ff13,
+      PIXMAN_a8r8g8b8,	0x34bcd9ff,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1006400,
+      PIXMAN_a4r4g4b4,	0x7000,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff8bff,
+      PIXMAN_a4r4g4b4,	0xfff4,
+      PIXMAN_a4r4g4b4,	0xf80
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x24630ff,
+      PIXMAN_a8r8g8b8,	0x1f00000b,
+      PIXMAN_a8r8g8b8,	0x9061f
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff8a00,
+      PIXMAN_a8r8g8b8,	0x79ffab00,
+      PIXMAN_r5g6b5,	0x7a00
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x19807ff,
+      PIXMAN_a4r4g4b4,	0x6794,
+      PIXMAN_a8r8g8b8,	0xff002e00
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x10000da,
+      PIXMAN_a4r4g4b4,	0xf864,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffffde,
+      PIXMAN_a2r2g2b2,	0x94,
+      PIXMAN_a8r8g8b8,	0x1000000
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x200c800,
+      PIXMAN_r5g6b5,	0xe9d4,
+      PIXMAN_a8r8g8b8,	0x2c00
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff00c9,
+      PIXMAN_r3g3b2,	0x4c,
+      PIXMAN_r5g6b5,	0x4800
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x122d5ff,
+      PIXMAN_r5g6b5,	0x418b,
+      PIXMAN_a4r4g4b4,	0x25
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ffff55,
+      PIXMAN_a2r2g2b2,	0x1c,
+      PIXMAN_a8r8g8b8,	0xff00
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x135ffff,
+      PIXMAN_r5g6b5,	0x39c4,
+      PIXMAN_r5g6b5,	0xb7
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x100d2c3,
+      PIXMAN_r3g3b2,	0x2a,
+      PIXMAN_a8r8g8b8,	0x3c00
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x17268ff,
+      PIXMAN_a8r8g8b8,	0x7c00ffff,
+      PIXMAN_r5g6b5,	0x318f
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff00ff,
+      PIXMAN_r3g3b2,	0x68,
+      PIXMAN_r3g3b2,	0xb4
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x200ffff,
+      PIXMAN_r5g6b5,	0xff86,
+      PIXMAN_a8r8g8b8,	0x200f300
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x18a23ff,
+      PIXMAN_a2r2g2b2,	0x44,
+      PIXMAN_a4r4g4b4,	0x205
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x16bff23,
+      PIXMAN_a8r8g8b8,	0x31fd00ff,
+      PIXMAN_r3g3b2,	0x7
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x137d1ff,
+      PIXMAN_a4r4g4b4,	0x56c1,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff5bff,
+      PIXMAN_a4r4g4b4,	0xfff4,
+      PIXMAN_a4r4g4b4,	0xf50
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x15c6b00,
+      PIXMAN_a8r8g8b8,	0x7d008a,
+      PIXMAN_a4r4g4b4,	0x200
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x12091ff,
+      PIXMAN_a8r8g8b8,	0xb74cff6b,
+      PIXMAN_a2r2g2b2,	0x8
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff5bff,
+      PIXMAN_a8r8g8b8,	0xff6ddce8,
+      PIXMAN_a2r2g2b2,	0x10
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_a4r4g4b4,	0xffb7,
+      PIXMAN_a4r4g4b4,	0xb0
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x173ffff,
+      PIXMAN_r5g6b5,	0xff2c,
+      PIXMAN_a4r4g4b4,	0x6
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x17102ff,
+      PIXMAN_a8r8g8b8,	0x955bff66,
+      PIXMAN_a8r8g8b8,	0x280066
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x3c7ff24,
+      PIXMAN_r5g6b5,	0xc4,
+      PIXMAN_r5g6b5,	0x163
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100c2a6,
+      PIXMAN_r5g6b5,	0xa9b9,
+      PIXMAN_a4r4g4b4,	0x8
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x26049ff,
+      PIXMAN_a4r4g4b4,	0xb2,
+      PIXMAN_r5g6b5,	0x8904
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2f100ff,
+      PIXMAN_r3g3b2,	0x30,
+      PIXMAN_a8r8g8b8,	0x2220100
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ffff88,
+      PIXMAN_r3g3b2,	0x7e,
+      PIXMAN_r3g3b2,	0x60
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x153ffab,
+      PIXMAN_a8r8g8b8,	0xfd10725a,
+      PIXMAN_r3g3b2,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff00d2,
+      PIXMAN_r5g6b5,	0xff6b,
+      PIXMAN_a8r8g8b8,	0x101014a
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100d965,
+      PIXMAN_a8r8g8b8,	0xff007b00,
+      PIXMAN_r3g3b2,	0xc
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ec0000,
+      PIXMAN_r5g6b5,	0x6fff,
+      PIXMAN_r5g6b5,	0x6000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x19d59a2,
+      PIXMAN_a8r8g8b8,	0x4a00ff7a,
+      PIXMAN_a8r8g8b8,	0x2e1a2f
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1eb0000,
+      PIXMAN_a4r4g4b4,	0x72bc,
+      PIXMAN_r5g6b5,	0x1800
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_a4r4g4b4,	0xc034,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x195ff15,
+      PIXMAN_a4r4g4b4,	0xb7b1,
+      PIXMAN_r5g6b5,	0x4000
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffdf94,
+      PIXMAN_a4r4g4b4,	0x78,
+      PIXMAN_r3g3b2,	0xc
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x26f00ff,
+      PIXMAN_a4r4g4b4,	0xff93,
+      PIXMAN_r5g6b5,	0x1dd2
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2ff3fc5,
+      PIXMAN_r3g3b2,	0x2f,
+      PIXMAN_a8r8g8b8,	0x240000
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1ff696e,
+      PIXMAN_a4r4g4b4,	0x22ff,
+      PIXMAN_r5g6b5,	0x34d
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x10033d9,
+      PIXMAN_a8r8g8b8,	0x38650000,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffff00,
+      PIXMAN_a4r4g4b4,	0x2070,
+      PIXMAN_r5g6b5,	0x2100
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1008746,
+      PIXMAN_a8r8g8b8,	0xb56971,
+      PIXMAN_r5g6b5,	0xc25c
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x144d200,
+      PIXMAN_a4r4g4b4,	0xff42,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1ffffd0,
+      PIXMAN_r5g6b5,	0x5b00,
+      PIXMAN_r3g3b2,	0x4c
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x10000ff,
+      PIXMAN_a8r8g8b8,	0xff006f,
+      PIXMAN_r5g6b5,	0xd
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x10666ff,
+      PIXMAN_a4r4g4b4,	0x39b2,
+      PIXMAN_r5g6b5,	0xa6
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x11a007d,
+      PIXMAN_r3g3b2,	0xf9,
+      PIXMAN_a8r8g8b8,	0x11a0000
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1eb90ee,
+      PIXMAN_r5g6b5,	0xd,
+      PIXMAN_a2r2g2b2,	0x1
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ff42d5,
+      PIXMAN_a4r4g4b4,	0x3400,
+      PIXMAN_r3g3b2,	0x40
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1dfff00,
+      PIXMAN_a8r8g8b8,	0x3ffff9d2,
+      PIXMAN_r5g6b5,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff6500,
+      PIXMAN_a2r2g2b2,	0x56,
+      PIXMAN_r3g3b2,	0x44
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x119ffe6,
+      PIXMAN_r3g3b2,	0x8d,
+      PIXMAN_a4r4g4b4,	0xff00
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x100cd00,
+      PIXMAN_r5g6b5,	0x33ff,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x569ffd7,
+      PIXMAN_r5g6b5,	0x8cc,
+      PIXMAN_r5g6b5,	0xc0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100876a,
+      PIXMAN_a8r8g8b8,	0x575447a5,
+      PIXMAN_r5g6b5,	0x164
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x12d00ff,
+      PIXMAN_a4r4g4b4,	0x3fff,
+      PIXMAN_a4r4g4b4,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ff953b,
+      PIXMAN_a4r4g4b4,	0x2914,
+      PIXMAN_r5g6b5,	0x20a1
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffead4,
+      PIXMAN_a8r8g8b8,	0xff00ea4e,
+      PIXMAN_r3g3b2,	0x5a
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x1ff6400,
+      PIXMAN_a2r2g2b2,	0x99,
+      PIXMAN_r5g6b5,	0xa620
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x17b0084,
+      PIXMAN_r3g3b2,	0xbd,
+      PIXMAN_a4r4g4b4,	0x500
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x4f90bbb,
+      PIXMAN_a8r8g8b8,	0xff00d21f,
+      PIXMAN_a8r8g8b8,	0xfb00fc4a
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ffbb1d,
+      PIXMAN_a8r8g8b8,	0x2dff79ff,
+      PIXMAN_r5g6b5,	0x2c0
+    },
+    { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ffff,
+      PIXMAN_a2r2g2b2,	0x43,
+      PIXMAN_a4r4g4b4,	0x6f
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1f000ff,
+      PIXMAN_a4r4g4b4,	0xb393,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1c60020,
+      PIXMAN_a8r8g8b8,	0x6bffffff,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1727d00,
+      PIXMAN_a2r2g2b2,	0x67,
+      PIXMAN_a4r4g4b4,	0x400
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x14a5194,
+      PIXMAN_a4r4g4b4,	0xd7ff,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x20003fa,
+      PIXMAN_a4r4g4b4,	0x24ff,
+      PIXMAN_a8r8g8b8,	0xffff1550
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1a6ff83,
+      PIXMAN_a4r4g4b4,	0xf400,
+      PIXMAN_r5g6b5,	0x2800
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ffcf00,
+      PIXMAN_r5g6b5,	0x71ff,
+      PIXMAN_a4r4g4b4,	0x30
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x333ffff,
+      PIXMAN_a4r4g4b4,	0x2c00,
+      PIXMAN_r3g3b2,	0x4
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1c2ffe8,
+      PIXMAN_r5g6b5,	0xc200,
+      PIXMAN_a8r8g8b8,	0xfeca41ff
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a2r2g2b2,	0x47,
+      PIXMAN_a8r8g8b8,	0x2ffff00,
+      PIXMAN_a8r8g8b8,	0x3aa0102
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffeb00,
+      PIXMAN_a4r4g4b4,	0xb493,
+      PIXMAN_a4r4g4b4,	0x400
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2afffff,
+      PIXMAN_r5g6b5,	0xcb,
+      PIXMAN_r5g6b5,	0xc0
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x183ff00,
+      PIXMAN_r3g3b2,	0x87,
+      PIXMAN_r5g6b5,	0xae91
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x3ffff00,
+      PIXMAN_a4r4g4b4,	0x2ba4,
+      PIXMAN_r5g6b5,	0x2100
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x215cbc2,
+      PIXMAN_a4r4g4b4,	0xafd3,
+      PIXMAN_a8r8g8b8,	0x115b000
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1853f65,
+      PIXMAN_a8r8g8b8,	0xc68cdc41,
+      PIXMAN_r5g6b5,	0x3
+    },
+    { PIXMAN_OP_CONJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x3ffff8f,
+      PIXMAN_a4r4g4b4,	0x8824,
+      PIXMAN_a4r4g4b4,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x28e08e6,
+      PIXMAN_a8r8g8b8,	0x2cffff31,
+      PIXMAN_r5g6b5,	0x1805
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x1b500be,
+      PIXMAN_r5g6b5,	0xd946,
+      PIXMAN_r5g6b5,	0x9800
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x133ffb3,
+      PIXMAN_a2r2g2b2,	0x42,
+      PIXMAN_a8r8g8b8,	0x11553c
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x21aff81,
+      PIXMAN_r3g3b2,	0xc7,
+      PIXMAN_r5g6b5,	0x120
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x12e004f,
+      PIXMAN_a4r4g4b4,	0xf617,
+      PIXMAN_a4r4g4b4,	0x102
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x164861f,
+      PIXMAN_r3g3b2,	0x4e,
+      PIXMAN_r5g6b5,	0x19c0
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff0eff,
+      PIXMAN_a8r8g8b8,	0xff5c00aa,
+      PIXMAN_r5g6b5,	0x5800
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x1e4c60f,
+      PIXMAN_a8r8g8b8,	0x38ff0e0c,
+      PIXMAN_a4r4g4b4,	0xff2a
+    },
+    { PIXMAN_OP_DISJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff0000,
+      PIXMAN_a8r8g8b8,	0x9f3d6700,
+      PIXMAN_r5g6b5,	0xf3ff
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x205ffd0,
+      PIXMAN_a8r8g8b8,	0xffc22b3b,
+      PIXMAN_a8r8g8b8,	0x2040000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x1ff0059,
+      PIXMAN_r5g6b5,	0x74ff,
+      PIXMAN_a8r8g8b8,	0x1730101
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x29affb8,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_a8r8g8b8,	0x2d25cff
+    },
+    { PIXMAN_OP_DISJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x1ffff8b,
+      PIXMAN_a4r4g4b4,	0xff7b,
+      PIXMAN_r5g6b5,	0x3a0
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2a86ad7,
+      PIXMAN_a4r4g4b4,	0xdc22,
+      PIXMAN_a8r8g8b8,	0x2860000
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x3ff00ff,
+      PIXMAN_r3g3b2,	0x33,
+      PIXMAN_r5g6b5,	0x2000
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1e50063,
+      PIXMAN_a8r8g8b8,	0x35ff95d7,
+      PIXMAN_r3g3b2,	0x20
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x2ffe6ff,
+      PIXMAN_a8r8g8b8,	0x153ef297,
+      PIXMAN_r5g6b5,	0x6d2
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x34ffeff,
+      PIXMAN_a4r4g4b4,	0x2e,
+      PIXMAN_r5g6b5,	0x1d
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2ffeada,
+      PIXMAN_r5g6b5,	0xabc6,
+      PIXMAN_a8r8g8b8,	0xfd15b256
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x100ff00,
+      PIXMAN_a8r8g8b8,	0xcff3f32,
+      PIXMAN_a8r8g8b8,	0x3f00
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x1e1b0f1,
+      PIXMAN_a8r8g8b8,	0xff63ff54,
+      PIXMAN_r3g3b2,	0x5d
+    },
+    { PIXMAN_OP_DISJOINT_XOR,
+      PIXMAN_a8r8g8b8,	0x2ffff23,
+      PIXMAN_a8r8g8b8,	0x380094ff,
+      PIXMAN_r5g6b5,	0x3a4b
+    },
+    { PIXMAN_OP_CONJOINT_ATOP,
+      PIXMAN_a4r4g4b4,	0x1000,
+      PIXMAN_r5g6b5,	0xca,
+      PIXMAN_a8r8g8b8,	0x3434500
+    },
+    { PIXMAN_OP_DISJOINT_IN,
+      PIXMAN_a8r8g8b8,	0x195ffe5,
+      PIXMAN_a4r4g4b4,	0x3a29,
+      PIXMAN_a8r8g8b8,	0x0
+    },
+    { PIXMAN_OP_DISJOINT_ATOP,
+      PIXMAN_a8r8g8b8,	0x139007a,
+      PIXMAN_a4r4g4b4,	0x4979,
+      PIXMAN_r5g6b5,	0x84
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa9,
+      PIXMAN_a4r4g4b4,	0xfa18,
+      PIXMAN_a8r8g8b8,	0xabff67ff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x94,
+      PIXMAN_a4r4g4b4,	0x5109,
+      PIXMAN_a8r8g8b8,	0x3affffff
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_r5g6b5,	0xd038,
+      PIXMAN_r5g6b5,	0xff00,
+      PIXMAN_r5g6b5,	0xf9a5
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0x543128ff,
+      PIXMAN_a8r8g8b8,	0x7029ff,
+      PIXMAN_a8r8g8b8,	0x316b1d7
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_r5g6b5,	0x53ff,
+      PIXMAN_r5g6b5,	0x72ff,
+      PIXMAN_a8r8g8b8,	0xffffdeff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0x5b00002b,
+      PIXMAN_a4r4g4b4,	0xc3,
+      PIXMAN_a8r8g8b8,	0x23530be
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0xcefc0041,
+      PIXMAN_a8r8g8b8,	0xf60d02,
+      PIXMAN_a8r8g8b8,	0x1f2ffe5
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_r5g6b5,	0xffdb,
+      PIXMAN_r5g6b5,	0xc700,
+      PIXMAN_r5g6b5,	0x654
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_r5g6b5,	0xffc6,
+      PIXMAN_r5g6b5,	0xff09,
+      PIXMAN_r5g6b5,	0xfe58
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x95,
+      PIXMAN_r5g6b5,	0x1b4a,
+      PIXMAN_a8r8g8b8,	0xab234cff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x95,
+      PIXMAN_a4r4g4b4,	0x5e99,
+      PIXMAN_a8r8g8b8,	0x3b1c1cdd
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_r5g6b5,	0x22,
+      PIXMAN_r5g6b5,	0xd00,
+      PIXMAN_r5g6b5,	0xfbb1
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_r5g6b5,	0xffc8,
+      PIXMAN_a8r8g8b8,	0xa1a3ffff,
+      PIXMAN_r5g6b5,	0x44a
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0xffff7cff,
+      PIXMAN_r5g6b5,	0x900,
+      PIXMAN_a8r8g8b8,	0xffff94ec
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xa7,
+      PIXMAN_r5g6b5,	0xff,
+      PIXMAN_a8r8g8b8,	0xaa00cffe
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0x85,
+      PIXMAN_r5g6b5,	0xffb3,
+      PIXMAN_a8r8g8b8,	0xaaffff4a
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a8r8g8b8,	0x3500a118,
+      PIXMAN_a4r4g4b4,	0x9942,
+      PIXMAN_a8r8g8b8,	0x01ff405e
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xb5,
+      PIXMAN_x4a4,	0xe,
+      PIXMAN_a8r8g8b8,	0xffbaff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xe872,
+      PIXMAN_x2r10g10b10, 0xa648ff00,
+      PIXMAN_a2r10g10b10, 0x14ff00e8,
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x4d2db34,
+      PIXMAN_a8,	0x19,
+      PIXMAN_r5g6b5,	0x9700,
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x2ff0076,
+      PIXMAN_a8r8g8b8,	0x2a0000,
+      PIXMAN_r3g3b2,	0x0,
+    },
+    { PIXMAN_OP_CONJOINT_OVER_REVERSE,
+      PIXMAN_a8r8g8b8,	0x14f00ff,
+      PIXMAN_r5g6b5,	0xd48,
+      PIXMAN_a4r4g4b4,	0x0,
+    },
+    { PIXMAN_OP_CONJOINT_OUT,
+      PIXMAN_a8r8g8b8,	0x3d8bbff,
+      PIXMAN_r5g6b5,	0x6900,
+      PIXMAN_a8r8g8b8,	0x0,
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x2ff00ff,
+      PIXMAN_a4r4g4b4,	0x2300,
+      PIXMAN_r3g3b2,	0x0,
+    },
+    { PIXMAN_OP_SATURATE,
+      PIXMAN_a8r8g8b8,	0x4d2db34,
+      PIXMAN_a8r8g8b8,	0xff0019ff,
+      PIXMAN_r5g6b5,	0x9700,
+    },
+    { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+      PIXMAN_a8r8g8b8,	0x100ac05,
+      PIXMAN_r3g3b2,	0xef,
+      PIXMAN_a2r2g2b2,	0xff,
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a2r2g2b2,	0xbf,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x7e
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r5g6b5,	0xffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x33
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_a8r8g8b8,	0x84c4ffd7,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xffddff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a8r8g8b8,	0xff6e56,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x20ff1ade
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a4r4g4b4,	0xfe0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xbdff
+    },
+    { PIXMAN_OP_SCREEN,
+      PIXMAN_a8r8g8b8,	0x9671ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x43
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a2r2g2b2,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x39ff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_r5g6b5,	0xffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x1968
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a4r4g4b4,	0x4247,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xd8ffff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_r5g6b5,	0xff00,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x79
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r3g3b2,	0xe0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x39
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a8r8g8b8,	0xfff8,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0xff
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_r5g6b5,	0x75fc,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x11ff,
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_r3g3b2,	0x52,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0xc627
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0x9f2b,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x4b00e7f5
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a8r8g8b8,	0x00dfff5c,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x5e0f,
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_a8r8g8b8,	0xff00121b,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x3776
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_r5g6b5,	0x03e0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x01003c00,
+    },
     { PIXMAN_OP_OVER,
       PIXMAN_a8r8g8b8,	0x0f00c300,
       PIXMAN_null,	0x00,
@@ -111,6 +2481,316 @@ static const pixel_combination_t regressions[] =
       PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x10bb1ed7,
     },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a2r2g2b2,	0xbf,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x7e
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a8r8g8b8,	0xffffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xff3fffff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_r3g3b2,	0x38,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x5b
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_a8r8g8b8,	0x2e9effff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x77
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r5g6b5,	0xffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x33
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a8r8g8b8,	0xd0089ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0xb1
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_r3g3b2,	0x8a,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xcd0004
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_a8r8g8b8,	0xffff1e3a,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xcf00
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_a8r8g8b8,	0x84c4ffd7,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xffddff
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_a4r4g4b4,	0xfd75,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x7f
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_r3g3b2,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x63ff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a8r8g8b8,	0xff6e56,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x20ff1ade
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a4r4g4b4,	0xfe0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xbdff
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_r5g6b5,	0x9799,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x8d
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_a8r8g8b8,	0xe8ff1c33,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0x6200
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_a8r8g8b8,	0x22ffffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x63
+    },
+    { PIXMAN_OP_SCREEN,
+      PIXMAN_a8r8g8b8,	0x9671ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x43
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a2r2g2b2,	0x83,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0xff
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_r3g3b2,	0x0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x97
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_r5g6b5,	0xb900,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x6800ff00
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a4r4g4b4,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0x8e
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xff00,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0xbc
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r5g6b5,	0xfffe,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x90
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_r3g3b2,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xc35f
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a2r2g2b2,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x39ff
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a2r2g2b2,	0x1e,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xbaff
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a8r8g8b8,	0xb4ffff26,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0xff
+    },
+    { PIXMAN_OP_COLOR_DODGE,
+      PIXMAN_a4r4g4b4,	0xe3ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x878b
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a8r8g8b8,	0xff700044,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x6
+    },
+    { PIXMAN_OP_DARKEN,
+      PIXMAN_a2r2g2b2,	0xb6,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xcd00
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_a2r2g2b2,	0xfe,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x12
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a8r8g8b8,	0xb1ff006c,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xff7c
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r3g3b2,	0x4e,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x3c
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_r5g6b5,	0xffff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0x1968
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_r3g3b2,	0xe7,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x8cced6ac
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a4r4g4b4,	0xa500,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x1bff009d
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r5g6b5,	0x45ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x32
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a2r2g2b2,	0x18,
+      PIXMAN_null,	0x00,
+      PIXMAN_r5g6b5,	0xdc00
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a4r4g4b4,	0x4247,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xd8ffff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_r5g6b5,	0xff00,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x79
+    },
+    { PIXMAN_OP_COLOR_BURN,
+      PIXMAN_r3g3b2,	0xf,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x9fff00ff
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a2r2g2b2,	0x93,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xff
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a2r2g2b2,	0xa3,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0xca
+    },
+    { PIXMAN_OP_DIFFERENCE,
+      PIXMAN_r3g3b2,	0xe0,
+      PIXMAN_null,	0x00,
+      PIXMAN_a2r2g2b2,	0x39
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r3g3b2,	0x16,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x98ffff
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_r3g3b2,	0x96,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0x225f6c
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_a4r4g4b4,	0x12c7,
+      PIXMAN_null,	0x00,
+      PIXMAN_a4r4g4b4,	0xb100
+    },
+    { PIXMAN_OP_LIGHTEN,
+      PIXMAN_a8r8g8b8,	0xffda91,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0x6a
+    },
+    { PIXMAN_OP_EXCLUSION,
+      PIXMAN_a8r8g8b8,	0xfff8,
+      PIXMAN_null,	0x00,
+      PIXMAN_r3g3b2,	0xff
+    },
+    { PIXMAN_OP_SOFT_LIGHT,
+      PIXMAN_a2r2g2b2,	0xff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xf0ff48ca
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xf1ff,
+      PIXMAN_r5g6b5,	0x6eff,
+      PIXMAN_a8r8g8b8,	0xffffff,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xf1ff,
+      PIXMAN_a8,	0xdf,
+      PIXMAN_a8r8g8b8,	0xffffff,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xf1ff,
+      PIXMAN_null,	0x00,
+      PIXMAN_a8r8g8b8,	0xffffff,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xb867,
+      PIXMAN_a4r4g4b4,	0x82d9,
+      PIXMAN_a8r8g8b8,	0xffc5,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xa9f5,
+      PIXMAN_r5g6b5,	0xadff,
+      PIXMAN_a8r8g8b8,	0xffff00,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0x4900,
+      PIXMAN_r5g6b5,	0x865c,
+      PIXMAN_a8r8g8b8,	0xebff,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xd9ff,
+      PIXMAN_a8r8g8b8,	0xffffffff,
+      PIXMAN_a8r8g8b8,	0x8ff0d,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0x41ff,
+      PIXMAN_a4r4g4b4,	0xcff,
+      PIXMAN_a8r8g8b8,	0xe1ff00,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0x91ff,
+      PIXMAN_a2r2g2b2,	0xf3,
+      PIXMAN_a8r8g8b8,	0xe4ffb4,
+    },
+    { PIXMAN_OP_HARD_LIGHT,
+      PIXMAN_r5g6b5,	0xb9ff,
+      PIXMAN_a2r2g2b2,	0xff,
+      PIXMAN_a8r8g8b8,	0xffff,
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a8r8g8b8,	0x473affff,
+      PIXMAN_r5g6b5,	0x2b00,
+      PIXMAN_r5g6b5,	0x1ff,
+    },
+    { PIXMAN_OP_OVERLAY,
+      PIXMAN_a8r8g8b8,	0xe4ff,
+      PIXMAN_r3g3b2,	0xff,
+      PIXMAN_r5g6b5,	0x89ff,
+    },
 };
 
 static void
commit bd94c1793794b5af9a191380b855f8ff24d7913b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Jan 17 06:36:51 2013 -0500

    test/tolerance-test: New test program
    
    This new test program is similar to test/composite in that it relies
    on the pixel_checker_t API to do tolerance based verification. But
    unlike the composite test, which verifies combinations of a fixed set
    of pixels, this one generates random images and verifies that those
    composite correctly.
    
    Also unlike composite, tolerance-test supports all the separable blend
    mode operators in addition to the original Render operators.
    
    When tests fail, a C struct is printed that can be pasted into
    pixel-test for regression purposes.
    
    There is an option "--forever" which causes the random seed to be set
    to the current time, and then the test runs until interrupted. This is
    useful for overnight runs.
    
    This test currently fails badly due to various bugs in the blend mode
    operators. Later commits will fix those.

diff --git a/test/Makefile.sources b/test/Makefile.sources
index 2ae5d9f..9b520ec 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -27,6 +27,7 @@ TESTPROGRAMS =			\
 	scaling-test		\
 	affine-test		\
 	composite		\
+	tolerance-test		\
 	$(NULL)
 
 # Other programs
diff --git a/test/tolerance-test.c b/test/tolerance-test.c
new file mode 100644
index 0000000..5625630
--- /dev/null
+++ b/test/tolerance-test.c
@@ -0,0 +1,360 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <float.h>
+#include <math.h>
+#include "utils.h"
+
+#define MAX_WIDTH  16
+#define MAX_HEIGHT 16
+#define MAX_STRIDE 4
+
+static const pixman_format_code_t formats[] =
+{
+    PIXMAN_a2r10g10b10,
+    PIXMAN_x2r10g10b10,
+    PIXMAN_a8r8g8b8,
+    PIXMAN_a4r4g4b4,
+    PIXMAN_a2r2g2b2,
+    PIXMAN_r5g6b5,
+    PIXMAN_r3g3b2,
+};
+
+static const pixman_op_t operators[] =
+{
+    PIXMAN_OP_CLEAR,
+    PIXMAN_OP_SRC,
+    PIXMAN_OP_DST,
+    PIXMAN_OP_OVER,
+    PIXMAN_OP_OVER_REVERSE,
+    PIXMAN_OP_IN,
+    PIXMAN_OP_IN_REVERSE,
+    PIXMAN_OP_OUT,
+    PIXMAN_OP_OUT_REVERSE,
+    PIXMAN_OP_ATOP,
+    PIXMAN_OP_ATOP_REVERSE,
+    PIXMAN_OP_XOR,
+    PIXMAN_OP_ADD,
+    PIXMAN_OP_SATURATE,
+
+    PIXMAN_OP_DISJOINT_CLEAR,
+    PIXMAN_OP_DISJOINT_SRC,
+    PIXMAN_OP_DISJOINT_DST,
+    PIXMAN_OP_DISJOINT_OVER,
+    PIXMAN_OP_DISJOINT_OVER_REVERSE,
+    PIXMAN_OP_DISJOINT_IN,
+    PIXMAN_OP_DISJOINT_IN_REVERSE,
+    PIXMAN_OP_DISJOINT_OUT,
+    PIXMAN_OP_DISJOINT_OUT_REVERSE,
+    PIXMAN_OP_DISJOINT_ATOP,
+    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+    PIXMAN_OP_DISJOINT_XOR,
+
+    PIXMAN_OP_CONJOINT_CLEAR,
+    PIXMAN_OP_CONJOINT_SRC,
+    PIXMAN_OP_CONJOINT_DST,
+    PIXMAN_OP_CONJOINT_OVER,
+    PIXMAN_OP_CONJOINT_OVER_REVERSE,
+    PIXMAN_OP_CONJOINT_IN,
+    PIXMAN_OP_CONJOINT_IN_REVERSE,
+    PIXMAN_OP_CONJOINT_OUT,
+    PIXMAN_OP_CONJOINT_OUT_REVERSE,
+    PIXMAN_OP_CONJOINT_ATOP,
+    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+    PIXMAN_OP_CONJOINT_XOR,
+
+    PIXMAN_OP_MULTIPLY,
+    PIXMAN_OP_SCREEN,
+    PIXMAN_OP_OVERLAY,
+    PIXMAN_OP_DARKEN,
+    PIXMAN_OP_LIGHTEN,
+    PIXMAN_OP_COLOR_DODGE,
+    PIXMAN_OP_COLOR_BURN,
+    PIXMAN_OP_HARD_LIGHT,
+    PIXMAN_OP_SOFT_LIGHT,
+    PIXMAN_OP_DIFFERENCE,
+    PIXMAN_OP_EXCLUSION,
+};
+
+#define RANDOM_ELT(array)                                               \
+    (array[prng_rand_n (ARRAY_LENGTH (array))])
+
+static void
+free_bits (pixman_image_t *image, void *data)
+{
+    free (image->bits.bits);
+}
+
+static pixman_image_t *
+create_image (pixman_image_t **clone)
+{
+    pixman_format_code_t format = RANDOM_ELT (formats);
+    pixman_image_t *image;
+    int width = prng_rand_n (MAX_WIDTH);
+    int height = prng_rand_n (MAX_HEIGHT);
+    int stride = ((width * (PIXMAN_FORMAT_BPP (format) / 8)) + 3) & ~3;
+    uint32_t *bytes = malloc (stride * height);
+
+    prng_randmemset (bytes, stride * height, RANDMEMSET_MORE_00_AND_FF);
+
+    image = pixman_image_create_bits (
+        format, width, height, bytes, stride);
+
+    pixman_image_set_destroy_function (image, free_bits, NULL);
+
+    assert (image);
+
+    if (clone)
+    {
+        uint32_t *bytes_dup = malloc (stride * height);
+
+        memcpy (bytes_dup, bytes, stride * height);
+
+        *clone = pixman_image_create_bits (
+            format, width, height, bytes_dup, stride);
+
+        pixman_image_set_destroy_function (*clone, free_bits, NULL);
+    }
+    
+    return image;
+}
+
+static pixman_bool_t
+access (pixman_image_t *image, int x, int y, uint32_t *pixel)
+{
+    int bytes_per_pixel;
+    int stride;
+    uint8_t *location;
+
+    if (x < 0 || x >= image->bits.width || y < 0 || y >= image->bits.height)
+        return FALSE;
+    
+    bytes_per_pixel = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
+    stride = image->bits.rowstride * 4;
+    
+    location = (uint8_t *)image->bits.bits + y * stride + x * bytes_per_pixel;
+
+    if (bytes_per_pixel == 4)
+        *pixel = *(uint32_t *)location;
+    else if (bytes_per_pixel == 2)
+        *pixel = *(uint16_t *)location;
+    else if (bytes_per_pixel == 1)
+        *pixel = *(uint8_t *)location;
+    else
+	assert (0);
+
+    return TRUE;
+}
+
+static void
+get_color (pixel_checker_t *checker,
+	   pixman_image_t *image,
+	   int x, int y,
+	   color_t *color,
+	   uint32_t *pixel)
+{
+    if (!access (image, x, y, pixel))
+    {
+	color->a = 0.0;
+	color->r = 0.0;
+	color->g = 0.0;
+	color->b = 0.0;
+    }
+    else
+    {
+	pixel_checker_convert_pixel_to_color (
+	    checker, *pixel, color);
+    }
+}
+            
+static pixman_bool_t
+verify (int test_no,
+        pixman_op_t op,
+        pixman_image_t *source,
+	pixman_image_t *mask,
+        pixman_image_t *dest,
+        pixman_image_t *orig_dest,
+        int x, int y,
+        int width, int height,
+	pixman_bool_t component_alpha)
+{
+    pixel_checker_t dest_checker, src_checker, mask_checker;
+    int i, j;
+
+    pixel_checker_init (&src_checker, source->bits.format);
+    pixel_checker_init (&dest_checker, dest->bits.format);
+    pixel_checker_init (&mask_checker, mask->bits.format);
+
+    assert (dest->bits.format == orig_dest->bits.format);
+
+    for (j = y; j < y + height; ++j)
+    {
+        for (i = x; i < x + width; ++i)
+        {
+            color_t src_color, mask_color, orig_dest_color, result;
+            uint32_t dest_pixel, orig_dest_pixel, src_pixel, mask_pixel;
+
+            access (dest, i, j, &dest_pixel);
+
+	    get_color (&src_checker,
+		       source, i - x, j - y,
+		       &src_color, &src_pixel);
+
+	    get_color (&mask_checker,
+		       mask, i - x, j - y,
+		       &mask_color, &mask_pixel);
+
+	    get_color (&dest_checker, 
+		       orig_dest, i, j,
+		       &orig_dest_color, &orig_dest_pixel);
+
+	    do_composite (op, 
+			  &src_color, &mask_color, &orig_dest_color,
+			  &result, component_alpha);
+
+            if (!pixel_checker_check (&dest_checker, dest_pixel, &result))
+            {
+                int a, r, g, b;
+
+                printf ("--------- Test 0x%x failed ---------\n", test_no);
+                
+                printf ("   operator:         %s (%s alpha)\n", operator_name (op),
+			component_alpha? "component" : "unified");
+                printf ("   dest_x, dest_y:   %d %d\n", x, y);
+                printf ("   width, height:    %d %d\n", width, height);
+                printf ("   source:           format: %-14s  size: %2d x %2d\n",
+                        format_name (source->bits.format),
+			source->bits.width, source->bits.height);
+                printf ("   mask:             format: %-14s  size: %2d x %2d\n",
+                        format_name (mask->bits.format),
+			mask->bits.width, mask->bits.height);
+                printf ("   dest:             format: %-14s  size: %2d x %2d\n",
+                        format_name (dest->bits.format),
+			dest->bits.width, dest->bits.height);
+                printf ("   -- Failed pixel: (%d, %d) --\n", i, j);
+                printf ("   source ARGB:      %f  %f  %f  %f   (pixel: %x)\n",
+                        src_color.a, src_color.r, src_color.g, src_color.b,
+                        src_pixel);
+                printf ("   mask ARGB:        %f  %f  %f  %f   (pixel: %x)\n",
+                        mask_color.a, mask_color.r, mask_color.g, mask_color.b,
+                        mask_pixel);
+                printf ("   dest ARGB:        %f  %f  %f  %f   (pixel: %x)\n",
+                        orig_dest_color.a, orig_dest_color.r, orig_dest_color.g, orig_dest_color.b,
+                        orig_dest_pixel);
+                printf ("   expected ARGB:    %f  %f  %f  %f\n",
+                        result.a, result.r, result.g, result.b);
+
+                pixel_checker_get_min (&dest_checker, &result, &a, &r, &g, &b);
+                printf ("   min acceptable:   %8d  %8d  %8d  %8d\n", a, r, g, b);
+
+                pixel_checker_split_pixel (&dest_checker, dest_pixel, &a, &r, &g, &b);
+                printf ("   got:              %8d  %8d  %8d  %8d   (pixel: %x)\n", a, r, g, b, dest_pixel);
+                
+                pixel_checker_get_max (&dest_checker, &result, &a, &r, &g, &b);
+                printf ("   max acceptable:   %8d  %8d  %8d  %8d\n", a, r, g, b);
+		printf ("\n");
+		printf ("    { %s,\n", operator_name (op));
+		printf ("      PIXMAN_%s,\t0x%x,\n", format_name (source->bits.format), src_pixel);
+		printf ("      PIXMAN_%s,\t0x%x,\n", format_name (mask->bits.format), mask_pixel);
+		printf ("      PIXMAN_%s,\t0x%x\n", format_name (dest->bits.format), orig_dest_pixel);
+		printf ("    },\n");
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+static pixman_bool_t
+do_check (int i)
+{
+    pixman_image_t *source, *dest, *mask;
+    pixman_op_t op;
+    int x, y, width, height;
+    pixman_image_t *dest_copy;
+    pixman_bool_t result = TRUE;
+    pixman_bool_t component_alpha;
+
+    prng_srand (i);
+    op = RANDOM_ELT (operators);
+    x = prng_rand_n (MAX_WIDTH);
+    y = prng_rand_n (MAX_HEIGHT);
+    width = prng_rand_n (MAX_WIDTH) + 4;
+    height = prng_rand_n (MAX_HEIGHT) + 4;
+
+    source = create_image (NULL);
+    mask = create_image (NULL);
+    dest = create_image (&dest_copy);
+
+    if (x >= dest->bits.width)
+        x = dest->bits.width / 2;
+    if (y >= dest->bits.height)
+        y = dest->bits.height / 2;
+    if (x + width > dest->bits.width)
+        width = dest->bits.width - x;
+    if (y + height > dest->bits.height)
+        height = dest->bits.height - y;
+
+    component_alpha = prng_rand_n (2);
+
+    pixman_image_set_component_alpha (mask, component_alpha);
+    
+    pixman_image_composite32 (op, source, mask, dest,
+                              0, 0, 0, 0,
+                              x, y, width, height);
+
+    if (!verify (i, op, source, mask, dest, dest_copy,
+		 x, y, width, height, component_alpha))
+    {
+	result = FALSE;
+    }
+    
+    pixman_image_unref (source);
+    pixman_image_unref (mask);
+    pixman_image_unref (dest);
+    pixman_image_unref (dest_copy);
+
+    return result;
+}
+
+#define N_TESTS    10000000
+
+int
+main (int argc, const char *argv[])
+{
+    int i;
+    int result = 0;
+
+    if (argc == 2)
+    {
+	if (strcmp (argv[1], "--forever") == 0)
+	{
+	    uint32_t n;
+
+	    prng_srand (time (0));
+
+	    n = prng_rand();
+
+	    for (;;)
+		do_check (n++);
+	}
+        else
+	{
+	    do_check (strtol (argv[1], NULL, 0));
+	}
+    }
+    else
+    {
+#ifdef USE_OPENMP
+#       pragma omp parallel for default(none) shared(i) private (result)
+#endif
+        for (i = 0; i < N_TESTS; ++i)
+	{
+	    if (!do_check (i))
+		result = 1;
+	}
+    }
+    
+    return result;
+}
commit c2fd65dba35027a52696f497d414194514519d0f
Author: Søren Sandmann <ssp at redhat.com>
Date:   Wed Dec 4 10:32:29 2013 -0500

    pixel-test: Command line argument to specify the regression to run
    
    A new command line argument allows the user to specify which one of
    the regressions should be run.

diff --git a/test/pixel-test.c b/test/pixel-test.c
index 1ff4d8c..9d2831d 100644
--- a/test/pixel-test.c
+++ b/test/pixel-test.c
@@ -302,8 +302,20 @@ main (int argc, char **argv)
 {
     int result = 0;
     int i, j;
+    int lo, hi;
 
-    for (i = 0; i < ARRAY_LENGTH (regressions); ++i)
+    if (argc > 1)
+    {
+	lo = atoi (argv[1]);
+	hi = lo + 1;
+    }
+    else
+    {
+	lo = 0;
+	hi = ARRAY_LENGTH (regressions);
+    }
+
+    for (i = lo; i < hi; ++i)
     {
 	const pixel_combination_t *combination = &(regressions[i]);
 
commit a692e0160081ff509b40a18f6e73240bd6ef9f11
Author: Søren Sandmann <ssp at redhat.com>
Date:   Wed Dec 4 10:05:44 2013 -0500

    pixel-test: Add support for mask pixels
    
    Support is added to pixel-test for verifying operations involving
    masks. If a regression includes a mask, it is verified with the
    pixel_checker API in in both unified and component alpha modes.

diff --git a/test/pixel-test.c b/test/pixel-test.c
index 8c525d2..1ff4d8c 100644
--- a/test/pixel-test.c
+++ b/test/pixel-test.c
@@ -33,6 +33,8 @@ struct pixel_combination_t
     pixman_op_t			op;
     pixman_format_code_t	src_format;
     uint32_t			src_pixel;
+    pixman_format_code_t	mask_format;
+    uint32_t			mask_pixel;
     pixman_format_code_t	dest_format;
     uint32_t			dest_pixel;
 };
@@ -41,58 +43,72 @@ static const pixel_combination_t regressions[] =
 {
     { PIXMAN_OP_OVER,
       PIXMAN_a8r8g8b8,	0x0f00c300,
+      PIXMAN_null,	0x00,
       PIXMAN_x14r6g6b6,	0x003c0,
     },
     { PIXMAN_OP_DISJOINT_XOR,
       PIXMAN_a4r4g4b4,	0xd0c0,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x5300ea00,
     },
     { PIXMAN_OP_OVER,
       PIXMAN_a8r8g8b8,	0x20c6bf00,
+      PIXMAN_null,	0x00,
       PIXMAN_r5g6b5,	0xb9ff
     },
     { PIXMAN_OP_OVER,
       PIXMAN_a8r8g8b8,	0x204ac7ff,
+      PIXMAN_null,	0x00,
       PIXMAN_r5g6b5,	0xc1ff
     },
     { PIXMAN_OP_OVER_REVERSE,
       PIXMAN_r5g6b5,	0xffc3,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x102d00dd
     },
     { PIXMAN_OP_OVER_REVERSE,
       PIXMAN_r5g6b5,	0x1f00,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x1bdf0c89
     },
     { PIXMAN_OP_OVER_REVERSE,
       PIXMAN_r5g6b5,	0xf9d2,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x1076bcf7
     },
     { PIXMAN_OP_OVER_REVERSE,
       PIXMAN_r5g6b5,	0x00c3,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x1bfe9ae5
     },
     { PIXMAN_OP_OVER_REVERSE,
       PIXMAN_r5g6b5,	0x09ff,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x0b00c16c
     },
     { PIXMAN_OP_DISJOINT_ATOP,
       PIXMAN_a2r2g2b2,	0xbc,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x9efff1ff
     },
     { PIXMAN_OP_DISJOINT_ATOP,
       PIXMAN_a4r4g4b4,	0xae5f,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0xf215b675
     },
     { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
       PIXMAN_a8r8g8b8,	0xce007980,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x80ffe4ad
     },
     { PIXMAN_OP_DISJOINT_XOR,
       PIXMAN_a8r8g8b8,	0xb8b07bea,
+      PIXMAN_null,	0x00,
       PIXMAN_a4r4g4b4,	0x939c
     },
     { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
       PIXMAN_r5g6b5,	0x0063,
+      PIXMAN_null,	0x00,
       PIXMAN_a8r8g8b8,	0x10bb1ed7,
     },
 };
@@ -159,35 +175,59 @@ access (pixman_image_t *image, int x, int y)
 }
 
 static pixman_bool_t
-verify (int test_no, const pixel_combination_t *combination, int size)
+verify (int test_no, const pixel_combination_t *combination, int size,
+	pixman_bool_t component_alpha)
 {
-    pixman_image_t *src, *dest;
-    pixel_checker_t src_checker, dest_checker;
-    color_t source_color, dest_color, reference_color;
+    pixman_image_t *src, *mask, *dest;
+    pixel_checker_t src_checker, mask_checker, dest_checker;
+    color_t source_color, mask_color, dest_color, reference_color;
+    pixman_bool_t have_mask = (combination->mask_format != PIXMAN_null);
     pixman_bool_t result = TRUE;
     int i, j;
 
     /* Compute reference color */
     pixel_checker_init (&src_checker, combination->src_format);
+    if (have_mask)
+	pixel_checker_init (&mask_checker, combination->mask_format);
     pixel_checker_init (&dest_checker, combination->dest_format);
+
     pixel_checker_convert_pixel_to_color (
 	&src_checker, combination->src_pixel, &source_color);
+    if (combination->mask_format != PIXMAN_null)
+    {
+	pixel_checker_convert_pixel_to_color (
+	    &mask_checker, combination->mask_pixel, &mask_color);
+    }
     pixel_checker_convert_pixel_to_color (
 	&dest_checker, combination->dest_pixel, &dest_color);
+
     do_composite (combination->op,
-		  &source_color, NULL, &dest_color,
-		  &reference_color, FALSE);
+		  &source_color,
+		  have_mask? &mask_color : NULL,
+		  &dest_color,
+		  &reference_color, component_alpha);
 
     src = pixman_image_create_bits (
 	combination->src_format, size, size, NULL, -1);
+    if (have_mask)
+    {
+	mask = pixman_image_create_bits (
+	    combination->mask_format, size, size, NULL, -1);
+
+	pixman_image_set_component_alpha (mask, component_alpha);
+    }
     dest = pixman_image_create_bits (
 	combination->dest_format, size, size, NULL, -1);
 
     fill (src, combination->src_pixel);
+    if (have_mask)
+	fill (mask, combination->mask_pixel);
     fill (dest, combination->dest_pixel);
 
     pixman_image_composite32 (
-	combination->op, src, NULL, dest, 0, 0, 0, 0, 0, 0, size, size);
+	combination->op, src, 
+	have_mask ? mask : NULL,
+	dest, 0, 0, 0, 0, 0, 0, size, size);
 
     for (j = 0; j < size; ++j)
     {
@@ -200,9 +240,13 @@ verify (int test_no, const pixel_combination_t *combination, int size)
 	    {
 		printf ("----------- Test %d failed ----------\n", test_no);
 
-		printf ("   operator:         %s\n", operator_name (combination->op));
+		printf ("   operator:         %s (%s)\n", operator_name (combination->op),
+			have_mask? component_alpha ? "component alpha" : "unified alpha" : "no mask");
 		printf ("   src format:       %s\n", format_name (combination->src_format));
+		if (have_mask != PIXMAN_null)
+		    printf ("   mask format:      %s\n", format_name (combination->mask_format));
 		printf ("   dest format:      %s\n", format_name (combination->dest_format));
+
                 printf (" - source ARGB:      %f  %f  %f  %f   (pixel: %8x)\n",
                         source_color.a, source_color.r, source_color.g, source_color.b,
                         combination->src_pixel);
@@ -210,6 +254,16 @@ verify (int test_no, const pixel_combination_t *combination, int size)
 					   &a, &r, &g, &b);
                 printf ("                     %8d  %8d  %8d  %8d\n", a, r, g, b);
 
+		if (have_mask)
+		{
+		    printf (" - mask ARGB:        %f  %f  %f  %f   (pixel: %8x)\n",
+			    mask_color.a, mask_color.r, mask_color.g, mask_color.b,
+			    combination->mask_pixel);
+		    pixel_checker_split_pixel (&mask_checker, combination->mask_pixel,
+					       &a, &r, &g, &b);
+		    printf ("                     %8d  %8d  %8d  %8d\n", a, r, g, b);
+		}
+
                 printf (" - dest ARGB:        %f  %f  %f  %f   (pixel: %8x)\n",
                         dest_color.a, dest_color.r, dest_color.g, dest_color.b,
                         combination->dest_pixel);
@@ -255,12 +309,22 @@ main (int argc, char **argv)
 
 	for (j = 1; j < 34; ++j)
 	{
-	    if (!verify (i, combination, j))
+	    int k, ca;
+
+	    ca = combination->mask_format == PIXMAN_null ? 1 : 2;
+
+	    for (k = 0; k < ca; ++k)
 	    {
-		result = 1;
-		break;
+		if (!verify (i, combination, j, k))
+		{
+		    result = 1;
+		    goto next_regression;
+		}
 	    }
 	}
+
+    next_regression:
+	;
     }
 
     return result;
commit 779ca46e985cd2523fae630227e397e88bd892d0
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Sep 30 19:22:11 2013 -0400

    test/check-formats.c: Add support for separable blend modes

diff --git a/test/check-formats.c b/test/check-formats.c
index 7edc198..8eb263b 100644
--- a/test/check-formats.c
+++ b/test/check-formats.c
@@ -146,6 +146,22 @@ static const pixman_op_t op_list[] =
     PIXMAN_OP_CONJOINT_ATOP,
     PIXMAN_OP_CONJOINT_ATOP_REVERSE,
     PIXMAN_OP_CONJOINT_XOR,
+
+    PIXMAN_OP_MULTIPLY,
+    PIXMAN_OP_SCREEN,
+    PIXMAN_OP_OVERLAY,
+    PIXMAN_OP_DARKEN,
+    PIXMAN_OP_LIGHTEN,
+    PIXMAN_OP_COLOR_DODGE,
+    PIXMAN_OP_COLOR_BURN,
+    PIXMAN_OP_HARD_LIGHT,
+    PIXMAN_OP_SOFT_LIGHT,
+    PIXMAN_OP_DIFFERENCE,
+    PIXMAN_OP_EXCLUSION,
+    PIXMAN_OP_HSL_HUE,
+    PIXMAN_OP_HSL_SATURATION,
+    PIXMAN_OP_HSL_COLOR,
+    PIXMAN_OP_HSL_LUMINOSITY
 };
 
 static const pixman_format_code_t format_list[] =
commit a42af27fc02f792b92fd2573e38eac82a71c76d2
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Jan 19 12:24:07 2013 -0500

    test/utils.c: Add support for separable blend mode ops to do_composite()
    
    The implementations are copied from the floating point pipeline, but
    use double precision instead of single precision.

diff --git a/test/utils.c b/test/utils.c
index ebe0ccc..c57ca64 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -4,6 +4,7 @@
 #include <math.h>
 #include <signal.h>
 #include <stdlib.h>
+#include <float.h>
 
 #ifdef HAVE_GETTIMEOFDAY
 #include <sys/time.h>
@@ -1099,6 +1100,152 @@ format_name (pixman_format_code_t format)
     return "<unknown format>";
 };
 
+#define IS_ZERO(f)     (-DBL_MIN < (f) && (f) < DBL_MIN)
+
+typedef double (* blend_func_t) (double as, double s, double ad, double d);
+
+static force_inline double
+blend_multiply (double sa, double s, double da, double d)
+{
+    return d * s;
+}
+
+static force_inline double
+blend_screen (double sa, double s, double da, double d)
+{
+    return d * sa + s * da - s * d;
+}
+
+static force_inline double
+blend_overlay (double sa, double s, double da, double d)
+{
+    if (2 * d < da)
+        return 2 * s * d;
+    else
+        return sa * da - 2 * (da - d) * (sa - s);
+}
+
+static force_inline double
+blend_darken (double sa, double s, double da, double d)
+{
+    s = s * da;
+    d = d * sa;
+
+    if (s > d)
+        return d;
+    else
+        return s;
+}
+
+static force_inline double
+blend_lighten (double sa, double s, double da, double d)
+{
+    s = s * da;
+    d = d * sa;
+
+    if (s > d)
+        return s;
+    else
+        return d;
+}
+
+static force_inline double
+blend_color_dodge (double sa, double s, double da, double d)
+{
+    if (IS_ZERO (d))
+        return 0.0f;
+    else if (d * sa >= sa * da - s * da)
+        return sa * da;
+    else if (IS_ZERO (sa - s))
+        return sa * da;
+    else
+        return sa * sa * d / (sa - s);
+}
+
+static force_inline double
+blend_color_burn (double sa, double s, double da, double d)
+{
+    if (d >= da)
+        return sa * da;
+    else if (sa * (da - d) >= s * da)
+        return 0.0f;
+    else if (IS_ZERO (s))
+        return 0.0f;
+    else
+        return sa * (da - sa * (da - d) / s);
+}
+
+static force_inline double
+blend_hard_light (double sa, double s, double da, double d)
+{
+    if (2 * s < sa)
+        return 2 * s * d;
+    else
+        return sa * da - 2 * (da - d) * (sa - s);
+}
+
+static force_inline double
+blend_soft_light (double sa, double s, double da, double d)
+{
+    if (2 * s <= sa)
+    {
+        if (IS_ZERO (da))
+            return d * sa;
+        else
+            return d * sa - d * (da - d) * (sa - 2 * s) / da;
+    }
+    else
+    {
+        if (IS_ZERO (da))
+        {
+            return 0.0f;
+        }
+        else
+        {
+            if (4 * d <= da)
+                return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
+            else
+                return d * sa + (sqrt (d * da) - d) * (2 * s - sa);
+        }
+    }
+}
+
+static force_inline double
+blend_difference (double sa, double s, double da, double d)
+{
+    double dsa = d * sa;
+    double sda = s * da;
+
+    if (sda < dsa)
+        return dsa - sda;
+    else
+        return sda - dsa;
+}
+
+static force_inline double
+blend_exclusion (double sa, double s, double da, double d)
+{
+    return s * da + d * sa - 2 * d * s;
+}
+
+static double
+clamp (double d)
+{
+    if (d > 1.0)
+	return 1.0;
+    else if (d < 0.0)
+	return 0.0;
+    else
+	return d;
+}
+
+static double
+blend_channel (double as, double s, double ad, double d,
+                   blend_func_t blend)
+{
+    return clamp ((1 - ad) * s + (1 - as) * d + blend (as, s, ad, d));
+}
+
 static double
 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
 {
@@ -1336,6 +1483,21 @@ do_composite (pixman_op_t op,
 {
     color_t srcval, srcalpha;
 
+    static const blend_func_t blend_funcs[] =
+    {
+        blend_multiply,
+        blend_screen,
+        blend_overlay,
+        blend_darken,
+        blend_lighten,
+        blend_color_dodge,
+        blend_color_burn,
+        blend_hard_light,
+        blend_soft_light,
+        blend_difference,
+        blend_exclusion,
+    };
+
     if (mask == NULL)
     {
 	srcval = *src;
@@ -1370,10 +1532,22 @@ do_composite (pixman_op_t op,
 	srcalpha.a = src->a * mask->a;
     }
 
-    result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
-    result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
-    result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
-    result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
+    if (op >= PIXMAN_OP_MULTIPLY)
+    {
+        blend_func_t func = blend_funcs[op - PIXMAN_OP_MULTIPLY];
+
+	result->a = srcalpha.a + dst->a - srcalpha.a * dst->a;
+	result->r = blend_channel (srcalpha.r, srcval.r, dst->a, dst->r, func);
+	result->g = blend_channel (srcalpha.g, srcval.g, dst->a, dst->g, func);
+	result->b = blend_channel (srcalpha.b, srcval.b, dst->a, dst->b, func);
+    }
+    else
+    {
+        result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
+        result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
+        result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
+        result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
+    }
 }
 
 static double


More information about the xorg-commit mailing list