beta-0.89.2
[luatex.git] / source / libs / pixman / pixman-src / pixman / pixman-combine32.c
blob4c484d3e38cc1dedbc62cc10c6ec3389626d14a4
1 /*
2 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
3 * 2005 Lars Knoll & Zack Rusin, Trolltech
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
21 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 * SOFTWARE.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <math.h>
29 #include <string.h>
31 #include "pixman-private.h"
32 #include "pixman-combine32.h"
34 /* component alpha helper functions */
36 static void
37 combine_mask_ca (uint32_t *src, uint32_t *mask)
39 uint32_t a = *mask;
41 uint32_t x;
42 uint16_t xa;
44 if (!a)
46 *(src) = 0;
47 return;
50 x = *(src);
51 if (a == ~0)
53 x = x >> A_SHIFT;
54 x |= x << G_SHIFT;
55 x |= x << R_SHIFT;
56 *(mask) = x;
57 return;
60 xa = x >> A_SHIFT;
61 UN8x4_MUL_UN8x4 (x, a);
62 *(src) = x;
64 UN8x4_MUL_UN8 (a, xa);
65 *(mask) = a;
68 static void
69 combine_mask_value_ca (uint32_t *src, const uint32_t *mask)
71 uint32_t a = *mask;
72 uint32_t x;
74 if (!a)
76 *(src) = 0;
77 return;
80 if (a == ~0)
81 return;
83 x = *(src);
84 UN8x4_MUL_UN8x4 (x, a);
85 *(src) = x;
88 static void
89 combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask)
91 uint32_t a = *(mask);
92 uint32_t x;
94 if (!a)
95 return;
97 x = *(src) >> A_SHIFT;
98 if (x == MASK)
99 return;
101 if (a == ~0)
103 x |= x << G_SHIFT;
104 x |= x << R_SHIFT;
105 *(mask) = x;
106 return;
109 UN8x4_MUL_UN8 (a, x);
110 *(mask) = a;
114 * There are two ways of handling alpha -- either as a single unified value or
115 * a separate value for each component, hence each macro must have two
116 * versions. The unified alpha version has a 'u' at the end of the name,
117 * the component version has a 'ca'. Similarly, functions which deal with
118 * this difference will have two versions using the same convention.
121 static force_inline uint32_t
122 combine_mask (const uint32_t *src, const uint32_t *mask, int i)
124 uint32_t s, m;
126 if (mask)
128 m = *(mask + i) >> A_SHIFT;
130 if (!m)
131 return 0;
134 s = *(src + i);
136 if (mask)
137 UN8x4_MUL_UN8 (s, m);
139 return s;
142 static void
143 combine_clear (pixman_implementation_t *imp,
144 pixman_op_t op,
145 uint32_t * dest,
146 const uint32_t * src,
147 const uint32_t * mask,
148 int width)
150 memset (dest, 0, width * sizeof (uint32_t));
153 static void
154 combine_dst (pixman_implementation_t *imp,
155 pixman_op_t op,
156 uint32_t * dest,
157 const uint32_t * src,
158 const uint32_t * mask,
159 int width)
161 return;
164 static void
165 combine_src_u (pixman_implementation_t *imp,
166 pixman_op_t op,
167 uint32_t * dest,
168 const uint32_t * src,
169 const uint32_t * mask,
170 int width)
172 int i;
174 if (!mask)
176 memcpy (dest, src, width * sizeof (uint32_t));
178 else
180 for (i = 0; i < width; ++i)
182 uint32_t s = combine_mask (src, mask, i);
184 *(dest + i) = s;
189 static void
190 combine_over_u (pixman_implementation_t *imp,
191 pixman_op_t op,
192 uint32_t * dest,
193 const uint32_t * src,
194 const uint32_t * mask,
195 int width)
197 int i;
199 if (!mask)
201 for (i = 0; i < width; ++i)
203 uint32_t s = *(src + i);
204 uint32_t a = ALPHA_8 (s);
205 if (a == 0xFF)
207 *(dest + i) = s;
209 else if (s)
211 uint32_t d = *(dest + i);
212 uint32_t ia = a ^ 0xFF;
213 UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
214 *(dest + i) = d;
218 else
220 for (i = 0; i < width; ++i)
222 uint32_t m = ALPHA_8 (*(mask + i));
223 if (m == 0xFF)
225 uint32_t s = *(src + i);
226 uint32_t a = ALPHA_8 (s);
227 if (a == 0xFF)
229 *(dest + i) = s;
231 else if (s)
233 uint32_t d = *(dest + i);
234 uint32_t ia = a ^ 0xFF;
235 UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
236 *(dest + i) = d;
239 else if (m)
241 uint32_t s = *(src + i);
242 if (s)
244 uint32_t d = *(dest + i);
245 UN8x4_MUL_UN8 (s, m);
246 UN8x4_MUL_UN8_ADD_UN8x4 (d, ALPHA_8 (~s), s);
247 *(dest + i) = d;
254 static void
255 combine_over_reverse_u (pixman_implementation_t *imp,
256 pixman_op_t op,
257 uint32_t * dest,
258 const uint32_t * src,
259 const uint32_t * mask,
260 int width)
262 int i;
264 for (i = 0; i < width; ++i)
266 uint32_t s = combine_mask (src, mask, i);
267 uint32_t d = *(dest + i);
268 uint32_t ia = ALPHA_8 (~*(dest + i));
269 UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
270 *(dest + i) = s;
274 static void
275 combine_in_u (pixman_implementation_t *imp,
276 pixman_op_t op,
277 uint32_t * dest,
278 const uint32_t * src,
279 const uint32_t * mask,
280 int width)
282 int i;
284 for (i = 0; i < width; ++i)
286 uint32_t s = combine_mask (src, mask, i);
287 uint32_t a = ALPHA_8 (*(dest + i));
288 UN8x4_MUL_UN8 (s, a);
289 *(dest + i) = s;
293 static void
294 combine_in_reverse_u (pixman_implementation_t *imp,
295 pixman_op_t op,
296 uint32_t * dest,
297 const uint32_t * src,
298 const uint32_t * mask,
299 int width)
301 int i;
303 for (i = 0; i < width; ++i)
305 uint32_t s = combine_mask (src, mask, i);
306 uint32_t d = *(dest + i);
307 uint32_t a = ALPHA_8 (s);
308 UN8x4_MUL_UN8 (d, a);
309 *(dest + i) = d;
313 static void
314 combine_out_u (pixman_implementation_t *imp,
315 pixman_op_t op,
316 uint32_t * dest,
317 const uint32_t * src,
318 const uint32_t * mask,
319 int width)
321 int i;
323 for (i = 0; i < width; ++i)
325 uint32_t s = combine_mask (src, mask, i);
326 uint32_t a = ALPHA_8 (~*(dest + i));
327 UN8x4_MUL_UN8 (s, a);
328 *(dest + i) = s;
332 static void
333 combine_out_reverse_u (pixman_implementation_t *imp,
334 pixman_op_t op,
335 uint32_t * dest,
336 const uint32_t * src,
337 const uint32_t * mask,
338 int width)
340 int i;
342 for (i = 0; i < width; ++i)
344 uint32_t s = combine_mask (src, mask, i);
345 uint32_t d = *(dest + i);
346 uint32_t a = ALPHA_8 (~s);
347 UN8x4_MUL_UN8 (d, a);
348 *(dest + i) = d;
352 static void
353 combine_atop_u (pixman_implementation_t *imp,
354 pixman_op_t op,
355 uint32_t * dest,
356 const uint32_t * src,
357 const uint32_t * mask,
358 int width)
360 int i;
362 for (i = 0; i < width; ++i)
364 uint32_t s = combine_mask (src, mask, i);
365 uint32_t d = *(dest + i);
366 uint32_t dest_a = ALPHA_8 (d);
367 uint32_t src_ia = ALPHA_8 (~s);
369 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
370 *(dest + i) = s;
374 static void
375 combine_atop_reverse_u (pixman_implementation_t *imp,
376 pixman_op_t op,
377 uint32_t * dest,
378 const uint32_t * src,
379 const uint32_t * mask,
380 int width)
382 int i;
384 for (i = 0; i < width; ++i)
386 uint32_t s = combine_mask (src, mask, i);
387 uint32_t d = *(dest + i);
388 uint32_t src_a = ALPHA_8 (s);
389 uint32_t dest_ia = ALPHA_8 (~d);
391 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
392 *(dest + i) = s;
396 static void
397 combine_xor_u (pixman_implementation_t *imp,
398 pixman_op_t op,
399 uint32_t * dest,
400 const uint32_t * src,
401 const uint32_t * mask,
402 int width)
404 int i;
406 for (i = 0; i < width; ++i)
408 uint32_t s = combine_mask (src, mask, i);
409 uint32_t d = *(dest + i);
410 uint32_t src_ia = ALPHA_8 (~s);
411 uint32_t dest_ia = ALPHA_8 (~d);
413 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
414 *(dest + i) = s;
418 static void
419 combine_add_u (pixman_implementation_t *imp,
420 pixman_op_t op,
421 uint32_t * dest,
422 const uint32_t * src,
423 const uint32_t * mask,
424 int width)
426 int i;
428 for (i = 0; i < width; ++i)
430 uint32_t s = combine_mask (src, mask, i);
431 uint32_t d = *(dest + i);
432 UN8x4_ADD_UN8x4 (d, s);
433 *(dest + i) = d;
438 * PDF blend modes:
440 * The following blend modes have been taken from the PDF ISO 32000
441 * specification, which at this point in time is available from
443 * http://www.adobe.com/devnet/pdf/pdf_reference.html
445 * The specific documents of interest are the PDF spec itself:
447 * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
449 * chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat
450 * 9.1 and Reader 9.1:
452 * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf
454 * that clarifies the specifications for blend modes ColorDodge and
455 * ColorBurn.
457 * The formula for computing the final pixel color given in 11.3.6 is:
459 * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
461 * with B() is the blend function. When B(Cb, Cs) = Cs, this formula
462 * reduces to the regular OVER operator.
464 * Cs and Cb are not premultiplied, so in our implementation we instead
465 * use:
467 * cr = (1 – αs) × cb + (1 – αb) × cs + αb × αs × B (cb/αb, cs/αs)
469 * where cr, cs, and cb are premultiplied colors, and where the
471 * αb × αs × B(cb/αb, cs/αs)
473 * part is first arithmetically simplified under the assumption that αb
474 * and αs are not 0, and then updated to produce a meaningful result when
475 * they are.
477 * For all the blend mode operators, the alpha channel is given by
479 * αr = αs + αb + αb × αs
483 * Multiply
485 * ad * as * B(d / ad, s / as)
486 * = ad * as * d/ad * s/as
487 * = d * s
490 static void
491 combine_multiply_u (pixman_implementation_t *imp,
492 pixman_op_t op,
493 uint32_t * dest,
494 const uint32_t * src,
495 const uint32_t * mask,
496 int width)
498 int i;
500 for (i = 0; i < width; ++i)
502 uint32_t s = combine_mask (src, mask, i);
503 uint32_t d = *(dest + i);
504 uint32_t ss = s;
505 uint32_t src_ia = ALPHA_8 (~s);
506 uint32_t dest_ia = ALPHA_8 (~d);
508 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (ss, dest_ia, d, src_ia);
509 UN8x4_MUL_UN8x4 (d, s);
510 UN8x4_ADD_UN8x4 (d, ss);
512 *(dest + i) = d;
516 static void
517 combine_multiply_ca (pixman_implementation_t *imp,
518 pixman_op_t op,
519 uint32_t * dest,
520 const uint32_t * src,
521 const uint32_t * mask,
522 int width)
524 int i;
526 for (i = 0; i < width; ++i)
528 uint32_t m = *(mask + i);
529 uint32_t s = *(src + i);
530 uint32_t d = *(dest + i);
531 uint32_t r = d;
532 uint32_t dest_ia = ALPHA_8 (~d);
534 combine_mask_ca (&s, &m);
536 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia);
537 UN8x4_MUL_UN8x4 (d, s);
538 UN8x4_ADD_UN8x4 (r, d);
540 *(dest + i) = r;
544 #define CLAMP(v, low, high) \
545 do \
547 if (v < (low)) \
548 v = (low); \
549 if (v > (high)) \
550 v = (high); \
551 } while (0)
553 #define PDF_SEPARABLE_BLEND_MODE(name) \
554 static void \
555 combine_ ## name ## _u (pixman_implementation_t *imp, \
556 pixman_op_t op, \
557 uint32_t * dest, \
558 const uint32_t * src, \
559 const uint32_t * mask, \
560 int width) \
562 int i; \
563 for (i = 0; i < width; ++i) \
565 uint32_t s = combine_mask (src, mask, i); \
566 uint32_t d = *(dest + i); \
567 uint8_t sa = ALPHA_8 (s); \
568 uint8_t isa = ~sa; \
569 uint8_t da = ALPHA_8 (d); \
570 uint8_t ida = ~da; \
571 int32_t ra, rr, rg, rb; \
573 ra = da * 0xff + sa * 0xff - sa * da; \
574 rr = isa * RED_8 (d) + ida * RED_8 (s); \
575 rg = isa * GREEN_8 (d) + ida * GREEN_8 (s); \
576 rb = isa * BLUE_8 (d) + ida * BLUE_8 (s); \
578 rr += blend_ ## name (RED_8 (d), da, RED_8 (s), sa); \
579 rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa); \
580 rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa); \
582 CLAMP (ra, 0, 255 * 255); \
583 CLAMP (rr, 0, 255 * 255); \
584 CLAMP (rg, 0, 255 * 255); \
585 CLAMP (rb, 0, 255 * 255); \
587 ra = DIV_ONE_UN8 (ra); \
588 rr = DIV_ONE_UN8 (rr); \
589 rg = DIV_ONE_UN8 (rg); \
590 rb = DIV_ONE_UN8 (rb); \
592 *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb; \
596 static void \
597 combine_ ## name ## _ca (pixman_implementation_t *imp, \
598 pixman_op_t op, \
599 uint32_t * dest, \
600 const uint32_t * src, \
601 const uint32_t * mask, \
602 int width) \
604 int i; \
605 for (i = 0; i < width; ++i) \
607 uint32_t m = *(mask + i); \
608 uint32_t s = *(src + i); \
609 uint32_t d = *(dest + i); \
610 uint8_t da = ALPHA_8 (d); \
611 uint8_t ida = ~da; \
612 int32_t ra, rr, rg, rb; \
613 uint8_t ira, iga, iba; \
615 combine_mask_ca (&s, &m); \
617 ira = ~RED_8 (m); \
618 iga = ~GREEN_8 (m); \
619 iba = ~BLUE_8 (m); \
621 ra = da * 0xff + ALPHA_8 (s) * 0xff - ALPHA_8 (s) * da; \
622 rr = ira * RED_8 (d) + ida * RED_8 (s); \
623 rg = iga * GREEN_8 (d) + ida * GREEN_8 (s); \
624 rb = iba * BLUE_8 (d) + ida * BLUE_8 (s); \
626 rr += blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)); \
627 rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)); \
628 rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m)); \
630 CLAMP (ra, 0, 255 * 255); \
631 CLAMP (rr, 0, 255 * 255); \
632 CLAMP (rg, 0, 255 * 255); \
633 CLAMP (rb, 0, 255 * 255); \
635 ra = DIV_ONE_UN8 (ra); \
636 rr = DIV_ONE_UN8 (rr); \
637 rg = DIV_ONE_UN8 (rg); \
638 rb = DIV_ONE_UN8 (rb); \
640 *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb; \
645 * Screen
647 * ad * as * B(d/ad, s/as)
648 * = ad * as * (d/ad + s/as - s/as * d/ad)
649 * = ad * s + as * d - s * d
651 static inline int32_t
652 blend_screen (int32_t d, int32_t ad, int32_t s, int32_t as)
654 return s * ad + d * as - s * d;
657 PDF_SEPARABLE_BLEND_MODE (screen)
660 * Overlay
662 * ad * as * B(d/ad, s/as)
663 * = ad * as * Hardlight (s, d)
664 * = if (d / ad < 0.5)
665 * as * ad * Multiply (s/as, 2 * d/ad)
666 * else
667 * as * ad * Screen (s/as, 2 * d / ad - 1)
668 * = if (d < 0.5 * ad)
669 * as * ad * s/as * 2 * d /ad
670 * else
671 * as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1))
672 * = if (2 * d < ad)
673 * 2 * s * d
674 * else
675 * ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1)
676 * = if (2 * d < ad)
677 * 2 * s * d
678 * else
679 * as * ad - 2 * (ad - d) * (as - s)
681 static inline int32_t
682 blend_overlay (int32_t d, int32_t ad, int32_t s, int32_t as)
684 uint32_t r;
686 if (2 * d < ad)
687 r = 2 * s * d;
688 else
689 r = as * ad - 2 * (ad - d) * (as - s);
691 return r;
694 PDF_SEPARABLE_BLEND_MODE (overlay)
697 * Darken
699 * ad * as * B(d/ad, s/as)
700 * = ad * as * MIN(d/ad, s/as)
701 * = MIN (as * d, ad * s)
703 static inline int32_t
704 blend_darken (int32_t d, int32_t ad, int32_t s, int32_t as)
706 s = ad * s;
707 d = as * d;
709 return s > d ? d : s;
712 PDF_SEPARABLE_BLEND_MODE (darken)
715 * Lighten
717 * ad * as * B(d/ad, s/as)
718 * = ad * as * MAX(d/ad, s/as)
719 * = MAX (as * d, ad * s)
721 static inline int32_t
722 blend_lighten (int32_t d, int32_t ad, int32_t s, int32_t as)
724 s = ad * s;
725 d = as * d;
727 return s > d ? s : d;
730 PDF_SEPARABLE_BLEND_MODE (lighten)
733 * Hard light
735 * ad * as * B(d/ad, s/as)
736 * = if (s/as <= 0.5)
737 * ad * as * Multiply (d/ad, 2 * s/as)
738 * else
739 * ad * as * Screen (d/ad, 2 * s/as - 1)
740 * = if 2 * s <= as
741 * ad * as * d/ad * 2 * s / as
742 * else
743 * ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1))
744 * = if 2 * s <= as
745 * 2 * s * d
746 * else
747 * as * ad - 2 * (ad - d) * (as - s)
749 static inline int32_t
750 blend_hard_light (int32_t d, int32_t ad, int32_t s, int32_t as)
752 if (2 * s < as)
753 return 2 * s * d;
754 else
755 return as * ad - 2 * (ad - d) * (as - s);
758 PDF_SEPARABLE_BLEND_MODE (hard_light)
761 * Difference
763 * ad * as * B(s/as, d/ad)
764 * = ad * as * abs (s/as - d/ad)
765 * = if (s/as <= d/ad)
766 * ad * as * (d/ad - s/as)
767 * else
768 * ad * as * (s/as - d/ad)
769 * = if (ad * s <= as * d)
770 * as * d - ad * s
771 * else
772 * ad * s - as * d
774 static inline int32_t
775 blend_difference (int32_t d, int32_t ad, int32_t s, int32_t as)
777 int32_t das = d * as;
778 int32_t sad = s * ad;
780 if (sad < das)
781 return das - sad;
782 else
783 return sad - das;
786 PDF_SEPARABLE_BLEND_MODE (difference)
789 * Exclusion
791 * ad * as * B(s/as, d/ad)
792 * = ad * as * (d/ad + s/as - 2 * d/ad * s/as)
793 * = as * d + ad * s - 2 * s * d
796 /* This can be made faster by writing it directly and not using
797 * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
799 static inline int32_t
800 blend_exclusion (int32_t d, int32_t ad, int32_t s, int32_t as)
802 return s * ad + d * as - 2 * d * s;
805 PDF_SEPARABLE_BLEND_MODE (exclusion)
807 #undef PDF_SEPARABLE_BLEND_MODE
809 /* Component alpha combiners */
811 static void
812 combine_clear_ca (pixman_implementation_t *imp,
813 pixman_op_t op,
814 uint32_t * dest,
815 const uint32_t * src,
816 const uint32_t * mask,
817 int width)
819 memset (dest, 0, width * sizeof(uint32_t));
822 static void
823 combine_src_ca (pixman_implementation_t *imp,
824 pixman_op_t op,
825 uint32_t * dest,
826 const uint32_t * src,
827 const uint32_t * mask,
828 int width)
830 int i;
832 for (i = 0; i < width; ++i)
834 uint32_t s = *(src + i);
835 uint32_t m = *(mask + i);
837 combine_mask_value_ca (&s, &m);
839 *(dest + i) = s;
843 static void
844 combine_over_ca (pixman_implementation_t *imp,
845 pixman_op_t op,
846 uint32_t * dest,
847 const uint32_t * src,
848 const uint32_t * mask,
849 int width)
851 int i;
853 for (i = 0; i < width; ++i)
855 uint32_t s = *(src + i);
856 uint32_t m = *(mask + i);
857 uint32_t a;
859 combine_mask_ca (&s, &m);
861 a = ~m;
862 if (a)
864 uint32_t d = *(dest + i);
865 UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s);
866 s = d;
869 *(dest + i) = s;
873 static void
874 combine_over_reverse_ca (pixman_implementation_t *imp,
875 pixman_op_t op,
876 uint32_t * dest,
877 const uint32_t * src,
878 const uint32_t * mask,
879 int width)
881 int i;
883 for (i = 0; i < width; ++i)
885 uint32_t d = *(dest + i);
886 uint32_t a = ~d >> A_SHIFT;
888 if (a)
890 uint32_t s = *(src + i);
891 uint32_t m = *(mask + i);
893 UN8x4_MUL_UN8x4 (s, m);
894 UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d);
896 *(dest + i) = s;
901 static void
902 combine_in_ca (pixman_implementation_t *imp,
903 pixman_op_t op,
904 uint32_t * dest,
905 const uint32_t * src,
906 const uint32_t * mask,
907 int width)
909 int i;
911 for (i = 0; i < width; ++i)
913 uint32_t d = *(dest + i);
914 uint16_t a = d >> A_SHIFT;
915 uint32_t s = 0;
917 if (a)
919 uint32_t m = *(mask + i);
921 s = *(src + i);
922 combine_mask_value_ca (&s, &m);
924 if (a != MASK)
925 UN8x4_MUL_UN8 (s, a);
928 *(dest + i) = s;
932 static void
933 combine_in_reverse_ca (pixman_implementation_t *imp,
934 pixman_op_t op,
935 uint32_t * dest,
936 const uint32_t * src,
937 const uint32_t * mask,
938 int width)
940 int i;
942 for (i = 0; i < width; ++i)
944 uint32_t s = *(src + i);
945 uint32_t m = *(mask + i);
946 uint32_t a;
948 combine_mask_alpha_ca (&s, &m);
950 a = m;
951 if (a != ~0)
953 uint32_t d = 0;
955 if (a)
957 d = *(dest + i);
958 UN8x4_MUL_UN8x4 (d, a);
961 *(dest + i) = d;
966 static void
967 combine_out_ca (pixman_implementation_t *imp,
968 pixman_op_t op,
969 uint32_t * dest,
970 const uint32_t * src,
971 const uint32_t * mask,
972 int width)
974 int i;
976 for (i = 0; i < width; ++i)
978 uint32_t d = *(dest + i);
979 uint16_t a = ~d >> A_SHIFT;
980 uint32_t s = 0;
982 if (a)
984 uint32_t m = *(mask + i);
986 s = *(src + i);
987 combine_mask_value_ca (&s, &m);
989 if (a != MASK)
990 UN8x4_MUL_UN8 (s, a);
993 *(dest + i) = s;
997 static void
998 combine_out_reverse_ca (pixman_implementation_t *imp,
999 pixman_op_t op,
1000 uint32_t * dest,
1001 const uint32_t * src,
1002 const uint32_t * mask,
1003 int width)
1005 int i;
1007 for (i = 0; i < width; ++i)
1009 uint32_t s = *(src + i);
1010 uint32_t m = *(mask + i);
1011 uint32_t a;
1013 combine_mask_alpha_ca (&s, &m);
1015 a = ~m;
1016 if (a != ~0)
1018 uint32_t d = 0;
1020 if (a)
1022 d = *(dest + i);
1023 UN8x4_MUL_UN8x4 (d, a);
1026 *(dest + i) = d;
1031 static void
1032 combine_atop_ca (pixman_implementation_t *imp,
1033 pixman_op_t op,
1034 uint32_t * dest,
1035 const uint32_t * src,
1036 const uint32_t * mask,
1037 int width)
1039 int i;
1041 for (i = 0; i < width; ++i)
1043 uint32_t d = *(dest + i);
1044 uint32_t s = *(src + i);
1045 uint32_t m = *(mask + i);
1046 uint32_t ad;
1047 uint16_t as = d >> A_SHIFT;
1049 combine_mask_ca (&s, &m);
1051 ad = ~m;
1053 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1055 *(dest + i) = d;
1059 static void
1060 combine_atop_reverse_ca (pixman_implementation_t *imp,
1061 pixman_op_t op,
1062 uint32_t * dest,
1063 const uint32_t * src,
1064 const uint32_t * mask,
1065 int width)
1067 int i;
1069 for (i = 0; i < width; ++i)
1071 uint32_t d = *(dest + i);
1072 uint32_t s = *(src + i);
1073 uint32_t m = *(mask + i);
1074 uint32_t ad;
1075 uint16_t as = ~d >> A_SHIFT;
1077 combine_mask_ca (&s, &m);
1079 ad = m;
1081 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1083 *(dest + i) = d;
1087 static void
1088 combine_xor_ca (pixman_implementation_t *imp,
1089 pixman_op_t op,
1090 uint32_t * dest,
1091 const uint32_t * src,
1092 const uint32_t * mask,
1093 int width)
1095 int i;
1097 for (i = 0; i < width; ++i)
1099 uint32_t d = *(dest + i);
1100 uint32_t s = *(src + i);
1101 uint32_t m = *(mask + i);
1102 uint32_t ad;
1103 uint16_t as = ~d >> A_SHIFT;
1105 combine_mask_ca (&s, &m);
1107 ad = ~m;
1109 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1111 *(dest + i) = d;
1115 static void
1116 combine_add_ca (pixman_implementation_t *imp,
1117 pixman_op_t op,
1118 uint32_t * dest,
1119 const uint32_t * src,
1120 const uint32_t * mask,
1121 int width)
1123 int i;
1125 for (i = 0; i < width; ++i)
1127 uint32_t s = *(src + i);
1128 uint32_t m = *(mask + i);
1129 uint32_t d = *(dest + i);
1131 combine_mask_value_ca (&s, &m);
1133 UN8x4_ADD_UN8x4 (d, s);
1135 *(dest + i) = d;
1139 void
1140 _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
1142 /* Unified alpha */
1143 imp->combine_32[PIXMAN_OP_CLEAR] = combine_clear;
1144 imp->combine_32[PIXMAN_OP_SRC] = combine_src_u;
1145 imp->combine_32[PIXMAN_OP_DST] = combine_dst;
1146 imp->combine_32[PIXMAN_OP_OVER] = combine_over_u;
1147 imp->combine_32[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u;
1148 imp->combine_32[PIXMAN_OP_IN] = combine_in_u;
1149 imp->combine_32[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u;
1150 imp->combine_32[PIXMAN_OP_OUT] = combine_out_u;
1151 imp->combine_32[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u;
1152 imp->combine_32[PIXMAN_OP_ATOP] = combine_atop_u;
1153 imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
1154 imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u;
1155 imp->combine_32[PIXMAN_OP_ADD] = combine_add_u;
1157 imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
1158 imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u;
1159 imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u;
1160 imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u;
1161 imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
1162 imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
1163 imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
1164 imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
1166 /* Component alpha combiners */
1167 imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
1168 imp->combine_32_ca[PIXMAN_OP_SRC] = combine_src_ca;
1169 /* dest */
1170 imp->combine_32_ca[PIXMAN_OP_OVER] = combine_over_ca;
1171 imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca;
1172 imp->combine_32_ca[PIXMAN_OP_IN] = combine_in_ca;
1173 imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca;
1174 imp->combine_32_ca[PIXMAN_OP_OUT] = combine_out_ca;
1175 imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca;
1176 imp->combine_32_ca[PIXMAN_OP_ATOP] = combine_atop_ca;
1177 imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
1178 imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca;
1179 imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca;
1181 imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
1182 imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
1183 imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
1184 imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
1185 imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
1186 imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
1187 imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
1188 imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;