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