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