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