Home | History | Annotate | Download | only in pixman
      1 /*
      2  * Copyright  2000 Keith Packard, member of The XFree86 Project, Inc.
      3  *             2005 Lars Knoll & Zack Rusin, Trolltech
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software and its
      6  * documentation for any purpose is hereby granted without fee, provided that
      7  * the above copyright notice appear in all copies and that both that
      8  * copyright notice and this permission notice appear in supporting
      9  * documentation, and that the name of Keith Packard not be used in
     10  * advertising or publicity pertaining to distribution of the software without
     11  * specific, written prior permission.  Keith Packard makes no
     12  * representations about the suitability of this software for any purpose.  It
     13  * is provided "as is" without express or implied warranty.
     14  *
     15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
     16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
     17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     20  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     21  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     22  * SOFTWARE.
     23  */
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <math.h>
     29 #include <string.h>
     30 
     31 #include "pixman-private.h"
     32 #include "pixman-combine32.h"
     33 
     34 /* component alpha helper functions */
     35 
     36 static void
     37 combine_mask_ca (uint32_t *src, uint32_t *mask)
     38 {
     39     uint32_t a = *mask;
     40 
     41     uint32_t x;
     42     uint16_t xa;
     43 
     44     if (!a)
     45     {
     46 	*(src) = 0;
     47 	return;
     48     }
     49 
     50     x = *(src);
     51     if (a == ~0)
     52     {
     53 	x = x >> A_SHIFT;
     54 	x |= x << G_SHIFT;
     55 	x |= x << R_SHIFT;
     56 	*(mask) = x;
     57 	return;
     58     }
     59 
     60     xa = x >> A_SHIFT;
     61     UN8x4_MUL_UN8x4 (x, a);
     62     *(src) = x;
     63 
     64     UN8x4_MUL_UN8 (a, xa);
     65     *(mask) = a;
     66 }
     67 
     68 static void
     69 combine_mask_value_ca (uint32_t *src, const uint32_t *mask)
     70 {
     71     uint32_t a = *mask;
     72     uint32_t x;
     73 
     74     if (!a)
     75     {
     76 	*(src) = 0;
     77 	return;
     78     }
     79 
     80     if (a == ~0)
     81 	return;
     82 
     83     x = *(src);
     84     UN8x4_MUL_UN8x4 (x, a);
     85     *(src) = x;
     86 }
     87 
     88 static void
     89 combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask)
     90 {
     91     uint32_t a = *(mask);
     92     uint32_t x;
     93 
     94     if (!a)
     95 	return;
     96 
     97     x = *(src) >> A_SHIFT;
     98     if (x == MASK)
     99 	return;
    100 
    101     if (a == ~0)
    102     {
    103 	x |= x << G_SHIFT;
    104 	x |= x << R_SHIFT;
    105 	*(mask) = x;
    106 	return;
    107     }
    108 
    109     UN8x4_MUL_UN8 (a, x);
    110     *(mask) = a;
    111 }
    112 
    113 /*
    114  * There are two ways of handling alpha -- either as a single unified value or
    115  * a separate value for each component, hence each macro must have two
    116  * versions.  The unified alpha version has a 'u' at the end of the name,
    117  * the component version has a 'ca'.  Similarly, functions which deal with
    118  * this difference will have two versions using the same convention.
    119  */
    120 
    121 static force_inline uint32_t
    122 combine_mask (const uint32_t *src, const uint32_t *mask, int i)
    123 {
    124     uint32_t s, m;
    125 
    126     if (mask)
    127     {
    128 	m = *(mask + i) >> A_SHIFT;
    129 
    130 	if (!m)
    131 	    return 0;
    132     }
    133 
    134     s = *(src + i);
    135 
    136     if (mask)
    137 	UN8x4_MUL_UN8 (s, m);
    138 
    139     return s;
    140 }
    141 
    142 static void
    143 combine_clear (pixman_implementation_t *imp,
    144                pixman_op_t              op,
    145                uint32_t *                dest,
    146                const uint32_t *          src,
    147                const uint32_t *          mask,
    148                int                      width)
    149 {
    150     memset (dest, 0, width * sizeof(uint32_t));
    151 }
    152 
    153 static void
    154 combine_dst (pixman_implementation_t *imp,
    155 	     pixman_op_t	      op,
    156 	     uint32_t *		      dest,
    157 	     const uint32_t *	      src,
    158 	     const uint32_t *          mask,
    159 	     int		      width)
    160 {
    161     return;
    162 }
    163 
    164 static void
    165 combine_src_u (pixman_implementation_t *imp,
    166                pixman_op_t              op,
    167                uint32_t *                dest,
    168                const uint32_t *          src,
    169                const uint32_t *          mask,
    170                int                      width)
    171 {
    172     int i;
    173 
    174     if (!mask)
    175     {
    176 	memcpy (dest, src, width * sizeof (uint32_t));
    177     }
    178     else
    179     {
    180 	for (i = 0; i < width; ++i)
    181 	{
    182 	    uint32_t s = combine_mask (src, mask, i);
    183 
    184 	    *(dest + i) = s;
    185 	}
    186     }
    187 }
    188 
    189 static void
    190 combine_over_u (pixman_implementation_t *imp,
    191                 pixman_op_t              op,
    192                 uint32_t *                dest,
    193                 const uint32_t *          src,
    194                 const uint32_t *          mask,
    195                 int                      width)
    196 {
    197     int i;
    198 
    199     if (!mask)
    200     {
    201 	for (i = 0; i < width; ++i)
    202 	{
    203 	    uint32_t s = *(src + i);
    204 	    uint32_t a = ALPHA_8 (s);
    205 	    if (a == 0xFF)
    206 	    {
    207 		*(dest + i) = s;
    208 	    }
    209 	    else if (s)
    210 	    {
    211 		uint32_t d = *(dest + i);
    212 		uint32_t ia = a ^ 0xFF;
    213 		UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
    214 		*(dest + i) = d;
    215 	    }
    216 	}
    217     }
    218     else
    219     {
    220 	for (i = 0; i < width; ++i)
    221 	{
    222 	    uint32_t m = ALPHA_8 (*(mask + i));
    223 	    if (m == 0xFF)
    224 	    {
    225 		uint32_t s = *(src + i);
    226 		uint32_t a = ALPHA_8 (s);
    227 		if (a == 0xFF)
    228 		{
    229 		    *(dest + i) = s;
    230 		}
    231 		else if (s)
    232 		{
    233 		    uint32_t d = *(dest + i);
    234 		    uint32_t ia = a ^ 0xFF;
    235 		    UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
    236 		    *(dest + i) = d;
    237 		}
    238 	    }
    239 	    else if (m)
    240 	    {
    241 		uint32_t s = *(src + i);
    242 		if (s)
    243 		{
    244 		    uint32_t d = *(dest + i);
    245 		    UN8x4_MUL_UN8 (s, m);
    246 		    UN8x4_MUL_UN8_ADD_UN8x4 (d, ALPHA_8 (~s), s);
    247 		    *(dest + i) = d;
    248 		}
    249 	    }
    250 	}
    251     }
    252 }
    253 
    254 static void
    255 combine_over_reverse_u (pixman_implementation_t *imp,
    256                         pixman_op_t              op,
    257                         uint32_t *                dest,
    258                         const uint32_t *          src,
    259                         const uint32_t *          mask,
    260                         int                      width)
    261 {
    262     int i;
    263 
    264     for (i = 0; i < width; ++i)
    265     {
    266 	uint32_t s = combine_mask (src, mask, i);
    267 	uint32_t d = *(dest + i);
    268 	uint32_t ia = ALPHA_8 (~*(dest + i));
    269 	UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
    270 	*(dest + i) = s;
    271     }
    272 }
    273 
    274 static void
    275 combine_in_u (pixman_implementation_t *imp,
    276               pixman_op_t              op,
    277               uint32_t *                dest,
    278               const uint32_t *          src,
    279               const uint32_t *          mask,
    280               int                      width)
    281 {
    282     int i;
    283 
    284     for (i = 0; i < width; ++i)
    285     {
    286 	uint32_t s = combine_mask (src, mask, i);
    287 	uint32_t a = ALPHA_8 (*(dest + i));
    288 	UN8x4_MUL_UN8 (s, a);
    289 	*(dest + i) = s;
    290     }
    291 }
    292 
    293 static void
    294 combine_in_reverse_u (pixman_implementation_t *imp,
    295                       pixman_op_t              op,
    296                       uint32_t *                dest,
    297                       const uint32_t *          src,
    298                       const uint32_t *          mask,
    299                       int                      width)
    300 {
    301     int i;
    302 
    303     for (i = 0; i < width; ++i)
    304     {
    305 	uint32_t s = combine_mask (src, mask, i);
    306 	uint32_t d = *(dest + i);
    307 	uint32_t a = ALPHA_8 (s);
    308 	UN8x4_MUL_UN8 (d, a);
    309 	*(dest + i) = d;
    310     }
    311 }
    312 
    313 static void
    314 combine_out_u (pixman_implementation_t *imp,
    315                pixman_op_t              op,
    316                uint32_t *                dest,
    317                const uint32_t *          src,
    318                const uint32_t *          mask,
    319                int                      width)
    320 {
    321     int i;
    322 
    323     for (i = 0; i < width; ++i)
    324     {
    325 	uint32_t s = combine_mask (src, mask, i);
    326 	uint32_t a = ALPHA_8 (~*(dest + i));
    327 	UN8x4_MUL_UN8 (s, a);
    328 	*(dest + i) = s;
    329     }
    330 }
    331 
    332 static void
    333 combine_out_reverse_u (pixman_implementation_t *imp,
    334                        pixman_op_t              op,
    335                        uint32_t *                dest,
    336                        const uint32_t *          src,
    337                        const uint32_t *          mask,
    338                        int                      width)
    339 {
    340     int i;
    341 
    342     for (i = 0; i < width; ++i)
    343     {
    344 	uint32_t s = combine_mask (src, mask, i);
    345 	uint32_t d = *(dest + i);
    346 	uint32_t a = ALPHA_8 (~s);
    347 	UN8x4_MUL_UN8 (d, a);
    348 	*(dest + i) = d;
    349     }
    350 }
    351 
    352 static void
    353 combine_atop_u (pixman_implementation_t *imp,
    354                 pixman_op_t              op,
    355                 uint32_t *                dest,
    356                 const uint32_t *          src,
    357                 const uint32_t *          mask,
    358                 int                      width)
    359 {
    360     int i;
    361 
    362     for (i = 0; i < width; ++i)
    363     {
    364 	uint32_t s = combine_mask (src, mask, i);
    365 	uint32_t d = *(dest + i);
    366 	uint32_t dest_a = ALPHA_8 (d);
    367 	uint32_t src_ia = ALPHA_8 (~s);
    368 
    369 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
    370 	*(dest + i) = s;
    371     }
    372 }
    373 
    374 static void
    375 combine_atop_reverse_u (pixman_implementation_t *imp,
    376                         pixman_op_t              op,
    377                         uint32_t *                dest,
    378                         const uint32_t *          src,
    379                         const uint32_t *          mask,
    380                         int                      width)
    381 {
    382     int i;
    383 
    384     for (i = 0; i < width; ++i)
    385     {
    386 	uint32_t s = combine_mask (src, mask, i);
    387 	uint32_t d = *(dest + i);
    388 	uint32_t src_a = ALPHA_8 (s);
    389 	uint32_t dest_ia = ALPHA_8 (~d);
    390 
    391 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
    392 	*(dest + i) = s;
    393     }
    394 }
    395 
    396 static void
    397 combine_xor_u (pixman_implementation_t *imp,
    398                pixman_op_t              op,
    399                uint32_t *                dest,
    400                const uint32_t *          src,
    401                const uint32_t *          mask,
    402                int                      width)
    403 {
    404     int i;
    405 
    406     for (i = 0; i < width; ++i)
    407     {
    408 	uint32_t s = combine_mask (src, mask, i);
    409 	uint32_t d = *(dest + i);
    410 	uint32_t src_ia = ALPHA_8 (~s);
    411 	uint32_t dest_ia = ALPHA_8 (~d);
    412 
    413 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
    414 	*(dest + i) = s;
    415     }
    416 }
    417 
    418 static void
    419 combine_add_u (pixman_implementation_t *imp,
    420                pixman_op_t              op,
    421                uint32_t *                dest,
    422                const uint32_t *          src,
    423                const uint32_t *          mask,
    424                int                      width)
    425 {
    426     int i;
    427 
    428     for (i = 0; i < width; ++i)
    429     {
    430 	uint32_t s = combine_mask (src, mask, i);
    431 	uint32_t d = *(dest + i);
    432 	UN8x4_ADD_UN8x4 (d, s);
    433 	*(dest + i) = d;
    434     }
    435 }
    436 
    437 static void
    438 combine_saturate_u (pixman_implementation_t *imp,
    439                     pixman_op_t              op,
    440                     uint32_t *                dest,
    441                     const uint32_t *          src,
    442                     const uint32_t *          mask,
    443                     int                      width)
    444 {
    445     int i;
    446 
    447     for (i = 0; i < width; ++i)
    448     {
    449 	uint32_t s = combine_mask (src, mask, i);
    450 	uint32_t d = *(dest + i);
    451 	uint16_t sa, da;
    452 
    453 	sa = s >> A_SHIFT;
    454 	da = ~d >> A_SHIFT;
    455 	if (sa > da)
    456 	{
    457 	    sa = DIV_UN8 (da, sa);
    458 	    UN8x4_MUL_UN8 (s, sa);
    459 	}
    460 	;
    461 	UN8x4_ADD_UN8x4 (d, s);
    462 	*(dest + i) = d;
    463     }
    464 }
    465 
    466 /*
    467  * PDF blend modes:
    468  * The following blend modes have been taken from the PDF ISO 32000
    469  * specification, which at this point in time is available from
    470  * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
    471  * The relevant chapters are 11.3.5 and 11.3.6.
    472  * The formula for computing the final pixel color given in 11.3.6 is:
    473  * r  Cr = (1  s)  b  Cb + (1  b)  s  Cs + b  s  B(Cb, Cs)
    474  * with B() being the blend function.
    475  * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
    476  *
    477  * These blend modes should match the SVG filter draft specification, as
    478  * it has been designed to mirror ISO 32000. Note that at the current point
    479  * no released draft exists that shows this, as the formulas have not been
    480  * updated yet after the release of ISO 32000.
    481  *
    482  * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
    483  * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
    484  * argument. Note that this implementation operates on premultiplied colors,
    485  * while the PDF specification does not. Therefore the code uses the formula
    486  * Cra = (1  as) . Dca + (1  ad) . Sca + B(Dca, ad, Sca, as)
    487  */
    488 
    489 /*
    490  * Multiply
    491  * B(Dca, ad, Sca, as) = Dca.Sca
    492  */
    493 static void
    494 combine_multiply_u (pixman_implementation_t *imp,
    495                     pixman_op_t              op,
    496                     uint32_t *                dest,
    497                     const uint32_t *          src,
    498                     const uint32_t *          mask,
    499                     int                      width)
    500 {
    501     int i;
    502 
    503     for (i = 0; i < width; ++i)
    504     {
    505 	uint32_t s = combine_mask (src, mask, i);
    506 	uint32_t d = *(dest + i);
    507 	uint32_t ss = s;
    508 	uint32_t src_ia = ALPHA_8 (~s);
    509 	uint32_t dest_ia = ALPHA_8 (~d);
    510 
    511 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (ss, dest_ia, d, src_ia);
    512 	UN8x4_MUL_UN8x4 (d, s);
    513 	UN8x4_ADD_UN8x4 (d, ss);
    514 
    515 	*(dest + i) = d;
    516     }
    517 }
    518 
    519 static void
    520 combine_multiply_ca (pixman_implementation_t *imp,
    521                      pixman_op_t              op,
    522                      uint32_t *                dest,
    523                      const uint32_t *          src,
    524                      const uint32_t *          mask,
    525                      int                      width)
    526 {
    527     int i;
    528 
    529     for (i = 0; i < width; ++i)
    530     {
    531 	uint32_t m = *(mask + i);
    532 	uint32_t s = *(src + i);
    533 	uint32_t d = *(dest + i);
    534 	uint32_t r = d;
    535 	uint32_t dest_ia = ALPHA_8 (~d);
    536 
    537 	combine_mask_ca (&s, &m);
    538 
    539 	UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia);
    540 	UN8x4_MUL_UN8x4 (d, s);
    541 	UN8x4_ADD_UN8x4 (r, d);
    542 
    543 	*(dest + i) = r;
    544     }
    545 }
    546 
    547 #define PDF_SEPARABLE_BLEND_MODE(name)					\
    548     static void								\
    549     combine_ ## name ## _u (pixman_implementation_t *imp,		\
    550 			    pixman_op_t              op,		\
    551                             uint32_t *                dest,		\
    552 			    const uint32_t *          src,		\
    553 			    const uint32_t *          mask,		\
    554 			    int                      width)		\
    555     {									\
    556 	int i;								\
    557 	for (i = 0; i < width; ++i) {					\
    558 	    uint32_t s = combine_mask (src, mask, i);			\
    559 	    uint32_t d = *(dest + i);					\
    560 	    uint8_t sa = ALPHA_8 (s);					\
    561 	    uint8_t isa = ~sa;						\
    562 	    uint8_t da = ALPHA_8 (d);					\
    563 	    uint8_t ida = ~da;						\
    564 	    uint32_t result;						\
    565 									\
    566 	    result = d;							\
    567 	    UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida);	\
    568 	    								\
    569 	    *(dest + i) = result +					\
    570 		(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) +		\
    571 		(blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \
    572 		(blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \
    573 		(blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa));	\
    574 	}								\
    575     }									\
    576     									\
    577     static void								\
    578     combine_ ## name ## _ca (pixman_implementation_t *imp,		\
    579 			     pixman_op_t              op,		\
    580                              uint32_t *                dest,		\
    581 			     const uint32_t *          src,		\
    582 			     const uint32_t *          mask,		\
    583 			     int                     width)		\
    584     {									\
    585 	int i;								\
    586 	for (i = 0; i < width; ++i) {					\
    587 	    uint32_t m = *(mask + i);					\
    588 	    uint32_t s = *(src + i);					\
    589 	    uint32_t d = *(dest + i);					\
    590 	    uint8_t da = ALPHA_8 (d);					\
    591 	    uint8_t ida = ~da;						\
    592 	    uint32_t result;						\
    593             								\
    594 	    combine_mask_ca (&s, &m);					\
    595             								\
    596 	    result = d;							\
    597 	    UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida);     \
    598             								\
    599 	    result +=							\
    600 	        (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) +	\
    601 	        (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \
    602 	        (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \
    603 	        (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \
    604 	    								\
    605 	    *(dest + i) = result;					\
    606 	}								\
    607     }
    608 
    609 /*
    610  * Screen
    611  * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
    612  */
    613 static inline uint32_t
    614 blend_screen (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    615 {
    616     return DIV_ONE_UN8 (sca * da + dca * sa - sca * dca);
    617 }
    618 
    619 PDF_SEPARABLE_BLEND_MODE (screen)
    620 
    621 /*
    622  * Overlay
    623  * B(Dca, Da, Sca, Sa) =
    624  *   if 2.Dca < Da
    625  *     2.Sca.Dca
    626  *   otherwise
    627  *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
    628  */
    629 static inline uint32_t
    630 blend_overlay (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    631 {
    632     uint32_t rca;
    633 
    634     if (2 * dca < da)
    635 	rca = 2 * sca * dca;
    636     else
    637 	rca = sa * da - 2 * (da - dca) * (sa - sca);
    638     return DIV_ONE_UN8 (rca);
    639 }
    640 
    641 PDF_SEPARABLE_BLEND_MODE (overlay)
    642 
    643 /*
    644  * Darken
    645  * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
    646  */
    647 static inline uint32_t
    648 blend_darken (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    649 {
    650     uint32_t s, d;
    651 
    652     s = sca * da;
    653     d = dca * sa;
    654     return DIV_ONE_UN8 (s > d ? d : s);
    655 }
    656 
    657 PDF_SEPARABLE_BLEND_MODE (darken)
    658 
    659 /*
    660  * Lighten
    661  * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
    662  */
    663 static inline uint32_t
    664 blend_lighten (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    665 {
    666     uint32_t s, d;
    667 
    668     s = sca * da;
    669     d = dca * sa;
    670     return DIV_ONE_UN8 (s > d ? s : d);
    671 }
    672 
    673 PDF_SEPARABLE_BLEND_MODE (lighten)
    674 
    675 /*
    676  * Color dodge
    677  * B(Dca, Da, Sca, Sa) =
    678  *   if Dca == 0
    679  *     0
    680  *   if Sca == Sa
    681  *     Sa.Da
    682  *   otherwise
    683  *     Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
    684  */
    685 static inline uint32_t
    686 blend_color_dodge (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    687 {
    688     if (sca >= sa)
    689     {
    690 	return dca == 0 ? 0 : DIV_ONE_UN8 (sa * da);
    691     }
    692     else
    693     {
    694 	uint32_t rca = dca * sa / (sa - sca);
    695 	return DIV_ONE_UN8 (sa * MIN (rca, da));
    696     }
    697 }
    698 
    699 PDF_SEPARABLE_BLEND_MODE (color_dodge)
    700 
    701 /*
    702  * Color burn
    703  * B(Dca, Da, Sca, Sa) =
    704  *   if Dca == Da
    705  *     Sa.Da
    706  *   if Sca == 0
    707  *     0
    708  *   otherwise
    709  *     Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
    710  */
    711 static inline uint32_t
    712 blend_color_burn (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    713 {
    714     if (sca == 0)
    715     {
    716 	return dca < da ? 0 : DIV_ONE_UN8 (sa * da);
    717     }
    718     else
    719     {
    720 	uint32_t rca = (da - dca) * sa / sca;
    721 	return DIV_ONE_UN8 (sa * (MAX (rca, da) - rca));
    722     }
    723 }
    724 
    725 PDF_SEPARABLE_BLEND_MODE (color_burn)
    726 
    727 /*
    728  * Hard light
    729  * B(Dca, Da, Sca, Sa) =
    730  *   if 2.Sca < Sa
    731  *     2.Sca.Dca
    732  *   otherwise
    733  *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
    734  */
    735 static inline uint32_t
    736 blend_hard_light (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    737 {
    738     if (2 * sca < sa)
    739 	return DIV_ONE_UN8 (2 * sca * dca);
    740     else
    741 	return DIV_ONE_UN8 (sa * da - 2 * (da - dca) * (sa - sca));
    742 }
    743 
    744 PDF_SEPARABLE_BLEND_MODE (hard_light)
    745 
    746 /*
    747  * Soft light
    748  * B(Dca, Da, Sca, Sa) =
    749  *   if (2.Sca <= Sa)
    750  *     Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
    751  *   otherwise if Dca.4 <= Da
    752  *     Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
    753  *   otherwise
    754  *     (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
    755  */
    756 static inline uint32_t
    757 blend_soft_light (uint32_t dca_org,
    758 		  uint32_t da_org,
    759 		  uint32_t sca_org,
    760 		  uint32_t sa_org)
    761 {
    762     double dca = dca_org * (1.0 / MASK);
    763     double da = da_org * (1.0 / MASK);
    764     double sca = sca_org * (1.0 / MASK);
    765     double sa = sa_org * (1.0 / MASK);
    766     double rca;
    767 
    768     if (2 * sca < sa)
    769     {
    770 	if (da == 0)
    771 	    rca = dca * sa;
    772 	else
    773 	    rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
    774     }
    775     else if (da == 0)
    776     {
    777 	rca = 0;
    778     }
    779     else if (4 * dca <= da)
    780     {
    781 	rca = dca * sa +
    782 	    (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
    783     }
    784     else
    785     {
    786 	rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
    787     }
    788     return rca * MASK + 0.5;
    789 }
    790 
    791 PDF_SEPARABLE_BLEND_MODE (soft_light)
    792 
    793 /*
    794  * Difference
    795  * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
    796  */
    797 static inline uint32_t
    798 blend_difference (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    799 {
    800     uint32_t dcasa = dca * sa;
    801     uint32_t scada = sca * da;
    802 
    803     if (scada < dcasa)
    804 	return DIV_ONE_UN8 (dcasa - scada);
    805     else
    806 	return DIV_ONE_UN8 (scada - dcasa);
    807 }
    808 
    809 PDF_SEPARABLE_BLEND_MODE (difference)
    810 
    811 /*
    812  * Exclusion
    813  * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
    814  */
    815 
    816 /* This can be made faster by writing it directly and not using
    817  * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
    818 
    819 static inline uint32_t
    820 blend_exclusion (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
    821 {
    822     return DIV_ONE_UN8 (sca * da + dca * sa - 2 * dca * sca);
    823 }
    824 
    825 PDF_SEPARABLE_BLEND_MODE (exclusion)
    826 
    827 #undef PDF_SEPARABLE_BLEND_MODE
    828 
    829 /*
    830  * PDF nonseperable blend modes are implemented using the following functions
    831  * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
    832  * and min value of the red, green and blue components.
    833  *
    834  * LUM (C) = 0.3  Cred + 0.59  Cgreen + 0.11  Cblue
    835  *
    836  * clip_color (C):
    837  *   l = LUM (C)
    838  *   min = Cmin
    839  *   max = Cmax
    840  *   if n < 0.0
    841  *     C = l + ( ( ( C  l )  l )  ( l  min ) )
    842  *   if x > 1.0
    843  *     C = l + ( ( ( C  l )  ( 1  l ) )  ( max  l ) )
    844  *   return C
    845  *
    846  * set_lum (C, l):
    847  *   d = l  LUM (C)
    848  *   C += d
    849  *   return clip_color (C)
    850  *
    851  * SAT (C) = CH_MAX (C) - CH_MIN (C)
    852  *
    853  * set_sat (C, s):
    854  *  if Cmax > Cmin
    855  *    Cmid = ( ( ( Cmid  Cmin )  s )  ( Cmax  Cmin ) )
    856  *    Cmax = s
    857  *  else
    858  *    Cmid = Cmax = 0.0
    859  *  Cmin = 0.0
    860  *  return C
    861  */
    862 
    863 /* For premultiplied colors, we need to know what happens when C is
    864  * multiplied by a real number. LUM and SAT are linear:
    865  *
    866  *    LUM (r  C) = r  LUM (C)		SAT (r * C) = r * SAT (C)
    867  *
    868  * If we extend clip_color with an extra argument a and change
    869  *
    870  *        if x >= 1.0
    871  *
    872  * into
    873  *
    874  *        if x >= a
    875  *
    876  * then clip_color is also linear:
    877  *
    878  *    r * clip_color (C, a) = clip_color (r_c, ra);
    879  *
    880  * for positive r.
    881  *
    882  * Similarly, we can extend set_lum with an extra argument that is just passed
    883  * on to clip_color:
    884  *
    885  *   r * set_lum ( C, l, a)
    886  *
    887  *   = r  clip_color ( C + l - LUM (C), a)
    888  *
    889  *   = clip_color ( r * C + r  l - r * LUM (C), r * a)
    890  *
    891  *   = set_lum ( r * C, r * l, r * a)
    892  *
    893  * Finally, set_sat:
    894  *
    895  *    r * set_sat (C, s) = set_sat (x * C, r * s)
    896  *
    897  * The above holds for all non-zero x, because the x'es in the fraction for
    898  * C_mid cancel out. Specifically, it holds for x = r:
    899  *
    900  *    r * set_sat (C, s) = set_sat (r_c, rs)
    901  *
    902  */
    903 
    904 /* So, for the non-separable PDF blend modes, we have (using s, d for
    905  * non-premultiplied colors, and S, D for premultiplied:
    906  *
    907  *   Color:
    908  *
    909  *     a_s * a_d * B(s, d)
    910  *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
    911  *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
    912  *
    913  *
    914  *   Luminosity:
    915  *
    916  *     a_s * a_d * B(s, d)
    917  *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
    918  *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
    919  *
    920  *
    921  *   Saturation:
    922  *
    923  *     a_s * a_d * B(s, d)
    924  *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
    925  *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
    926  *                                        a_s * LUM (D), a_s * a_d)
    927  *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
    928  *
    929  *   Hue:
    930  *
    931  *     a_s * a_d * B(s, d)
    932  *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
    933  *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
    934  *
    935  */
    936 
    937 #define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
    938 #define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
    939 #define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
    940 #define SAT(c) (CH_MAX (c) - CH_MIN (c))
    941 
    942 #define PDF_NON_SEPARABLE_BLEND_MODE(name)				\
    943     static void								\
    944     combine_ ## name ## _u (pixman_implementation_t *imp,		\
    945 			    pixman_op_t op,				\
    946                             uint32_t *dest,				\
    947 			    const uint32_t *src,				\
    948 			    const uint32_t *mask,			\
    949 			    int width)					\
    950     {									\
    951 	int i;								\
    952 	for (i = 0; i < width; ++i)					\
    953 	{								\
    954 	    uint32_t s = combine_mask (src, mask, i);			\
    955 	    uint32_t d = *(dest + i);					\
    956 	    uint8_t sa = ALPHA_8 (s);					\
    957 	    uint8_t isa = ~sa;						\
    958 	    uint8_t da = ALPHA_8 (d);					\
    959 	    uint8_t ida = ~da;						\
    960 	    uint32_t result;						\
    961 	    uint32_t sc[3], dc[3], c[3];					\
    962             								\
    963 	    result = d;							\
    964 	    UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida);	\
    965 	    dc[0] = RED_8 (d);						\
    966 	    sc[0] = RED_8 (s);						\
    967 	    dc[1] = GREEN_8 (d);					\
    968 	    sc[1] = GREEN_8 (s);					\
    969 	    dc[2] = BLUE_8 (d);						\
    970 	    sc[2] = BLUE_8 (s);						\
    971 	    blend_ ## name (c, dc, da, sc, sa);				\
    972             								\
    973 	    *(dest + i) = result +					\
    974 		(DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) +		\
    975 		(DIV_ONE_UN8 (c[0]) << R_SHIFT) +			\
    976 		(DIV_ONE_UN8 (c[1]) << G_SHIFT) +			\
    977 		(DIV_ONE_UN8 (c[2]));					\
    978 	}								\
    979     }
    980 
    981 static void
    982 set_lum (uint32_t dest[3], uint32_t src[3], uint32_t sa, uint32_t lum)
    983 {
    984     double a, l, min, max;
    985     double tmp[3];
    986 
    987     a = sa * (1.0 / MASK);
    988 
    989     l = lum * (1.0 / MASK);
    990     tmp[0] = src[0] * (1.0 / MASK);
    991     tmp[1] = src[1] * (1.0 / MASK);
    992     tmp[2] = src[2] * (1.0 / MASK);
    993 
    994     l = l - LUM (tmp);
    995     tmp[0] += l;
    996     tmp[1] += l;
    997     tmp[2] += l;
    998 
    999     /* clip_color */
   1000     l = LUM (tmp);
   1001     min = CH_MIN (tmp);
   1002     max = CH_MAX (tmp);
   1003 
   1004     if (min < 0)
   1005     {
   1006 	if (l - min == 0.0)
   1007 	{
   1008 	    tmp[0] = 0;
   1009 	    tmp[1] = 0;
   1010 	    tmp[2] = 0;
   1011 	}
   1012 	else
   1013 	{
   1014 	    tmp[0] = l + (tmp[0] - l) * l / (l - min);
   1015 	    tmp[1] = l + (tmp[1] - l) * l / (l - min);
   1016 	    tmp[2] = l + (tmp[2] - l) * l / (l - min);
   1017 	}
   1018     }
   1019     if (max > a)
   1020     {
   1021 	if (max - l == 0.0)
   1022 	{
   1023 	    tmp[0] = a;
   1024 	    tmp[1] = a;
   1025 	    tmp[2] = a;
   1026 	}
   1027 	else
   1028 	{
   1029 	    tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
   1030 	    tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
   1031 	    tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
   1032 	}
   1033     }
   1034 
   1035     dest[0] = tmp[0] * MASK + 0.5;
   1036     dest[1] = tmp[1] * MASK + 0.5;
   1037     dest[2] = tmp[2] * MASK + 0.5;
   1038 }
   1039 
   1040 static void
   1041 set_sat (uint32_t dest[3], uint32_t src[3], uint32_t sat)
   1042 {
   1043     int id[3];
   1044     uint32_t min, max;
   1045 
   1046     if (src[0] > src[1])
   1047     {
   1048 	if (src[0] > src[2])
   1049 	{
   1050 	    id[0] = 0;
   1051 	    if (src[1] > src[2])
   1052 	    {
   1053 		id[1] = 1;
   1054 		id[2] = 2;
   1055 	    }
   1056 	    else
   1057 	    {
   1058 		id[1] = 2;
   1059 		id[2] = 1;
   1060 	    }
   1061 	}
   1062 	else
   1063 	{
   1064 	    id[0] = 2;
   1065 	    id[1] = 0;
   1066 	    id[2] = 1;
   1067 	}
   1068     }
   1069     else
   1070     {
   1071 	if (src[0] > src[2])
   1072 	{
   1073 	    id[0] = 1;
   1074 	    id[1] = 0;
   1075 	    id[2] = 2;
   1076 	}
   1077 	else
   1078 	{
   1079 	    id[2] = 0;
   1080 	    if (src[1] > src[2])
   1081 	    {
   1082 		id[0] = 1;
   1083 		id[1] = 2;
   1084 	    }
   1085 	    else
   1086 	    {
   1087 		id[0] = 2;
   1088 		id[1] = 1;
   1089 	    }
   1090 	}
   1091     }
   1092 
   1093     max = dest[id[0]];
   1094     min = dest[id[2]];
   1095     if (max > min)
   1096     {
   1097 	dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
   1098 	dest[id[0]] = sat;
   1099 	dest[id[2]] = 0;
   1100     }
   1101     else
   1102     {
   1103 	dest[0] = dest[1] = dest[2] = 0;
   1104     }
   1105 }
   1106 
   1107 /*
   1108  * Hue:
   1109  * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
   1110  */
   1111 static inline void
   1112 blend_hsl_hue (uint32_t c[3],
   1113                uint32_t dc[3],
   1114                uint32_t da,
   1115                uint32_t sc[3],
   1116                uint32_t sa)
   1117 {
   1118     c[0] = sc[0] * da;
   1119     c[1] = sc[1] * da;
   1120     c[2] = sc[2] * da;
   1121     set_sat (c, c, SAT (dc) * sa);
   1122     set_lum (c, c, sa * da, LUM (dc) * sa);
   1123 }
   1124 
   1125 PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
   1126 
   1127 /*
   1128  * Saturation:
   1129  * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
   1130  */
   1131 static inline void
   1132 blend_hsl_saturation (uint32_t c[3],
   1133                       uint32_t dc[3],
   1134                       uint32_t da,
   1135                       uint32_t sc[3],
   1136                       uint32_t sa)
   1137 {
   1138     c[0] = dc[0] * sa;
   1139     c[1] = dc[1] * sa;
   1140     c[2] = dc[2] * sa;
   1141     set_sat (c, c, SAT (sc) * da);
   1142     set_lum (c, c, sa * da, LUM (dc) * sa);
   1143 }
   1144 
   1145 PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
   1146 
   1147 /*
   1148  * Color:
   1149  * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
   1150  */
   1151 static inline void
   1152 blend_hsl_color (uint32_t c[3],
   1153                  uint32_t dc[3],
   1154                  uint32_t da,
   1155                  uint32_t sc[3],
   1156                  uint32_t sa)
   1157 {
   1158     c[0] = sc[0] * da;
   1159     c[1] = sc[1] * da;
   1160     c[2] = sc[2] * da;
   1161     set_lum (c, c, sa * da, LUM (dc) * sa);
   1162 }
   1163 
   1164 PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
   1165 
   1166 /*
   1167  * Luminosity:
   1168  * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
   1169  */
   1170 static inline void
   1171 blend_hsl_luminosity (uint32_t c[3],
   1172                       uint32_t dc[3],
   1173                       uint32_t da,
   1174                       uint32_t sc[3],
   1175                       uint32_t sa)
   1176 {
   1177     c[0] = dc[0] * sa;
   1178     c[1] = dc[1] * sa;
   1179     c[2] = dc[2] * sa;
   1180     set_lum (c, c, sa * da, LUM (sc) * da);
   1181 }
   1182 
   1183 PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
   1184 
   1185 #undef SAT
   1186 #undef LUM
   1187 #undef CH_MAX
   1188 #undef CH_MIN
   1189 #undef PDF_NON_SEPARABLE_BLEND_MODE
   1190 
   1191 /* All of the disjoint/conjoint composing functions
   1192  *
   1193  * The four entries in the first column indicate what source contributions
   1194  * come from each of the four areas of the picture -- areas covered by neither
   1195  * A nor B, areas covered only by A, areas covered only by B and finally
   1196  * areas covered by both A and B.
   1197  *
   1198  * Disjoint			Conjoint
   1199  * Fa		Fb		Fa		Fb
   1200  * (0,0,0,0)	0		0		0		0
   1201  * (0,A,0,A)	1		0		1		0
   1202  * (0,0,B,B)	0		1		0		1
   1203  * (0,A,B,A)	1		min((1-a)/b,1)	1		max(1-a/b,0)
   1204  * (0,A,B,B)	min((1-b)/a,1)	1		max(1-b/a,0)	1
   1205  * (0,0,0,A)	max(1-(1-b)/a,0) 0		min(1,b/a)	0
   1206  * (0,0,0,B)	0		max(1-(1-a)/b,0) 0		min(a/b,1)
   1207  * (0,A,0,0)	min(1,(1-b)/a)	0		max(1-b/a,0)	0
   1208  * (0,0,B,0)	0		min(1,(1-a)/b)	0		max(1-a/b,0)
   1209  * (0,0,B,A)	max(1-(1-b)/a,0) min(1,(1-a)/b)	 min(1,b/a)	max(1-a/b,0)
   1210  * (0,A,0,B)	min(1,(1-b)/a)	max(1-(1-a)/b,0) max(1-b/a,0)	min(1,a/b)
   1211  * (0,A,B,0)	min(1,(1-b)/a)	min(1,(1-a)/b)	max(1-b/a,0)	max(1-a/b,0)
   1212  *
   1213  * See  http://marc.info/?l=xfree-render&m=99792000027857&w=2  for more
   1214  * information about these operators.
   1215  */
   1216 
   1217 #define COMBINE_A_OUT 1
   1218 #define COMBINE_A_IN  2
   1219 #define COMBINE_B_OUT 4
   1220 #define COMBINE_B_IN  8
   1221 
   1222 #define COMBINE_CLEAR   0
   1223 #define COMBINE_A       (COMBINE_A_OUT | COMBINE_A_IN)
   1224 #define COMBINE_B       (COMBINE_B_OUT | COMBINE_B_IN)
   1225 #define COMBINE_A_OVER  (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)
   1226 #define COMBINE_B_OVER  (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)
   1227 #define COMBINE_A_ATOP  (COMBINE_B_OUT | COMBINE_A_IN)
   1228 #define COMBINE_B_ATOP  (COMBINE_A_OUT | COMBINE_B_IN)
   1229 #define COMBINE_XOR     (COMBINE_A_OUT | COMBINE_B_OUT)
   1230 
   1231 /* portion covered by a but not b */
   1232 static uint8_t
   1233 combine_disjoint_out_part (uint8_t a, uint8_t b)
   1234 {
   1235     /* min (1, (1-b) / a) */
   1236 
   1237     b = ~b;                 /* 1 - b */
   1238     if (b >= a)             /* 1 - b >= a -> (1-b)/a >= 1 */
   1239 	return MASK;        /* 1 */
   1240     return DIV_UN8 (b, a);     /* (1-b) / a */
   1241 }
   1242 
   1243 /* portion covered by both a and b */
   1244 static uint8_t
   1245 combine_disjoint_in_part (uint8_t a, uint8_t b)
   1246 {
   1247     /* max (1-(1-b)/a,0) */
   1248     /*  = - min ((1-b)/a - 1, 0) */
   1249     /*  = 1 - min (1, (1-b)/a) */
   1250 
   1251     b = ~b;                 /* 1 - b */
   1252     if (b >= a)             /* 1 - b >= a -> (1-b)/a >= 1 */
   1253 	return 0;           /* 1 - 1 */
   1254     return ~DIV_UN8(b, a);    /* 1 - (1-b) / a */
   1255 }
   1256 
   1257 /* portion covered by a but not b */
   1258 static uint8_t
   1259 combine_conjoint_out_part (uint8_t a, uint8_t b)
   1260 {
   1261     /* max (1-b/a,0) */
   1262     /* = 1-min(b/a,1) */
   1263 
   1264     /* min (1, (1-b) / a) */
   1265 
   1266     if (b >= a)             /* b >= a -> b/a >= 1 */
   1267 	return 0x00;        /* 0 */
   1268     return ~DIV_UN8(b, a);    /* 1 - b/a */
   1269 }
   1270 
   1271 /* portion covered by both a and b */
   1272 static uint8_t
   1273 combine_conjoint_in_part (uint8_t a, uint8_t b)
   1274 {
   1275     /* min (1,b/a) */
   1276 
   1277     if (b >= a)             /* b >= a -> b/a >= 1 */
   1278 	return MASK;        /* 1 */
   1279     return DIV_UN8 (b, a);     /* b/a */
   1280 }
   1281 
   1282 #define GET_COMP(v, i)   ((uint16_t) (uint8_t) ((v) >> i))
   1283 
   1284 #define ADD(x, y, i, t)							\
   1285     ((t) = GET_COMP (x, i) + GET_COMP (y, i),				\
   1286      (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
   1287 
   1288 #define GENERIC(x, y, i, ax, ay, t, u, v)				\
   1289     ((t) = (MUL_UN8 (GET_COMP (y, i), ay, (u)) +			\
   1290             MUL_UN8 (GET_COMP (x, i), ax, (v))),			\
   1291      (uint32_t) ((uint8_t) ((t) |					\
   1292                            (0 - ((t) >> G_SHIFT)))) << (i))
   1293 
   1294 static void
   1295 combine_disjoint_general_u (uint32_t *      dest,
   1296                             const uint32_t *src,
   1297                             const uint32_t *mask,
   1298                             int            width,
   1299                             uint8_t        combine)
   1300 {
   1301     int i;
   1302 
   1303     for (i = 0; i < width; ++i)
   1304     {
   1305 	uint32_t s = combine_mask (src, mask, i);
   1306 	uint32_t d = *(dest + i);
   1307 	uint32_t m, n, o, p;
   1308 	uint16_t Fa, Fb, t, u, v;
   1309 	uint8_t sa = s >> A_SHIFT;
   1310 	uint8_t da = d >> A_SHIFT;
   1311 
   1312 	switch (combine & COMBINE_A)
   1313 	{
   1314 	default:
   1315 	    Fa = 0;
   1316 	    break;
   1317 
   1318 	case COMBINE_A_OUT:
   1319 	    Fa = combine_disjoint_out_part (sa, da);
   1320 	    break;
   1321 
   1322 	case COMBINE_A_IN:
   1323 	    Fa = combine_disjoint_in_part (sa, da);
   1324 	    break;
   1325 
   1326 	case COMBINE_A:
   1327 	    Fa = MASK;
   1328 	    break;
   1329 	}
   1330 
   1331 	switch (combine & COMBINE_B)
   1332 	{
   1333 	default:
   1334 	    Fb = 0;
   1335 	    break;
   1336 
   1337 	case COMBINE_B_OUT:
   1338 	    Fb = combine_disjoint_out_part (da, sa);
   1339 	    break;
   1340 
   1341 	case COMBINE_B_IN:
   1342 	    Fb = combine_disjoint_in_part (da, sa);
   1343 	    break;
   1344 
   1345 	case COMBINE_B:
   1346 	    Fb = MASK;
   1347 	    break;
   1348 	}
   1349 	m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
   1350 	n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
   1351 	o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
   1352 	p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
   1353 	s = m | n | o | p;
   1354 	*(dest + i) = s;
   1355     }
   1356 }
   1357 
   1358 static void
   1359 combine_disjoint_over_u (pixman_implementation_t *imp,
   1360                          pixman_op_t              op,
   1361                          uint32_t *                dest,
   1362                          const uint32_t *          src,
   1363                          const uint32_t *          mask,
   1364                          int                      width)
   1365 {
   1366     int i;
   1367 
   1368     for (i = 0; i < width; ++i)
   1369     {
   1370 	uint32_t s = combine_mask (src, mask, i);
   1371 	uint16_t a = s >> A_SHIFT;
   1372 
   1373 	if (s != 0x00)
   1374 	{
   1375 	    uint32_t d = *(dest + i);
   1376 	    a = combine_disjoint_out_part (d >> A_SHIFT, a);
   1377 	    UN8x4_MUL_UN8_ADD_UN8x4 (d, a, s);
   1378 
   1379 	    *(dest + i) = d;
   1380 	}
   1381     }
   1382 }
   1383 
   1384 static void
   1385 combine_disjoint_in_u (pixman_implementation_t *imp,
   1386                        pixman_op_t              op,
   1387                        uint32_t *                dest,
   1388                        const uint32_t *          src,
   1389                        const uint32_t *          mask,
   1390                        int                      width)
   1391 {
   1392     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
   1393 }
   1394 
   1395 static void
   1396 combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
   1397                                pixman_op_t              op,
   1398                                uint32_t *                dest,
   1399                                const uint32_t *          src,
   1400                                const uint32_t *          mask,
   1401                                int                      width)
   1402 {
   1403     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
   1404 }
   1405 
   1406 static void
   1407 combine_disjoint_out_u (pixman_implementation_t *imp,
   1408                         pixman_op_t              op,
   1409                         uint32_t *                dest,
   1410                         const uint32_t *          src,
   1411                         const uint32_t *          mask,
   1412                         int                      width)
   1413 {
   1414     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
   1415 }
   1416 
   1417 static void
   1418 combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
   1419                                 pixman_op_t              op,
   1420                                 uint32_t *                dest,
   1421                                 const uint32_t *          src,
   1422                                 const uint32_t *          mask,
   1423                                 int                      width)
   1424 {
   1425     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
   1426 }
   1427 
   1428 static void
   1429 combine_disjoint_atop_u (pixman_implementation_t *imp,
   1430                          pixman_op_t              op,
   1431                          uint32_t *                dest,
   1432                          const uint32_t *          src,
   1433                          const uint32_t *          mask,
   1434                          int                      width)
   1435 {
   1436     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
   1437 }
   1438 
   1439 static void
   1440 combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
   1441                                  pixman_op_t              op,
   1442                                  uint32_t *                dest,
   1443                                  const uint32_t *          src,
   1444                                  const uint32_t *          mask,
   1445                                  int                      width)
   1446 {
   1447     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
   1448 }
   1449 
   1450 static void
   1451 combine_disjoint_xor_u (pixman_implementation_t *imp,
   1452                         pixman_op_t              op,
   1453                         uint32_t *                dest,
   1454                         const uint32_t *          src,
   1455                         const uint32_t *          mask,
   1456                         int                      width)
   1457 {
   1458     combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
   1459 }
   1460 
   1461 static void
   1462 combine_conjoint_general_u (uint32_t *      dest,
   1463                             const uint32_t *src,
   1464                             const uint32_t *mask,
   1465                             int            width,
   1466                             uint8_t        combine)
   1467 {
   1468     int i;
   1469 
   1470     for (i = 0; i < width; ++i)
   1471     {
   1472 	uint32_t s = combine_mask (src, mask, i);
   1473 	uint32_t d = *(dest + i);
   1474 	uint32_t m, n, o, p;
   1475 	uint16_t Fa, Fb, t, u, v;
   1476 	uint8_t sa = s >> A_SHIFT;
   1477 	uint8_t da = d >> A_SHIFT;
   1478 
   1479 	switch (combine & COMBINE_A)
   1480 	{
   1481 	default:
   1482 	    Fa = 0;
   1483 	    break;
   1484 
   1485 	case COMBINE_A_OUT:
   1486 	    Fa = combine_conjoint_out_part (sa, da);
   1487 	    break;
   1488 
   1489 	case COMBINE_A_IN:
   1490 	    Fa = combine_conjoint_in_part (sa, da);
   1491 	    break;
   1492 
   1493 	case COMBINE_A:
   1494 	    Fa = MASK;
   1495 	    break;
   1496 	}
   1497 
   1498 	switch (combine & COMBINE_B)
   1499 	{
   1500 	default:
   1501 	    Fb = 0;
   1502 	    break;
   1503 
   1504 	case COMBINE_B_OUT:
   1505 	    Fb = combine_conjoint_out_part (da, sa);
   1506 	    break;
   1507 
   1508 	case COMBINE_B_IN:
   1509 	    Fb = combine_conjoint_in_part (da, sa);
   1510 	    break;
   1511 
   1512 	case COMBINE_B:
   1513 	    Fb = MASK;
   1514 	    break;
   1515 	}
   1516 
   1517 	m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
   1518 	n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
   1519 	o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
   1520 	p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
   1521 
   1522 	s = m | n | o | p;
   1523 
   1524 	*(dest + i) = s;
   1525     }
   1526 }
   1527 
   1528 static void
   1529 combine_conjoint_over_u (pixman_implementation_t *imp,
   1530                          pixman_op_t              op,
   1531                          uint32_t *                dest,
   1532                          const uint32_t *          src,
   1533                          const uint32_t *          mask,
   1534                          int                      width)
   1535 {
   1536     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
   1537 }
   1538 
   1539 static void
   1540 combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
   1541                                  pixman_op_t              op,
   1542                                  uint32_t *                dest,
   1543                                  const uint32_t *          src,
   1544                                  const uint32_t *          mask,
   1545                                  int                      width)
   1546 {
   1547     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
   1548 }
   1549 
   1550 static void
   1551 combine_conjoint_in_u (pixman_implementation_t *imp,
   1552                        pixman_op_t              op,
   1553                        uint32_t *                dest,
   1554                        const uint32_t *          src,
   1555                        const uint32_t *          mask,
   1556                        int                      width)
   1557 {
   1558     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
   1559 }
   1560 
   1561 static void
   1562 combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
   1563                                pixman_op_t              op,
   1564                                uint32_t *                dest,
   1565                                const uint32_t *          src,
   1566                                const uint32_t *          mask,
   1567                                int                      width)
   1568 {
   1569     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
   1570 }
   1571 
   1572 static void
   1573 combine_conjoint_out_u (pixman_implementation_t *imp,
   1574                         pixman_op_t              op,
   1575                         uint32_t *                dest,
   1576                         const uint32_t *          src,
   1577                         const uint32_t *          mask,
   1578                         int                      width)
   1579 {
   1580     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
   1581 }
   1582 
   1583 static void
   1584 combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
   1585                                 pixman_op_t              op,
   1586                                 uint32_t *                dest,
   1587                                 const uint32_t *          src,
   1588                                 const uint32_t *          mask,
   1589                                 int                      width)
   1590 {
   1591     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
   1592 }
   1593 
   1594 static void
   1595 combine_conjoint_atop_u (pixman_implementation_t *imp,
   1596                          pixman_op_t              op,
   1597                          uint32_t *                dest,
   1598                          const uint32_t *          src,
   1599                          const uint32_t *          mask,
   1600                          int                      width)
   1601 {
   1602     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
   1603 }
   1604 
   1605 static void
   1606 combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
   1607                                  pixman_op_t              op,
   1608                                  uint32_t *                dest,
   1609                                  const uint32_t *          src,
   1610                                  const uint32_t *          mask,
   1611                                  int                      width)
   1612 {
   1613     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
   1614 }
   1615 
   1616 static void
   1617 combine_conjoint_xor_u (pixman_implementation_t *imp,
   1618                         pixman_op_t              op,
   1619                         uint32_t *                dest,
   1620                         const uint32_t *          src,
   1621                         const uint32_t *          mask,
   1622                         int                      width)
   1623 {
   1624     combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
   1625 }
   1626 
   1627 
   1628 /* Component alpha combiners */
   1629 
   1630 static void
   1631 combine_clear_ca (pixman_implementation_t *imp,
   1632                   pixman_op_t              op,
   1633                   uint32_t *                dest,
   1634                   const uint32_t *          src,
   1635                   const uint32_t *          mask,
   1636                   int                      width)
   1637 {
   1638     memset (dest, 0, width * sizeof(uint32_t));
   1639 }
   1640 
   1641 static void
   1642 combine_src_ca (pixman_implementation_t *imp,
   1643                 pixman_op_t              op,
   1644                 uint32_t *                dest,
   1645                 const uint32_t *          src,
   1646                 const uint32_t *          mask,
   1647                 int                      width)
   1648 {
   1649     int i;
   1650 
   1651     for (i = 0; i < width; ++i)
   1652     {
   1653 	uint32_t s = *(src + i);
   1654 	uint32_t m = *(mask + i);
   1655 
   1656 	combine_mask_value_ca (&s, &m);
   1657 
   1658 	*(dest + i) = s;
   1659     }
   1660 }
   1661 
   1662 static void
   1663 combine_over_ca (pixman_implementation_t *imp,
   1664                  pixman_op_t              op,
   1665                  uint32_t *                dest,
   1666                  const uint32_t *          src,
   1667                  const uint32_t *          mask,
   1668                  int                      width)
   1669 {
   1670     int i;
   1671 
   1672     for (i = 0; i < width; ++i)
   1673     {
   1674 	uint32_t s = *(src + i);
   1675 	uint32_t m = *(mask + i);
   1676 	uint32_t a;
   1677 
   1678 	combine_mask_ca (&s, &m);
   1679 
   1680 	a = ~m;
   1681 	if (a)
   1682 	{
   1683 	    uint32_t d = *(dest + i);
   1684 	    UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s);
   1685 	    s = d;
   1686 	}
   1687 
   1688 	*(dest + i) = s;
   1689     }
   1690 }
   1691 
   1692 static void
   1693 combine_over_reverse_ca (pixman_implementation_t *imp,
   1694                          pixman_op_t              op,
   1695                          uint32_t *                dest,
   1696                          const uint32_t *          src,
   1697                          const uint32_t *          mask,
   1698                          int                      width)
   1699 {
   1700     int i;
   1701 
   1702     for (i = 0; i < width; ++i)
   1703     {
   1704 	uint32_t d = *(dest + i);
   1705 	uint32_t a = ~d >> A_SHIFT;
   1706 
   1707 	if (a)
   1708 	{
   1709 	    uint32_t s = *(src + i);
   1710 	    uint32_t m = *(mask + i);
   1711 
   1712 	    UN8x4_MUL_UN8x4 (s, m);
   1713 	    UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d);
   1714 
   1715 	    *(dest + i) = s;
   1716 	}
   1717     }
   1718 }
   1719 
   1720 static void
   1721 combine_in_ca (pixman_implementation_t *imp,
   1722                pixman_op_t              op,
   1723                uint32_t *                dest,
   1724                const uint32_t *          src,
   1725                const uint32_t *          mask,
   1726                int                      width)
   1727 {
   1728     int i;
   1729 
   1730     for (i = 0; i < width; ++i)
   1731     {
   1732 	uint32_t d = *(dest + i);
   1733 	uint16_t a = d >> A_SHIFT;
   1734 	uint32_t s = 0;
   1735 
   1736 	if (a)
   1737 	{
   1738 	    uint32_t m = *(mask + i);
   1739 
   1740 	    s = *(src + i);
   1741 	    combine_mask_value_ca (&s, &m);
   1742 
   1743 	    if (a != MASK)
   1744 		UN8x4_MUL_UN8 (s, a);
   1745 	}
   1746 
   1747 	*(dest + i) = s;
   1748     }
   1749 }
   1750 
   1751 static void
   1752 combine_in_reverse_ca (pixman_implementation_t *imp,
   1753                        pixman_op_t              op,
   1754                        uint32_t *                dest,
   1755                        const uint32_t *          src,
   1756                        const uint32_t *          mask,
   1757                        int                      width)
   1758 {
   1759     int i;
   1760 
   1761     for (i = 0; i < width; ++i)
   1762     {
   1763 	uint32_t s = *(src + i);
   1764 	uint32_t m = *(mask + i);
   1765 	uint32_t a;
   1766 
   1767 	combine_mask_alpha_ca (&s, &m);
   1768 
   1769 	a = m;
   1770 	if (a != ~0)
   1771 	{
   1772 	    uint32_t d = 0;
   1773 
   1774 	    if (a)
   1775 	    {
   1776 		d = *(dest + i);
   1777 		UN8x4_MUL_UN8x4 (d, a);
   1778 	    }
   1779 
   1780 	    *(dest + i) = d;
   1781 	}
   1782     }
   1783 }
   1784 
   1785 static void
   1786 combine_out_ca (pixman_implementation_t *imp,
   1787                 pixman_op_t              op,
   1788                 uint32_t *                dest,
   1789                 const uint32_t *          src,
   1790                 const uint32_t *          mask,
   1791                 int                      width)
   1792 {
   1793     int i;
   1794 
   1795     for (i = 0; i < width; ++i)
   1796     {
   1797 	uint32_t d = *(dest + i);
   1798 	uint16_t a = ~d >> A_SHIFT;
   1799 	uint32_t s = 0;
   1800 
   1801 	if (a)
   1802 	{
   1803 	    uint32_t m = *(mask + i);
   1804 
   1805 	    s = *(src + i);
   1806 	    combine_mask_value_ca (&s, &m);
   1807 
   1808 	    if (a != MASK)
   1809 		UN8x4_MUL_UN8 (s, a);
   1810 	}
   1811 
   1812 	*(dest + i) = s;
   1813     }
   1814 }
   1815 
   1816 static void
   1817 combine_out_reverse_ca (pixman_implementation_t *imp,
   1818                         pixman_op_t              op,
   1819                         uint32_t *                dest,
   1820                         const uint32_t *          src,
   1821                         const uint32_t *          mask,
   1822                         int                      width)
   1823 {
   1824     int i;
   1825 
   1826     for (i = 0; i < width; ++i)
   1827     {
   1828 	uint32_t s = *(src + i);
   1829 	uint32_t m = *(mask + i);
   1830 	uint32_t a;
   1831 
   1832 	combine_mask_alpha_ca (&s, &m);
   1833 
   1834 	a = ~m;
   1835 	if (a != ~0)
   1836 	{
   1837 	    uint32_t d = 0;
   1838 
   1839 	    if (a)
   1840 	    {
   1841 		d = *(dest + i);
   1842 		UN8x4_MUL_UN8x4 (d, a);
   1843 	    }
   1844 
   1845 	    *(dest + i) = d;
   1846 	}
   1847     }
   1848 }
   1849 
   1850 static void
   1851 combine_atop_ca (pixman_implementation_t *imp,
   1852                  pixman_op_t              op,
   1853                  uint32_t *                dest,
   1854                  const uint32_t *          src,
   1855                  const uint32_t *          mask,
   1856                  int                      width)
   1857 {
   1858     int i;
   1859 
   1860     for (i = 0; i < width; ++i)
   1861     {
   1862 	uint32_t d = *(dest + i);
   1863 	uint32_t s = *(src + i);
   1864 	uint32_t m = *(mask + i);
   1865 	uint32_t ad;
   1866 	uint16_t as = d >> A_SHIFT;
   1867 
   1868 	combine_mask_ca (&s, &m);
   1869 
   1870 	ad = ~m;
   1871 
   1872 	UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
   1873 
   1874 	*(dest + i) = d;
   1875     }
   1876 }
   1877 
   1878 static void
   1879 combine_atop_reverse_ca (pixman_implementation_t *imp,
   1880                          pixman_op_t              op,
   1881                          uint32_t *                dest,
   1882                          const uint32_t *          src,
   1883                          const uint32_t *          mask,
   1884                          int                      width)
   1885 {
   1886     int i;
   1887 
   1888     for (i = 0; i < width; ++i)
   1889     {
   1890 	uint32_t d = *(dest + i);
   1891 	uint32_t s = *(src + i);
   1892 	uint32_t m = *(mask + i);
   1893 	uint32_t ad;
   1894 	uint16_t as = ~d >> A_SHIFT;
   1895 
   1896 	combine_mask_ca (&s, &m);
   1897 
   1898 	ad = m;
   1899 
   1900 	UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
   1901 
   1902 	*(dest + i) = d;
   1903     }
   1904 }
   1905 
   1906 static void
   1907 combine_xor_ca (pixman_implementation_t *imp,
   1908                 pixman_op_t              op,
   1909                 uint32_t *                dest,
   1910                 const uint32_t *          src,
   1911                 const uint32_t *          mask,
   1912                 int                      width)
   1913 {
   1914     int i;
   1915 
   1916     for (i = 0; i < width; ++i)
   1917     {
   1918 	uint32_t d = *(dest + i);
   1919 	uint32_t s = *(src + i);
   1920 	uint32_t m = *(mask + i);
   1921 	uint32_t ad;
   1922 	uint16_t as = ~d >> A_SHIFT;
   1923 
   1924 	combine_mask_ca (&s, &m);
   1925 
   1926 	ad = ~m;
   1927 
   1928 	UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
   1929 
   1930 	*(dest + i) = d;
   1931     }
   1932 }
   1933 
   1934 static void
   1935 combine_add_ca (pixman_implementation_t *imp,
   1936                 pixman_op_t              op,
   1937                 uint32_t *                dest,
   1938                 const uint32_t *          src,
   1939                 const uint32_t *          mask,
   1940                 int                      width)
   1941 {
   1942     int i;
   1943 
   1944     for (i = 0; i < width; ++i)
   1945     {
   1946 	uint32_t s = *(src + i);
   1947 	uint32_t m = *(mask + i);
   1948 	uint32_t d = *(dest + i);
   1949 
   1950 	combine_mask_value_ca (&s, &m);
   1951 
   1952 	UN8x4_ADD_UN8x4 (d, s);
   1953 
   1954 	*(dest + i) = d;
   1955     }
   1956 }
   1957 
   1958 static void
   1959 combine_saturate_ca (pixman_implementation_t *imp,
   1960                      pixman_op_t              op,
   1961                      uint32_t *                dest,
   1962                      const uint32_t *          src,
   1963                      const uint32_t *          mask,
   1964                      int                      width)
   1965 {
   1966     int i;
   1967 
   1968     for (i = 0; i < width; ++i)
   1969     {
   1970 	uint32_t s, d;
   1971 	uint16_t sa, sr, sg, sb, da;
   1972 	uint16_t t, u, v;
   1973 	uint32_t m, n, o, p;
   1974 
   1975 	d = *(dest + i);
   1976 	s = *(src + i);
   1977 	m = *(mask + i);
   1978 
   1979 	combine_mask_ca (&s, &m);
   1980 
   1981 	sa = (m >> A_SHIFT);
   1982 	sr = (m >> R_SHIFT) & MASK;
   1983 	sg = (m >> G_SHIFT) & MASK;
   1984 	sb =  m             & MASK;
   1985 	da = ~d >> A_SHIFT;
   1986 
   1987 	if (sb <= da)
   1988 	    m = ADD (s, d, 0, t);
   1989 	else
   1990 	    m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v);
   1991 
   1992 	if (sg <= da)
   1993 	    n = ADD (s, d, G_SHIFT, t);
   1994 	else
   1995 	    n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v);
   1996 
   1997 	if (sr <= da)
   1998 	    o = ADD (s, d, R_SHIFT, t);
   1999 	else
   2000 	    o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v);
   2001 
   2002 	if (sa <= da)
   2003 	    p = ADD (s, d, A_SHIFT, t);
   2004 	else
   2005 	    p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v);
   2006 
   2007 	*(dest + i) = m | n | o | p;
   2008     }
   2009 }
   2010 
   2011 static void
   2012 combine_disjoint_general_ca (uint32_t *      dest,
   2013                              const uint32_t *src,
   2014                              const uint32_t *mask,
   2015                              int            width,
   2016                              uint8_t        combine)
   2017 {
   2018     int i;
   2019 
   2020     for (i = 0; i < width; ++i)
   2021     {
   2022 	uint32_t s, d;
   2023 	uint32_t m, n, o, p;
   2024 	uint32_t Fa, Fb;
   2025 	uint16_t t, u, v;
   2026 	uint32_t sa;
   2027 	uint8_t da;
   2028 
   2029 	s = *(src + i);
   2030 	m = *(mask + i);
   2031 	d = *(dest + i);
   2032 	da = d >> A_SHIFT;
   2033 
   2034 	combine_mask_ca (&s, &m);
   2035 
   2036 	sa = m;
   2037 
   2038 	switch (combine & COMBINE_A)
   2039 	{
   2040 	default:
   2041 	    Fa = 0;
   2042 	    break;
   2043 
   2044 	case COMBINE_A_OUT:
   2045 	    m = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> 0), da);
   2046 	    n = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
   2047 	    o = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
   2048 	    p = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
   2049 	    Fa = m | n | o | p;
   2050 	    break;
   2051 
   2052 	case COMBINE_A_IN:
   2053 	    m = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> 0), da);
   2054 	    n = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
   2055 	    o = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
   2056 	    p = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
   2057 	    Fa = m | n | o | p;
   2058 	    break;
   2059 
   2060 	case COMBINE_A:
   2061 	    Fa = ~0;
   2062 	    break;
   2063 	}
   2064 
   2065 	switch (combine & COMBINE_B)
   2066 	{
   2067 	default:
   2068 	    Fb = 0;
   2069 	    break;
   2070 
   2071 	case COMBINE_B_OUT:
   2072 	    m = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> 0));
   2073 	    n = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
   2074 	    o = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
   2075 	    p = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
   2076 	    Fb = m | n | o | p;
   2077 	    break;
   2078 
   2079 	case COMBINE_B_IN:
   2080 	    m = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> 0));
   2081 	    n = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
   2082 	    o = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
   2083 	    p = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
   2084 	    Fb = m | n | o | p;
   2085 	    break;
   2086 
   2087 	case COMBINE_B:
   2088 	    Fb = ~0;
   2089 	    break;
   2090 	}
   2091 	m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
   2092 	n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
   2093 	o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
   2094 	p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
   2095 
   2096 	s = m | n | o | p;
   2097 
   2098 	*(dest + i) = s;
   2099     }
   2100 }
   2101 
   2102 static void
   2103 combine_disjoint_over_ca (pixman_implementation_t *imp,
   2104                           pixman_op_t              op,
   2105                           uint32_t *                dest,
   2106                           const uint32_t *          src,
   2107                           const uint32_t *          mask,
   2108                           int                      width)
   2109 {
   2110     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
   2111 }
   2112 
   2113 static void
   2114 combine_disjoint_in_ca (pixman_implementation_t *imp,
   2115                         pixman_op_t              op,
   2116                         uint32_t *                dest,
   2117                         const uint32_t *          src,
   2118                         const uint32_t *          mask,
   2119                         int                      width)
   2120 {
   2121     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
   2122 }
   2123 
   2124 static void
   2125 combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
   2126                                 pixman_op_t              op,
   2127                                 uint32_t *                dest,
   2128                                 const uint32_t *          src,
   2129                                 const uint32_t *          mask,
   2130                                 int                      width)
   2131 {
   2132     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
   2133 }
   2134 
   2135 static void
   2136 combine_disjoint_out_ca (pixman_implementation_t *imp,
   2137                          pixman_op_t              op,
   2138                          uint32_t *                dest,
   2139                          const uint32_t *          src,
   2140                          const uint32_t *          mask,
   2141                          int                      width)
   2142 {
   2143     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
   2144 }
   2145 
   2146 static void
   2147 combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
   2148                                  pixman_op_t              op,
   2149                                  uint32_t *                dest,
   2150                                  const uint32_t *          src,
   2151                                  const uint32_t *          mask,
   2152                                  int                      width)
   2153 {
   2154     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
   2155 }
   2156 
   2157 static void
   2158 combine_disjoint_atop_ca (pixman_implementation_t *imp,
   2159                           pixman_op_t              op,
   2160                           uint32_t *                dest,
   2161                           const uint32_t *          src,
   2162                           const uint32_t *          mask,
   2163                           int                      width)
   2164 {
   2165     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
   2166 }
   2167 
   2168 static void
   2169 combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
   2170                                   pixman_op_t              op,
   2171                                   uint32_t *                dest,
   2172                                   const uint32_t *          src,
   2173                                   const uint32_t *          mask,
   2174                                   int                      width)
   2175 {
   2176     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
   2177 }
   2178 
   2179 static void
   2180 combine_disjoint_xor_ca (pixman_implementation_t *imp,
   2181                          pixman_op_t              op,
   2182                          uint32_t *                dest,
   2183                          const uint32_t *          src,
   2184                          const uint32_t *          mask,
   2185                          int                      width)
   2186 {
   2187     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
   2188 }
   2189 
   2190 static void
   2191 combine_conjoint_general_ca (uint32_t *      dest,
   2192                              const uint32_t *src,
   2193                              const uint32_t *mask,
   2194                              int            width,
   2195                              uint8_t        combine)
   2196 {
   2197     int i;
   2198 
   2199     for (i = 0; i < width; ++i)
   2200     {
   2201 	uint32_t s, d;
   2202 	uint32_t m, n, o, p;
   2203 	uint32_t Fa, Fb;
   2204 	uint16_t t, u, v;
   2205 	uint32_t sa;
   2206 	uint8_t da;
   2207 
   2208 	s = *(src + i);
   2209 	m = *(mask + i);
   2210 	d = *(dest + i);
   2211 	da = d >> A_SHIFT;
   2212 
   2213 	combine_mask_ca (&s, &m);
   2214 
   2215 	sa = m;
   2216 
   2217 	switch (combine & COMBINE_A)
   2218 	{
   2219 	default:
   2220 	    Fa = 0;
   2221 	    break;
   2222 
   2223 	case COMBINE_A_OUT:
   2224 	    m = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> 0), da);
   2225 	    n = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
   2226 	    o = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
   2227 	    p = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
   2228 	    Fa = m | n | o | p;
   2229 	    break;
   2230 
   2231 	case COMBINE_A_IN:
   2232 	    m = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> 0), da);
   2233 	    n = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
   2234 	    o = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
   2235 	    p = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
   2236 	    Fa = m | n | o | p;
   2237 	    break;
   2238 
   2239 	case COMBINE_A:
   2240 	    Fa = ~0;
   2241 	    break;
   2242 	}
   2243 
   2244 	switch (combine & COMBINE_B)
   2245 	{
   2246 	default:
   2247 	    Fb = 0;
   2248 	    break;
   2249 
   2250 	case COMBINE_B_OUT:
   2251 	    m = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> 0));
   2252 	    n = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
   2253 	    o = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
   2254 	    p = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
   2255 	    Fb = m | n | o | p;
   2256 	    break;
   2257 
   2258 	case COMBINE_B_IN:
   2259 	    m = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> 0));
   2260 	    n = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
   2261 	    o = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
   2262 	    p = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
   2263 	    Fb = m | n | o | p;
   2264 	    break;
   2265 
   2266 	case COMBINE_B:
   2267 	    Fb = ~0;
   2268 	    break;
   2269 	}
   2270 	m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
   2271 	n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
   2272 	o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
   2273 	p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
   2274 
   2275 	s = m | n | o | p;
   2276 
   2277 	*(dest + i) = s;
   2278     }
   2279 }
   2280 
   2281 static void
   2282 combine_conjoint_over_ca (pixman_implementation_t *imp,
   2283                           pixman_op_t              op,
   2284                           uint32_t *                dest,
   2285                           const uint32_t *          src,
   2286                           const uint32_t *          mask,
   2287                           int                      width)
   2288 {
   2289     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
   2290 }
   2291 
   2292 static void
   2293 combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
   2294                                   pixman_op_t              op,
   2295                                   uint32_t *                dest,
   2296                                   const uint32_t *          src,
   2297                                   const uint32_t *          mask,
   2298                                   int                      width)
   2299 {
   2300     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
   2301 }
   2302 
   2303 static void
   2304 combine_conjoint_in_ca (pixman_implementation_t *imp,
   2305                         pixman_op_t              op,
   2306                         uint32_t *                dest,
   2307                         const uint32_t *          src,
   2308                         const uint32_t *          mask,
   2309                         int                      width)
   2310 {
   2311     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
   2312 }
   2313 
   2314 static void
   2315 combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
   2316                                 pixman_op_t              op,
   2317                                 uint32_t *                dest,
   2318                                 const uint32_t *          src,
   2319                                 const uint32_t *          mask,
   2320                                 int                      width)
   2321 {
   2322     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
   2323 }
   2324 
   2325 static void
   2326 combine_conjoint_out_ca (pixman_implementation_t *imp,
   2327                          pixman_op_t              op,
   2328                          uint32_t *                dest,
   2329                          const uint32_t *          src,
   2330                          const uint32_t *          mask,
   2331                          int                      width)
   2332 {
   2333     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
   2334 }
   2335 
   2336 static void
   2337 combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
   2338                                  pixman_op_t              op,
   2339                                  uint32_t *                dest,
   2340                                  const uint32_t *          src,
   2341                                  const uint32_t *          mask,
   2342                                  int                      width)
   2343 {
   2344     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
   2345 }
   2346 
   2347 static void
   2348 combine_conjoint_atop_ca (pixman_implementation_t *imp,
   2349                           pixman_op_t              op,
   2350                           uint32_t *                dest,
   2351                           const uint32_t *          src,
   2352                           const uint32_t *          mask,
   2353                           int                      width)
   2354 {
   2355     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
   2356 }
   2357 
   2358 static void
   2359 combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
   2360                                   pixman_op_t              op,
   2361                                   uint32_t *                dest,
   2362                                   const uint32_t *          src,
   2363                                   const uint32_t *          mask,
   2364                                   int                      width)
   2365 {
   2366     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
   2367 }
   2368 
   2369 static void
   2370 combine_conjoint_xor_ca (pixman_implementation_t *imp,
   2371                          pixman_op_t              op,
   2372                          uint32_t *                dest,
   2373                          const uint32_t *          src,
   2374                          const uint32_t *          mask,
   2375                          int                      width)
   2376 {
   2377     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
   2378 }
   2379 
   2380 void
   2381 _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
   2382 {
   2383     /* Unified alpha */
   2384     imp->combine_32[PIXMAN_OP_CLEAR] = combine_clear;
   2385     imp->combine_32[PIXMAN_OP_SRC] = combine_src_u;
   2386     imp->combine_32[PIXMAN_OP_DST] = combine_dst;
   2387     imp->combine_32[PIXMAN_OP_OVER] = combine_over_u;
   2388     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u;
   2389     imp->combine_32[PIXMAN_OP_IN] = combine_in_u;
   2390     imp->combine_32[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u;
   2391     imp->combine_32[PIXMAN_OP_OUT] = combine_out_u;
   2392     imp->combine_32[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u;
   2393     imp->combine_32[PIXMAN_OP_ATOP] = combine_atop_u;
   2394     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
   2395     imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u;
   2396     imp->combine_32[PIXMAN_OP_ADD] = combine_add_u;
   2397     imp->combine_32[PIXMAN_OP_SATURATE] = combine_saturate_u;
   2398 
   2399     /* Disjoint, unified */
   2400     imp->combine_32[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear;
   2401     imp->combine_32[PIXMAN_OP_DISJOINT_SRC] = combine_src_u;
   2402     imp->combine_32[PIXMAN_OP_DISJOINT_DST] = combine_dst;
   2403     imp->combine_32[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u;
   2404     imp->combine_32[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u;
   2405     imp->combine_32[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u;
   2406     imp->combine_32[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u;
   2407     imp->combine_32[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u;
   2408     imp->combine_32[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u;
   2409     imp->combine_32[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u;
   2410     imp->combine_32[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u;
   2411     imp->combine_32[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u;
   2412 
   2413     /* Conjoint, unified */
   2414     imp->combine_32[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear;
   2415     imp->combine_32[PIXMAN_OP_CONJOINT_SRC] = combine_src_u;
   2416     imp->combine_32[PIXMAN_OP_CONJOINT_DST] = combine_dst;
   2417     imp->combine_32[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u;
   2418     imp->combine_32[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u;
   2419     imp->combine_32[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u;
   2420     imp->combine_32[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u;
   2421     imp->combine_32[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u;
   2422     imp->combine_32[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u;
   2423     imp->combine_32[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u;
   2424     imp->combine_32[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u;
   2425     imp->combine_32[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u;
   2426 
   2427     imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
   2428     imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u;
   2429     imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u;
   2430     imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u;
   2431     imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
   2432     imp->combine_32[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u;
   2433     imp->combine_32[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u;
   2434     imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
   2435     imp->combine_32[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u;
   2436     imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
   2437     imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
   2438     imp->combine_32[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u;
   2439     imp->combine_32[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u;
   2440     imp->combine_32[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u;
   2441     imp->combine_32[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u;
   2442 
   2443     /* Component alpha combiners */
   2444     imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
   2445     imp->combine_32_ca[PIXMAN_OP_SRC] = combine_src_ca;
   2446     /* dest */
   2447     imp->combine_32_ca[PIXMAN_OP_OVER] = combine_over_ca;
   2448     imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca;
   2449     imp->combine_32_ca[PIXMAN_OP_IN] = combine_in_ca;
   2450     imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca;
   2451     imp->combine_32_ca[PIXMAN_OP_OUT] = combine_out_ca;
   2452     imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca;
   2453     imp->combine_32_ca[PIXMAN_OP_ATOP] = combine_atop_ca;
   2454     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
   2455     imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca;
   2456     imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca;
   2457     imp->combine_32_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca;
   2458 
   2459     /* Disjoint CA */
   2460     imp->combine_32_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca;
   2461     imp->combine_32_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca;
   2462     imp->combine_32_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst;
   2463     imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca;
   2464     imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca;
   2465     imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca;
   2466     imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca;
   2467     imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca;
   2468     imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca;
   2469     imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca;
   2470     imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca;
   2471     imp->combine_32_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca;
   2472 
   2473     /* Conjoint CA */
   2474     imp->combine_32_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca;
   2475     imp->combine_32_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca;
   2476     imp->combine_32_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst;
   2477     imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca;
   2478     imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca;
   2479     imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca;
   2480     imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca;
   2481     imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca;
   2482     imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca;
   2483     imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca;
   2484     imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca;
   2485     imp->combine_32_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca;
   2486 
   2487     imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
   2488     imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
   2489     imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
   2490     imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
   2491     imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
   2492     imp->combine_32_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca;
   2493     imp->combine_32_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca;
   2494     imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
   2495     imp->combine_32_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca;
   2496     imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
   2497     imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
   2498 
   2499     /* It is not clear that these make sense, so make them noops for now */
   2500     imp->combine_32_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
   2501     imp->combine_32_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
   2502     imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
   2503     imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
   2504 }
   2505