SkXfermode.cpp revision b0a8a377f832c59cee939ad721e1f87d378b7142
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkXfermode.h"
11#include "SkXfermode_opts_SSE2.h"
12#include "SkXfermode_proccoeff.h"
13#include "SkColorPriv.h"
14#include "SkLazyPtr.h"
15#include "SkMathPriv.h"
16#include "SkReadBuffer.h"
17#include "SkString.h"
18#include "SkUtilsArm.h"
19#include "SkWriteBuffer.h"
20
21#if !SK_ARM_NEON_IS_NONE
22#include "SkXfermode_opts_arm_neon.h"
23#endif
24
25#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
26
27#if 0
28// idea for higher precision blends in xfer procs (and slightly faster)
29// see DstATop as a probable caller
30static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
31    SkASSERT(a <= 255);
32    SkASSERT(b <= 255);
33    SkASSERT(c <= 255);
34    SkASSERT(d <= 255);
35    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
36    unsigned result = (prod + (prod >> 8)) >> 8;
37    SkASSERT(result <= 255);
38    return result;
39}
40#endif
41
42static inline unsigned saturated_add(unsigned a, unsigned b) {
43    SkASSERT(a <= 255);
44    SkASSERT(b <= 255);
45    unsigned sum = a + b;
46    if (sum > 255) {
47        sum = 255;
48    }
49    return sum;
50}
51
52static inline int clamp_signed_byte(int n) {
53    if (n < 0) {
54        n = 0;
55    } else if (n > 255) {
56        n = 255;
57    }
58    return n;
59}
60
61static inline int clamp_div255round(int prod) {
62    if (prod <= 0) {
63        return 0;
64    } else if (prod >= 255*255) {
65        return 255;
66    } else {
67        return SkDiv255Round(prod);
68    }
69}
70
71///////////////////////////////////////////////////////////////////////////////
72
73//  kClear_Mode,    //!< [0, 0]
74static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75    return 0;
76}
77
78//  kSrc_Mode,      //!< [Sa, Sc]
79static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80    return src;
81}
82
83//  kDst_Mode,      //!< [Da, Dc]
84static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
85    return dst;
86}
87
88//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
89static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
90#if 0
91    // this is the old, more-correct way, but it doesn't guarantee that dst==255
92    // will always stay opaque
93    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
94#else
95    // this is slightly faster, but more importantly guarantees that dst==255
96    // will always stay opaque
97    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
98#endif
99}
100
101//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
102static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
103    // this is the reverse of srcover, just flipping src and dst
104    // see srcover's comment about the 256 for opaqueness guarantees
105    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
106}
107
108//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
109static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
110    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
111}
112
113//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
114static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
115    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
116}
117
118//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
119static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
120    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
121}
122
123//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
124static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
125    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
126}
127
128//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
129static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
130    unsigned sa = SkGetPackedA32(src);
131    unsigned da = SkGetPackedA32(dst);
132    unsigned isa = 255 - sa;
133
134    return SkPackARGB32(da,
135                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
136                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
137                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
138                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
139                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
140                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
141}
142
143//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
144static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
145    unsigned sa = SkGetPackedA32(src);
146    unsigned da = SkGetPackedA32(dst);
147    unsigned ida = 255 - da;
148
149    return SkPackARGB32(sa,
150                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
151                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
152                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
153                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
154                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
155                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
156}
157
158//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
159static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
160    unsigned sa = SkGetPackedA32(src);
161    unsigned da = SkGetPackedA32(dst);
162    unsigned isa = 255 - sa;
163    unsigned ida = 255 - da;
164
165    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
166                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
167                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
168                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
169                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
170                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
171                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
172}
173
174///////////////////////////////////////////////////////////////////////////////
175
176// kPlus_Mode
177static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
178    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
179    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
180    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
181    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
182    return SkPackARGB32(a, r, g, b);
183}
184
185// kModulate_Mode
186static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
187    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
188    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
189    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
190    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
191    return SkPackARGB32(a, r, g, b);
192}
193
194static inline int srcover_byte(int a, int b) {
195    return a + b - SkAlphaMulAlpha(a, b);
196}
197
198// kMultiply_Mode
199// B(Cb, Cs) = Cb x Cs
200// multiply uses its own version of blendfunc_byte because sa and da are not needed
201static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
202    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
203}
204
205static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
206    int sa = SkGetPackedA32(src);
207    int da = SkGetPackedA32(dst);
208    int a = srcover_byte(sa, da);
209    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
210    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
211    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
212    return SkPackARGB32(a, r, g, b);
213}
214
215// kScreen_Mode
216static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
217    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
218    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
219    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
220    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
221    return SkPackARGB32(a, r, g, b);
222}
223
224// kOverlay_Mode
225static inline int overlay_byte(int sc, int dc, int sa, int da) {
226    int tmp = sc * (255 - da) + dc * (255 - sa);
227    int rc;
228    if (2 * dc <= da) {
229        rc = 2 * sc * dc;
230    } else {
231        rc = sa * da - 2 * (da - dc) * (sa - sc);
232    }
233    return clamp_div255round(rc + tmp);
234}
235static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
236    int sa = SkGetPackedA32(src);
237    int da = SkGetPackedA32(dst);
238    int a = srcover_byte(sa, da);
239    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
240    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
241    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
242    return SkPackARGB32(a, r, g, b);
243}
244
245// kDarken_Mode
246static inline int darken_byte(int sc, int dc, int sa, int da) {
247    int sd = sc * da;
248    int ds = dc * sa;
249    if (sd < ds) {
250        // srcover
251        return sc + dc - SkDiv255Round(ds);
252    } else {
253        // dstover
254        return dc + sc - SkDiv255Round(sd);
255    }
256}
257static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
258    int sa = SkGetPackedA32(src);
259    int da = SkGetPackedA32(dst);
260    int a = srcover_byte(sa, da);
261    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
262    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
263    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
264    return SkPackARGB32(a, r, g, b);
265}
266
267// kLighten_Mode
268static inline int lighten_byte(int sc, int dc, int sa, int da) {
269    int sd = sc * da;
270    int ds = dc * sa;
271    if (sd > ds) {
272        // srcover
273        return sc + dc - SkDiv255Round(ds);
274    } else {
275        // dstover
276        return dc + sc - SkDiv255Round(sd);
277    }
278}
279static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
280    int sa = SkGetPackedA32(src);
281    int da = SkGetPackedA32(dst);
282    int a = srcover_byte(sa, da);
283    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
284    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
285    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
286    return SkPackARGB32(a, r, g, b);
287}
288
289// kColorDodge_Mode
290static inline int colordodge_byte(int sc, int dc, int sa, int da) {
291    int diff = sa - sc;
292    int rc;
293    if (0 == dc) {
294        return SkAlphaMulAlpha(sc, 255 - da);
295    } else if (0 == diff) {
296        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
297    } else {
298        diff = dc * sa / diff;
299        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
300    }
301    return clamp_div255round(rc);
302}
303static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
304    int sa = SkGetPackedA32(src);
305    int da = SkGetPackedA32(dst);
306    int a = srcover_byte(sa, da);
307    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
308    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
309    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
310    return SkPackARGB32(a, r, g, b);
311}
312
313// kColorBurn_Mode
314static inline int colorburn_byte(int sc, int dc, int sa, int da) {
315    int rc;
316    if (dc == da) {
317        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
318    } else if (0 == sc) {
319        return SkAlphaMulAlpha(dc, 255 - sa);
320    } else {
321        int tmp = (da - dc) * sa / sc;
322        rc = sa * (da - ((da < tmp) ? da : tmp))
323            + sc * (255 - da) + dc * (255 - sa);
324    }
325    return clamp_div255round(rc);
326}
327static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
328    int sa = SkGetPackedA32(src);
329    int da = SkGetPackedA32(dst);
330    int a = srcover_byte(sa, da);
331    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
332    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
333    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
334    return SkPackARGB32(a, r, g, b);
335}
336
337// kHardLight_Mode
338static inline int hardlight_byte(int sc, int dc, int sa, int da) {
339    int rc;
340    if (2 * sc <= sa) {
341        rc = 2 * sc * dc;
342    } else {
343        rc = sa * da - 2 * (da - dc) * (sa - sc);
344    }
345    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
346}
347static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
348    int sa = SkGetPackedA32(src);
349    int da = SkGetPackedA32(dst);
350    int a = srcover_byte(sa, da);
351    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
352    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
353    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
354    return SkPackARGB32(a, r, g, b);
355}
356
357// returns 255 * sqrt(n/255)
358static U8CPU sqrt_unit_byte(U8CPU n) {
359    return SkSqrtBits(n, 15+4);
360}
361
362// kSoftLight_Mode
363static inline int softlight_byte(int sc, int dc, int sa, int da) {
364    int m = da ? dc * 256 / da : 0;
365    int rc;
366    if (2 * sc <= sa) {
367        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
368    } else if (4 * dc <= da) {
369        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
370        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
371    } else {
372        int tmp = sqrt_unit_byte(m) - m;
373        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
374    }
375    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
376}
377static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
378    int sa = SkGetPackedA32(src);
379    int da = SkGetPackedA32(dst);
380    int a = srcover_byte(sa, da);
381    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
382    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
383    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
384    return SkPackARGB32(a, r, g, b);
385}
386
387// kDifference_Mode
388static inline int difference_byte(int sc, int dc, int sa, int da) {
389    int tmp = SkMin32(sc * da, dc * sa);
390    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
391}
392static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
393    int sa = SkGetPackedA32(src);
394    int da = SkGetPackedA32(dst);
395    int a = srcover_byte(sa, da);
396    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
397    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
398    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
399    return SkPackARGB32(a, r, g, b);
400}
401
402// kExclusion_Mode
403static inline int exclusion_byte(int sc, int dc, int, int) {
404    // this equations is wacky, wait for SVG to confirm it
405    //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
406
407    // The above equation can be simplified as follows
408    int r = 255*(sc + dc) - 2 * sc * dc;
409    return clamp_div255round(r);
410}
411static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
412    int sa = SkGetPackedA32(src);
413    int da = SkGetPackedA32(dst);
414    int a = srcover_byte(sa, da);
415    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
416    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
417    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
418    return SkPackARGB32(a, r, g, b);
419}
420
421// The CSS compositing spec introduces the following formulas:
422// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
423// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
424// while PDF and CG uses the one from Rec. Rec. 601
425// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
426static inline int Lum(int r, int g, int b)
427{
428    return SkDiv255Round(r * 77 + g * 150 + b * 28);
429}
430
431static inline int min2(int a, int b) { return a < b ? a : b; }
432static inline int max2(int a, int b) { return a > b ? a : b; }
433#define minimum(a, b, c) min2(min2(a, b), c)
434#define maximum(a, b, c) max2(max2(a, b), c)
435
436static inline int Sat(int r, int g, int b) {
437    return maximum(r, g, b) - minimum(r, g, b);
438}
439
440static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
441    if(*Cmax > *Cmin) {
442        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
443        *Cmax = s;
444    } else {
445        *Cmax = 0;
446        *Cmid = 0;
447    }
448
449    *Cmin = 0;
450}
451
452static inline void SetSat(int* r, int* g, int* b, int s) {
453    if(*r <= *g) {
454        if(*g <= *b) {
455            setSaturationComponents(r, g, b, s);
456        } else if(*r <= *b) {
457            setSaturationComponents(r, b, g, s);
458        } else {
459            setSaturationComponents(b, r, g, s);
460        }
461    } else if(*r <= *b) {
462        setSaturationComponents(g, r, b, s);
463    } else if(*g <= *b) {
464        setSaturationComponents(g, b, r, s);
465    } else {
466        setSaturationComponents(b, g, r, s);
467    }
468}
469
470static inline void clipColor(int* r, int* g, int* b, int a) {
471    int L = Lum(*r, *g, *b);
472    int n = minimum(*r, *g, *b);
473    int x = maximum(*r, *g, *b);
474    int denom;
475    if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
476       *r = L + SkMulDiv(*r - L, L, denom);
477       *g = L + SkMulDiv(*g - L, L, denom);
478       *b = L + SkMulDiv(*b - L, L, denom);
479    }
480
481    if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
482       int numer = a - L;
483       *r = L + SkMulDiv(*r - L, numer, denom);
484       *g = L + SkMulDiv(*g - L, numer, denom);
485       *b = L + SkMulDiv(*b - L, numer, denom);
486    }
487}
488
489static inline void SetLum(int* r, int* g, int* b, int a, int l) {
490  int d = l - Lum(*r, *g, *b);
491  *r +=  d;
492  *g +=  d;
493  *b +=  d;
494
495  clipColor(r, g, b, a);
496}
497
498// non-separable blend modes are done in non-premultiplied alpha
499#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
500  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
501
502// kHue_Mode
503// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
504// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
505static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
506    int sr = SkGetPackedR32(src);
507    int sg = SkGetPackedG32(src);
508    int sb = SkGetPackedB32(src);
509    int sa = SkGetPackedA32(src);
510
511    int dr = SkGetPackedR32(dst);
512    int dg = SkGetPackedG32(dst);
513    int db = SkGetPackedB32(dst);
514    int da = SkGetPackedA32(dst);
515    int Sr, Sg, Sb;
516
517    if(sa && da) {
518        Sr = sr * sa;
519        Sg = sg * sa;
520        Sb = sb * sa;
521        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
522        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
523    } else {
524        Sr = 0;
525        Sg = 0;
526        Sb = 0;
527    }
528
529    int a = srcover_byte(sa, da);
530    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
531    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
532    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
533    return SkPackARGB32(a, r, g, b);
534}
535
536// kSaturation_Mode
537// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
538// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
539static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
540    int sr = SkGetPackedR32(src);
541    int sg = SkGetPackedG32(src);
542    int sb = SkGetPackedB32(src);
543    int sa = SkGetPackedA32(src);
544
545    int dr = SkGetPackedR32(dst);
546    int dg = SkGetPackedG32(dst);
547    int db = SkGetPackedB32(dst);
548    int da = SkGetPackedA32(dst);
549    int Dr, Dg, Db;
550
551    if(sa && da) {
552        Dr = dr * sa;
553        Dg = dg * sa;
554        Db = db * sa;
555        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
556        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
557    } else {
558        Dr = 0;
559        Dg = 0;
560        Db = 0;
561    }
562
563    int a = srcover_byte(sa, da);
564    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
565    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
566    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
567    return SkPackARGB32(a, r, g, b);
568}
569
570// kColor_Mode
571// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
572// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
573static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
574    int sr = SkGetPackedR32(src);
575    int sg = SkGetPackedG32(src);
576    int sb = SkGetPackedB32(src);
577    int sa = SkGetPackedA32(src);
578
579    int dr = SkGetPackedR32(dst);
580    int dg = SkGetPackedG32(dst);
581    int db = SkGetPackedB32(dst);
582    int da = SkGetPackedA32(dst);
583    int Sr, Sg, Sb;
584
585    if(sa && da) {
586        Sr = sr * da;
587        Sg = sg * da;
588        Sb = sb * da;
589        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
590    } else {
591        Sr = 0;
592        Sg = 0;
593        Sb = 0;
594    }
595
596    int a = srcover_byte(sa, da);
597    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
598    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
599    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
600    return SkPackARGB32(a, r, g, b);
601}
602
603// kLuminosity_Mode
604// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
605// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
606static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
607    int sr = SkGetPackedR32(src);
608    int sg = SkGetPackedG32(src);
609    int sb = SkGetPackedB32(src);
610    int sa = SkGetPackedA32(src);
611
612    int dr = SkGetPackedR32(dst);
613    int dg = SkGetPackedG32(dst);
614    int db = SkGetPackedB32(dst);
615    int da = SkGetPackedA32(dst);
616    int Dr, Dg, Db;
617
618    if(sa && da) {
619        Dr = dr * sa;
620        Dg = dg * sa;
621        Db = db * sa;
622        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
623    } else {
624        Dr = 0;
625        Dg = 0;
626        Db = 0;
627    }
628
629    int a = srcover_byte(sa, da);
630    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
631    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
632    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
633    return SkPackARGB32(a, r, g, b);
634}
635
636const ProcCoeff gProcCoeffs[] = {
637    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
638    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
639    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
640    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
641    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
642    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
643    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
644    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
645    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
646    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
647    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
648    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
649
650    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
651    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
652    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
653    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
654    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
655    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
656    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
657    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
662    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
663    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
664    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
665    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
666    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
667};
668
669///////////////////////////////////////////////////////////////////////////////
670
671bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
672    return false;
673}
674
675bool SkXfermode::asMode(Mode* mode) const {
676    return false;
677}
678
679bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
680    return false;
681}
682
683bool SkXfermode::asFragmentProcessorOrCoeff(SkXfermode* xfermode, GrFragmentProcessor** fp,
684                                            Coeff* src, Coeff* dst, GrTexture* background) {
685    if (NULL == xfermode) {
686        return ModeAsCoeff(kSrcOver_Mode, src, dst);
687    } else if (xfermode->asCoeff(src, dst)) {
688        return true;
689    } else {
690        return xfermode->asFragmentProcessor(fp, background);
691    }
692}
693
694SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
695    // no-op. subclasses should override this
696    return dst;
697}
698
699void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
700                        const SkPMColor* SK_RESTRICT src, int count,
701                        const SkAlpha* SK_RESTRICT aa) const {
702    SkASSERT(dst && src && count >= 0);
703
704    if (NULL == aa) {
705        for (int i = count - 1; i >= 0; --i) {
706            dst[i] = this->xferColor(src[i], dst[i]);
707        }
708    } else {
709        for (int i = count - 1; i >= 0; --i) {
710            unsigned a = aa[i];
711            if (0 != a) {
712                SkPMColor dstC = dst[i];
713                SkPMColor C = this->xferColor(src[i], dstC);
714                if (0xFF != a) {
715                    C = SkFourByteInterp(C, dstC, a);
716                }
717                dst[i] = C;
718            }
719        }
720    }
721}
722
723void SkXfermode::xfer16(uint16_t* dst,
724                        const SkPMColor* SK_RESTRICT src, int count,
725                        const SkAlpha* SK_RESTRICT aa) const {
726    SkASSERT(dst && src && count >= 0);
727
728    if (NULL == aa) {
729        for (int i = count - 1; i >= 0; --i) {
730            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
731            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
732        }
733    } else {
734        for (int i = count - 1; i >= 0; --i) {
735            unsigned a = aa[i];
736            if (0 != a) {
737                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
738                SkPMColor C = this->xferColor(src[i], dstC);
739                if (0xFF != a) {
740                    C = SkFourByteInterp(C, dstC, a);
741                }
742                dst[i] = SkPixel32ToPixel16_ToU16(C);
743            }
744        }
745    }
746}
747
748void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
749                        const SkPMColor src[], int count,
750                        const SkAlpha* SK_RESTRICT aa) const {
751    SkASSERT(dst && src && count >= 0);
752
753    if (NULL == aa) {
754        for (int i = count - 1; i >= 0; --i) {
755            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
756            dst[i] = SkToU8(SkGetPackedA32(res));
757        }
758    } else {
759        for (int i = count - 1; i >= 0; --i) {
760            unsigned a = aa[i];
761            if (0 != a) {
762                SkAlpha dstA = dst[i];
763                unsigned A = SkGetPackedA32(this->xferColor(src[i],
764                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
765                if (0xFF != a) {
766                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
767                }
768                dst[i] = SkToU8(A);
769            }
770        }
771    }
772}
773
774//////////////////////////////////////////////////////////////////////////////
775
776#if SK_SUPPORT_GPU
777
778#include "GrProcessor.h"
779#include "GrCoordTransform.h"
780#include "GrProcessorUnitTest.h"
781#include "GrTBackendProcessorFactory.h"
782#include "gl/GrGLProcessor.h"
783#include "gl/builders/GrGLProgramBuilder.h"
784
785/**
786 * GrProcessor that implements the all the separable xfer modes that cannot be expressed as Coeffs.
787 */
788class XferEffect : public GrFragmentProcessor {
789public:
790    static bool IsSupportedMode(SkXfermode::Mode mode) {
791        return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
792    }
793
794    static GrFragmentProcessor* Create(SkXfermode::Mode mode, GrTexture* background) {
795        if (!IsSupportedMode(mode)) {
796            return NULL;
797        } else {
798            return SkNEW_ARGS(XferEffect, (mode, background));
799        }
800    }
801
802    virtual void getConstantColorComponents(GrColor* color,
803                                            uint32_t* validFlags) const SK_OVERRIDE {
804        *validFlags = 0;
805    }
806
807    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
808        return GrTBackendFragmentProcessorFactory<XferEffect>::getInstance();
809    }
810
811    static const char* Name() { return "XferEffect"; }
812
813    SkXfermode::Mode mode() const { return fMode; }
814    const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
815
816    class GLProcessor : public GrGLFragmentProcessor {
817    public:
818        GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
819            : INHERITED(factory) {
820        }
821        virtual void emitCode(GrGLProgramBuilder* builder,
822                              const GrFragmentProcessor& fp,
823                              const GrProcessorKey& key,
824                              const char* outputColor,
825                              const char* inputColor,
826                              const TransformedCoordsArray& coords,
827                              const TextureSamplerArray& samplers) SK_OVERRIDE {
828            SkXfermode::Mode mode = fp.cast<XferEffect>().mode();
829            const GrTexture* backgroundTex =
830                    fp.cast<XferEffect>().backgroundAccess().getTexture();
831            GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
832            const char* dstColor;
833            if (backgroundTex) {
834                dstColor = "bgColor";
835                fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor);
836                fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
837                fsBuilder->codeAppendf(";\n");
838            } else {
839                dstColor = fsBuilder->dstColor();
840            }
841            SkASSERT(dstColor);
842
843            // We don't try to optimize for this case at all
844            if (NULL == inputColor) {
845                fsBuilder->codeAppendf("\t\tconst vec4 ones = vec4(1);\n");
846                inputColor = "ones";
847            }
848            fsBuilder->codeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
849
850            // These all perform src-over on the alpha channel.
851            fsBuilder->codeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
852                                    outputColor, inputColor, inputColor, dstColor);
853
854            switch (mode) {
855                case SkXfermode::kOverlay_Mode:
856                    // Overlay is Hard-Light with the src and dst reversed
857                    HardLight(fsBuilder, outputColor, dstColor, inputColor);
858                    break;
859                case SkXfermode::kDarken_Mode:
860                    fsBuilder->codeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
861                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
862                                            outputColor,
863                                            inputColor, dstColor, inputColor,
864                                            dstColor, inputColor, dstColor);
865                    break;
866                case SkXfermode::kLighten_Mode:
867                    fsBuilder->codeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
868                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
869                                            outputColor,
870                                            inputColor, dstColor, inputColor,
871                                            dstColor, inputColor, dstColor);
872                    break;
873                case SkXfermode::kColorDodge_Mode:
874                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
875                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
876                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
877                    break;
878                case SkXfermode::kColorBurn_Mode:
879                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
880                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
881                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
882                    break;
883                case SkXfermode::kHardLight_Mode:
884                    HardLight(fsBuilder, outputColor, inputColor, dstColor);
885                    break;
886                case SkXfermode::kSoftLight_Mode:
887                    fsBuilder->codeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
888                    fsBuilder->codeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
889                    fsBuilder->codeAppendf("\t\t} else {\n");
890                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'r');
891                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'g');
892                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'b');
893                    fsBuilder->codeAppendf("\t\t}\n");
894                    break;
895                case SkXfermode::kDifference_Mode:
896                    fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
897                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
898                                           outputColor, inputColor, dstColor, inputColor, dstColor,
899                                           dstColor, inputColor);
900                    break;
901                case SkXfermode::kExclusion_Mode:
902                    fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
903                                                        "2.0 * %s.rgb * %s.rgb;\n",
904                                           outputColor, dstColor, inputColor, dstColor, inputColor);
905                    break;
906                case SkXfermode::kMultiply_Mode:
907                    fsBuilder->codeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
908                                                        "(1.0 - %s.a) * %s.rgb + "
909                                                         "%s.rgb * %s.rgb;\n",
910                                           outputColor, inputColor, dstColor, dstColor, inputColor,
911                                           inputColor, dstColor);
912                    break;
913                case SkXfermode::kHue_Mode: {
914                    //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
915                    SkString setSat, setLum;
916                    AddSatFunction(fsBuilder, &setSat);
917                    AddLumFunction(fsBuilder, &setLum);
918                    fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
919                                           dstColor, inputColor);
920                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
921                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
922                                           dstColor);
923                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
924                                           outputColor, inputColor, dstColor, dstColor, inputColor);
925                    break;
926                }
927                case SkXfermode::kSaturation_Mode: {
928                    // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
929                    SkString setSat, setLum;
930                    AddSatFunction(fsBuilder, &setSat);
931                    AddLumFunction(fsBuilder, &setLum);
932                    fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
933                                           dstColor, inputColor);
934                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
935                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
936                                           dstColor);
937                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
938                                           outputColor, inputColor, dstColor, dstColor, inputColor);
939                    break;
940                }
941                case SkXfermode::kColor_Mode: {
942                    //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
943                    SkString setLum;
944                    AddLumFunction(fsBuilder, &setLum);
945                    fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
946                                           inputColor, dstColor);
947                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
948                                           outputColor, setLum.c_str(), dstColor, inputColor);
949                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
950                                           outputColor, inputColor, dstColor, dstColor, inputColor);
951                    break;
952                }
953                case SkXfermode::kLuminosity_Mode: {
954                    //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
955                    SkString setLum;
956                    AddLumFunction(fsBuilder, &setLum);
957                    fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
958                                           inputColor, dstColor);
959                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
960                                           outputColor, setLum.c_str(), dstColor, inputColor);
961                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
962                                           outputColor, inputColor, dstColor, dstColor, inputColor);
963                    break;
964                }
965                default:
966                    SkFAIL("Unknown XferEffect mode.");
967                    break;
968            }
969        }
970
971        static inline void GenKey(const GrProcessor& proc, const GrGLCaps&,
972                                  GrProcessorKeyBuilder* b) {
973            // The background may come from the dst or from a texture.
974            uint32_t key = proc.numTextures();
975            SkASSERT(key <= 1);
976            key |= proc.cast<XferEffect>().mode() << 1;
977            b->add32(key);
978        }
979
980    private:
981        static void HardLight(GrGLFragmentShaderBuilder* fsBuilder,
982                              const char* final,
983                              const char* src,
984                              const char* dst) {
985            static const char kComponents[] = {'r', 'g', 'b'};
986            for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
987                char component = kComponents[i];
988                fsBuilder->codeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
989                fsBuilder->codeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
990                fsBuilder->codeAppend("\t\t} else {\n");
991                fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
992                                       final, component, src, dst, dst, dst, component, src, src, component);
993                fsBuilder->codeAppend("\t\t}\n");
994            }
995            fsBuilder->codeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
996                                   final, src, dst, dst, src);
997        }
998
999        // Does one component of color-dodge
1000        static void ColorDodgeComponent(GrGLFragmentShaderBuilder* fsBuilder,
1001                                        const char* final,
1002                                        const char* src,
1003                                        const char* dst,
1004                                        const char component) {
1005            fsBuilder->codeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1006            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1007                                   final, component, src, component, dst);
1008            fsBuilder->codeAppend("\t\t} else {\n");
1009            fsBuilder->codeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1010            fsBuilder->codeAppend("\t\t\tif (0.0 == d) {\n");
1011            fsBuilder->codeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1012                                   final, component, src, dst, src, component, dst, dst, component,
1013                                   src);
1014            fsBuilder->codeAppend("\t\t\t} else {\n");
1015            fsBuilder->codeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1016                                   dst, dst, component, src);
1017            fsBuilder->codeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1018                                   final, component, src, src, component, dst, dst, component, src);
1019            fsBuilder->codeAppend("\t\t\t}\n");
1020            fsBuilder->codeAppend("\t\t}\n");
1021        }
1022
1023        // Does one component of color-burn
1024        static void ColorBurnComponent(GrGLFragmentShaderBuilder* fsBuilder,
1025                                       const char* final,
1026                                       const char* src,
1027                                       const char* dst,
1028                                       const char component) {
1029            fsBuilder->codeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1030            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1031                                   final, component, src, dst, src, component, dst, dst, component,
1032                                   src);
1033            fsBuilder->codeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1034            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1035                                   final, component, dst, component, src);
1036            fsBuilder->codeAppend("\t\t} else {\n");
1037            fsBuilder->codeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1038                                   dst, dst, dst, component, src, src, component);
1039            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1040                                   final, component, src, src, component, dst, dst, component, src);
1041            fsBuilder->codeAppend("\t\t}\n");
1042        }
1043
1044        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1045        static void SoftLightComponentPosDstAlpha(GrGLFragmentShaderBuilder* fsBuilder,
1046                                                  const char* final,
1047                                                  const char* src,
1048                                                  const char* dst,
1049                                                  const char component) {
1050            // if (2S < Sa)
1051            fsBuilder->codeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1052            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1053            fsBuilder->codeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
1054                                   final, component, dst, component, dst, component, src, src,
1055                                   component, dst, dst, src, component, dst, component, src, src,
1056                                   component);
1057            // else if (4D < Da)
1058            fsBuilder->codeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1059                                   dst, component, dst);
1060            fsBuilder->codeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1061                                   dst, component, dst, component);
1062            fsBuilder->codeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1063            fsBuilder->codeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1064            fsBuilder->codeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1065            // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
1066            fsBuilder->codeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
1067                                   final, component, src, component, src, component, dst, component,
1068                                   src, src, component, dst, src, src, component, src, src,
1069                                   component);
1070            fsBuilder->codeAppendf("\t\t\t} else {\n");
1071            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1072            fsBuilder->codeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
1073                                    final, component, dst, dst, component, src, src, component, dst,
1074                                    src, component, dst, component, src, src, component, src,
1075                                    component);
1076            fsBuilder->codeAppendf("\t\t\t}\n");
1077        }
1078
1079        // Adds a function that takes two colors and an alpha as input. It produces a color with the
1080        // hue and saturation of the first color, the luminosity of the second color, and the input
1081        // alpha. It has this signature:
1082        //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1083        static void AddLumFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setLumFunction) {
1084            // Emit a helper that gets the luminance of a color.
1085            SkString getFunction;
1086            GrGLShaderVar getLumArgs[] = {
1087                GrGLShaderVar("color", kVec3f_GrSLType),
1088            };
1089            SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1090            fsBuilder->emitFunction(kFloat_GrSLType,
1091                                    "luminance",
1092                                    SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1093                                    getLumBody.c_str(),
1094                                    &getFunction);
1095
1096            // Emit the set luminance function.
1097            GrGLShaderVar setLumArgs[] = {
1098                GrGLShaderVar("hueSat", kVec3f_GrSLType),
1099                GrGLShaderVar("alpha", kFloat_GrSLType),
1100                GrGLShaderVar("lumColor", kVec3f_GrSLType),
1101            };
1102            SkString setLumBody;
1103            setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1104            setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1105            setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1106            setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1107                              "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1108                              "\tif (minComp < 0.0) {\n"
1109                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1110                              "\t}\n"
1111                              "\tif (maxComp > alpha) {\n"
1112                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1113                              "\t}\n"
1114                              "\treturn outColor;\n");
1115            fsBuilder->emitFunction(kVec3f_GrSLType,
1116                                    "set_luminance",
1117                                    SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1118                                    setLumBody.c_str(),
1119                                    setLumFunction);
1120        }
1121
1122        // Adds a function that creates a color with the hue and luminosity of one input color and
1123        // the saturation of another color. It will have this signature:
1124        //      float set_saturation(vec3 hueLumColor, vec3 satColor)
1125        static void AddSatFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setSatFunction) {
1126            // Emit a helper that gets the saturation of a color
1127            SkString getFunction;
1128            GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1129            SkString getSatBody;
1130            getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1131                              "min(min(color.r, color.g), color.b);\n");
1132            fsBuilder->emitFunction(kFloat_GrSLType,
1133                                    "saturation",
1134                                    SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1135                                    getSatBody.c_str(),
1136                                    &getFunction);
1137
1138            // Emit a helper that sets the saturation given sorted input channels. This used
1139            // to use inout params for min, mid, and max components but that seems to cause
1140            // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1141            // adjusted min, mid, and max inputs, respectively.
1142            SkString helperFunction;
1143            GrGLShaderVar helperArgs[] = {
1144                GrGLShaderVar("minComp", kFloat_GrSLType),
1145                GrGLShaderVar("midComp", kFloat_GrSLType),
1146                GrGLShaderVar("maxComp", kFloat_GrSLType),
1147                GrGLShaderVar("sat", kFloat_GrSLType),
1148            };
1149            static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1150                                              "\t\tvec3 result;\n"
1151                                              "\t\tresult.r = 0.0;\n"
1152                                              "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1153                                              "\t\tresult.b = sat;\n"
1154                                              "\t\treturn result;\n"
1155                                              "\t} else {\n"
1156                                              "\t\treturn vec3(0, 0, 0);\n"
1157                                              "\t}\n";
1158            fsBuilder->emitFunction(kVec3f_GrSLType,
1159                                    "set_saturation_helper",
1160                                    SK_ARRAY_COUNT(helperArgs), helperArgs,
1161                                    kHelperBody,
1162                                    &helperFunction);
1163
1164            GrGLShaderVar setSatArgs[] = {
1165                GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1166                GrGLShaderVar("satColor", kVec3f_GrSLType),
1167            };
1168            const char* helpFunc = helperFunction.c_str();
1169            SkString setSatBody;
1170            setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1171                               "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1172                               "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1173                               "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1174                               "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1175                               "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1176                               "\t\t} else {\n"
1177                               "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1178                               "\t\t}\n"
1179                               "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1180                               "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1181                               "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1182                               "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1183                               "\t} else {\n"
1184                               "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1185                               "\t}\n"
1186                               "\treturn hueLumColor;\n",
1187                               getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1188                               helpFunc, helpFunc);
1189            fsBuilder->emitFunction(kVec3f_GrSLType,
1190                                    "set_saturation",
1191                                    SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1192                                    setSatBody.c_str(),
1193                                    setSatFunction);
1194
1195        }
1196
1197        typedef GrGLFragmentProcessor INHERITED;
1198    };
1199
1200    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1201
1202private:
1203    XferEffect(SkXfermode::Mode mode, GrTexture* background)
1204        : fMode(mode) {
1205        if (background) {
1206            fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1207            this->addCoordTransform(&fBackgroundTransform);
1208            fBackgroundAccess.reset(background);
1209            this->addTextureAccess(&fBackgroundAccess);
1210        } else {
1211            this->setWillReadDstColor();
1212        }
1213    }
1214    virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE {
1215        const XferEffect& s = other.cast<XferEffect>();
1216        return fMode == s.fMode &&
1217               fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1218    }
1219
1220    SkXfermode::Mode fMode;
1221    GrCoordTransform fBackgroundTransform;
1222    GrTextureAccess  fBackgroundAccess;
1223
1224    typedef GrFragmentProcessor INHERITED;
1225};
1226
1227GR_DEFINE_FRAGMENT_PROCESSOR_TEST(XferEffect);
1228GrFragmentProcessor* XferEffect::TestCreate(SkRandom* rand,
1229                                            GrContext*,
1230                                            const GrDrawTargetCaps&,
1231                                            GrTexture*[]) {
1232    int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1233
1234    return SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL));
1235}
1236
1237#endif
1238
1239///////////////////////////////////////////////////////////////////////////////
1240///////////////////////////////////////////////////////////////////////////////
1241
1242#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1243SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1244    uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1245    if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1246        // out of range, just set to something harmless
1247        mode32 = SkXfermode::kSrcOut_Mode;
1248    }
1249    fMode = (SkXfermode::Mode)mode32;
1250
1251    const ProcCoeff& rec = gProcCoeffs[fMode];
1252    fProc = rec.fProc;
1253    // these may be valid, or may be CANNOT_USE_COEFF
1254    fSrcCoeff = rec.fSC;
1255    fDstCoeff = rec.fDC;
1256}
1257#endif
1258
1259SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
1260    uint32_t mode32 = buffer.read32();
1261    if (!buffer.validate(mode32 >= SK_ARRAY_COUNT(gProcCoeffs))) {
1262        return NULL;
1263    }
1264    return SkXfermode::Create((SkXfermode::Mode)mode32);
1265}
1266
1267void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1268    buffer.write32(fMode);
1269}
1270
1271bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1272    if (mode) {
1273        *mode = fMode;
1274    }
1275    return true;
1276}
1277
1278bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1279    if (CANNOT_USE_COEFF == fSrcCoeff) {
1280        return false;
1281    }
1282
1283    if (sc) {
1284        *sc = fSrcCoeff;
1285    }
1286    if (dc) {
1287        *dc = fDstCoeff;
1288    }
1289    return true;
1290}
1291
1292void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1293                                 const SkPMColor* SK_RESTRICT src, int count,
1294                                 const SkAlpha* SK_RESTRICT aa) const {
1295    SkASSERT(dst && src && count >= 0);
1296
1297    SkXfermodeProc proc = fProc;
1298
1299    if (proc) {
1300        if (NULL == aa) {
1301            for (int i = count - 1; i >= 0; --i) {
1302                dst[i] = proc(src[i], dst[i]);
1303            }
1304        } else {
1305            for (int i = count - 1; i >= 0; --i) {
1306                unsigned a = aa[i];
1307                if (0 != a) {
1308                    SkPMColor dstC = dst[i];
1309                    SkPMColor C = proc(src[i], dstC);
1310                    if (a != 0xFF) {
1311                        C = SkFourByteInterp(C, dstC, a);
1312                    }
1313                    dst[i] = C;
1314                }
1315            }
1316        }
1317    }
1318}
1319
1320void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1321                                 const SkPMColor* SK_RESTRICT src, int count,
1322                                 const SkAlpha* SK_RESTRICT aa) const {
1323    SkASSERT(dst && src && count >= 0);
1324
1325    SkXfermodeProc proc = fProc;
1326
1327    if (proc) {
1328        if (NULL == aa) {
1329            for (int i = count - 1; i >= 0; --i) {
1330                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1331                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1332            }
1333        } else {
1334            for (int i = count - 1; i >= 0; --i) {
1335                unsigned a = aa[i];
1336                if (0 != a) {
1337                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1338                    SkPMColor C = proc(src[i], dstC);
1339                    if (0xFF != a) {
1340                        C = SkFourByteInterp(C, dstC, a);
1341                    }
1342                    dst[i] = SkPixel32ToPixel16_ToU16(C);
1343                }
1344            }
1345        }
1346    }
1347}
1348
1349void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1350                                 const SkPMColor* SK_RESTRICT src, int count,
1351                                 const SkAlpha* SK_RESTRICT aa) const {
1352    SkASSERT(dst && src && count >= 0);
1353
1354    SkXfermodeProc proc = fProc;
1355
1356    if (proc) {
1357        if (NULL == aa) {
1358            for (int i = count - 1; i >= 0; --i) {
1359                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1360                dst[i] = SkToU8(SkGetPackedA32(res));
1361            }
1362        } else {
1363            for (int i = count - 1; i >= 0; --i) {
1364                unsigned a = aa[i];
1365                if (0 != a) {
1366                    SkAlpha dstA = dst[i];
1367                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1368                    unsigned A = SkGetPackedA32(res);
1369                    if (0xFF != a) {
1370                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1371                    }
1372                    dst[i] = SkToU8(A);
1373                }
1374            }
1375        }
1376    }
1377}
1378
1379#if SK_SUPPORT_GPU
1380bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
1381                                              GrTexture* background) const {
1382    if (XferEffect::IsSupportedMode(fMode)) {
1383        if (fp) {
1384            *fp = XferEffect::Create(fMode, background);
1385            SkASSERT(*fp);
1386        }
1387        return true;
1388    }
1389    return false;
1390}
1391#endif
1392
1393const char* SkXfermode::ModeName(Mode mode) {
1394    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1395    const char* gModeStrings[] = {
1396        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1397        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1398        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1399        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1400        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1401    };
1402    return gModeStrings[mode];
1403    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1404}
1405
1406#ifndef SK_IGNORE_TO_STRING
1407void SkProcCoeffXfermode::toString(SkString* str) const {
1408    str->append("SkProcCoeffXfermode: ");
1409
1410    str->append("mode: ");
1411    str->append(ModeName(fMode));
1412
1413    static const char* gCoeffStrings[kCoeffCount] = {
1414        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1415    };
1416
1417    str->append(" src: ");
1418    if (CANNOT_USE_COEFF == fSrcCoeff) {
1419        str->append("can't use");
1420    } else {
1421        str->append(gCoeffStrings[fSrcCoeff]);
1422    }
1423
1424    str->append(" dst: ");
1425    if (CANNOT_USE_COEFF == fDstCoeff) {
1426        str->append("can't use");
1427    } else {
1428        str->append(gCoeffStrings[fDstCoeff]);
1429    }
1430}
1431#endif
1432
1433///////////////////////////////////////////////////////////////////////////////
1434
1435class SkClearXfermode : public SkProcCoeffXfermode {
1436public:
1437    static SkClearXfermode* Create(const ProcCoeff& rec) {
1438        return SkNEW_ARGS(SkClearXfermode, (rec));
1439    }
1440
1441    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1442    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1443
1444    SK_TO_STRING_OVERRIDE()
1445
1446private:
1447    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1448#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1449    SkClearXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1450#endif
1451
1452    typedef SkProcCoeffXfermode INHERITED;
1453};
1454
1455void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1456                             const SkPMColor* SK_RESTRICT, int count,
1457                             const SkAlpha* SK_RESTRICT aa) const {
1458    SkASSERT(dst && count >= 0);
1459
1460    if (NULL == aa) {
1461        memset(dst, 0, count << 2);
1462    } else {
1463        for (int i = count - 1; i >= 0; --i) {
1464            unsigned a = aa[i];
1465            if (0xFF == a) {
1466                dst[i] = 0;
1467            } else if (a != 0) {
1468                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1469            }
1470        }
1471    }
1472}
1473void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1474                             const SkPMColor* SK_RESTRICT, int count,
1475                             const SkAlpha* SK_RESTRICT aa) const {
1476    SkASSERT(dst && count >= 0);
1477
1478    if (NULL == aa) {
1479        memset(dst, 0, count);
1480    } else {
1481        for (int i = count - 1; i >= 0; --i) {
1482            unsigned a = aa[i];
1483            if (0xFF == a) {
1484                dst[i] = 0;
1485            } else if (0 != a) {
1486                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1487            }
1488        }
1489    }
1490}
1491
1492#ifndef SK_IGNORE_TO_STRING
1493void SkClearXfermode::toString(SkString* str) const {
1494    this->INHERITED::toString(str);
1495}
1496#endif
1497
1498///////////////////////////////////////////////////////////////////////////////
1499
1500class SkSrcXfermode : public SkProcCoeffXfermode {
1501public:
1502    static SkSrcXfermode* Create(const ProcCoeff& rec) {
1503        return SkNEW_ARGS(SkSrcXfermode, (rec));
1504    }
1505
1506    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1507    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1508
1509    SK_TO_STRING_OVERRIDE()
1510
1511private:
1512    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1513#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1514    SkSrcXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1515#endif
1516    typedef SkProcCoeffXfermode INHERITED;
1517};
1518
1519void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1520                           const SkPMColor* SK_RESTRICT src, int count,
1521                           const SkAlpha* SK_RESTRICT aa) const {
1522    SkASSERT(dst && src && count >= 0);
1523
1524    if (NULL == aa) {
1525        memcpy(dst, src, count << 2);
1526    } else {
1527        for (int i = count - 1; i >= 0; --i) {
1528            unsigned a = aa[i];
1529            if (a == 0xFF) {
1530                dst[i] = src[i];
1531            } else if (a != 0) {
1532                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1533            }
1534        }
1535    }
1536}
1537
1538void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1539                           const SkPMColor* SK_RESTRICT src, int count,
1540                           const SkAlpha* SK_RESTRICT aa) const {
1541    SkASSERT(dst && src && count >= 0);
1542
1543    if (NULL == aa) {
1544        for (int i = count - 1; i >= 0; --i) {
1545            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1546        }
1547    } else {
1548        for (int i = count - 1; i >= 0; --i) {
1549            unsigned a = aa[i];
1550            if (0 != a) {
1551                unsigned srcA = SkGetPackedA32(src[i]);
1552                if (a == 0xFF) {
1553                    dst[i] = SkToU8(srcA);
1554                } else {
1555                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1556                }
1557            }
1558        }
1559    }
1560}
1561#ifndef SK_IGNORE_TO_STRING
1562void SkSrcXfermode::toString(SkString* str) const {
1563    this->INHERITED::toString(str);
1564}
1565#endif
1566
1567///////////////////////////////////////////////////////////////////////////////
1568
1569class SkDstInXfermode : public SkProcCoeffXfermode {
1570public:
1571    static SkDstInXfermode* Create(const ProcCoeff& rec) {
1572        return SkNEW_ARGS(SkDstInXfermode, (rec));
1573    }
1574
1575    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1576
1577    SK_TO_STRING_OVERRIDE()
1578
1579private:
1580    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1581#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1582    SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1583#endif
1584
1585    typedef SkProcCoeffXfermode INHERITED;
1586};
1587
1588void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1589                             const SkPMColor* SK_RESTRICT src, int count,
1590                             const SkAlpha* SK_RESTRICT aa) const {
1591    SkASSERT(dst && src);
1592
1593    if (count <= 0) {
1594        return;
1595    }
1596    if (aa) {
1597        return this->INHERITED::xfer32(dst, src, count, aa);
1598    }
1599
1600    do {
1601        unsigned a = SkGetPackedA32(*src);
1602        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1603        dst++;
1604        src++;
1605    } while (--count != 0);
1606}
1607
1608#ifndef SK_IGNORE_TO_STRING
1609void SkDstInXfermode::toString(SkString* str) const {
1610    this->INHERITED::toString(str);
1611}
1612#endif
1613
1614///////////////////////////////////////////////////////////////////////////////
1615
1616class SkDstOutXfermode : public SkProcCoeffXfermode {
1617public:
1618    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1619        return SkNEW_ARGS(SkDstOutXfermode, (rec));
1620    }
1621
1622    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1623
1624    SK_TO_STRING_OVERRIDE()
1625
1626private:
1627    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1628#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1629    SkDstOutXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1630#endif
1631
1632    typedef SkProcCoeffXfermode INHERITED;
1633};
1634
1635void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1636                              const SkPMColor* SK_RESTRICT src, int count,
1637                              const SkAlpha* SK_RESTRICT aa) const {
1638    SkASSERT(dst && src);
1639
1640    if (count <= 0) {
1641        return;
1642    }
1643    if (aa) {
1644        return this->INHERITED::xfer32(dst, src, count, aa);
1645    }
1646
1647    do {
1648        unsigned a = SkGetPackedA32(*src);
1649        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1650        dst++;
1651        src++;
1652    } while (--count != 0);
1653}
1654
1655#ifndef SK_IGNORE_TO_STRING
1656void SkDstOutXfermode::toString(SkString* str) const {
1657    this->INHERITED::toString(str);
1658}
1659#endif
1660
1661///////////////////////////////////////////////////////////////////////////////
1662
1663extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1664extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1665
1666// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
1667namespace {
1668SkXfermode* create_mode(int iMode) {
1669    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1670
1671    ProcCoeff rec = gProcCoeffs[mode];
1672    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1673    if (pp != NULL) {
1674        rec.fProc = pp;
1675    }
1676
1677    SkXfermode* xfer = NULL;
1678    // check if we have a platform optim for that
1679    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1680    if (xfm != NULL) {
1681        xfer = xfm;
1682    } else {
1683        // All modes can in theory be represented by the ProcCoeff rec, since
1684        // it contains function ptrs. However, a few modes are both simple and
1685        // commonly used, so we call those out for their own subclasses here.
1686        switch (mode) {
1687            case SkXfermode::kClear_Mode:
1688                xfer = SkClearXfermode::Create(rec);
1689                break;
1690            case SkXfermode::kSrc_Mode:
1691                xfer = SkSrcXfermode::Create(rec);
1692                break;
1693            case SkXfermode::kSrcOver_Mode:
1694                SkASSERT(false);    // should not land here
1695                break;
1696            case SkXfermode::kDstIn_Mode:
1697                xfer = SkDstInXfermode::Create(rec);
1698                break;
1699            case SkXfermode::kDstOut_Mode:
1700                xfer = SkDstOutXfermode::Create(rec);
1701                break;
1702            default:
1703                // no special-case, just rely in the rec and its function-ptrs
1704                xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1705                break;
1706        }
1707    }
1708    return xfer;
1709}
1710}  // namespace
1711
1712
1713SkXfermode* SkXfermode::Create(Mode mode) {
1714    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1715
1716    if ((unsigned)mode >= kModeCount) {
1717        // report error
1718        return NULL;
1719    }
1720
1721    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1722    // so we can just return NULL from the factory.
1723    if (kSrcOver_Mode == mode) {
1724        return NULL;
1725    }
1726
1727    SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode);
1728    return SkSafeRef(cached[mode]);
1729}
1730
1731SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1732    SkXfermodeProc  proc = NULL;
1733    if ((unsigned)mode < kModeCount) {
1734        proc = gProcCoeffs[mode].fProc;
1735    }
1736    return proc;
1737}
1738
1739bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1740    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1741
1742    if ((unsigned)mode >= (unsigned)kModeCount) {
1743        // illegal mode parameter
1744        return false;
1745    }
1746
1747    const ProcCoeff& rec = gProcCoeffs[mode];
1748
1749    if (CANNOT_USE_COEFF == rec.fSC) {
1750        return false;
1751    }
1752
1753    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1754    if (src) {
1755        *src = rec.fSC;
1756    }
1757    if (dst) {
1758        *dst = rec.fDC;
1759    }
1760    return true;
1761}
1762
1763bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1764    if (NULL == xfer) {
1765        if (mode) {
1766            *mode = kSrcOver_Mode;
1767        }
1768        return true;
1769    }
1770    return xfer->asMode(mode);
1771}
1772
1773bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1774    if (NULL == xfer) {
1775        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1776    }
1777    return xfer->asCoeff(src, dst);
1778}
1779
1780bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1781    // if xfer==null then the mode is srcover
1782    Mode m = kSrcOver_Mode;
1783    if (xfer && !xfer->asMode(&m)) {
1784        return false;
1785    }
1786    return mode == m;
1787}
1788
1789///////////////////////////////////////////////////////////////////////////////
1790//////////// 16bit xfermode procs
1791
1792#ifdef SK_DEBUG
1793static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1794static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1795#endif
1796
1797static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1798    SkASSERT(require_255(src));
1799    return SkPixel32ToPixel16(src);
1800}
1801
1802static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1803    return dst;
1804}
1805
1806static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1807    SkASSERT(require_0(src));
1808    return dst;
1809}
1810
1811static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1812    SkASSERT(require_255(src));
1813    return SkPixel32ToPixel16(src);
1814}
1815
1816static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1817    SkASSERT(require_0(src));
1818    return dst;
1819}
1820
1821static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1822    SkASSERT(require_255(src));
1823    return dst;
1824}
1825
1826static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1827    SkASSERT(require_255(src));
1828    return SkPixel32ToPixel16(src);
1829}
1830
1831static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1832    SkASSERT(require_255(src));
1833    return dst;
1834}
1835
1836static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1837    SkASSERT(require_0(src));
1838    return dst;
1839}
1840
1841static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1842    unsigned isa = 255 - SkGetPackedA32(src);
1843
1844    return SkPackRGB16(
1845           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1846           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1847           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1848}
1849
1850static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1851    SkASSERT(require_0(src));
1852    return dst;
1853}
1854
1855static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1856    SkASSERT(require_255(src));
1857    return SkPixel32ToPixel16(src);
1858}
1859
1860static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1861    SkASSERT(require_255(src));
1862    return dst;
1863}
1864
1865/*********
1866    darken and lighten boil down to this.
1867
1868    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1869    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1870
1871    if (Sa == 0) these become
1872        darken  = Dc + min(0, Dc) = 0
1873        lighten = Dc + max(0, Dc) = Dc
1874
1875    if (Sa == 1) these become
1876        darken  = min(Sc, Dc)
1877        lighten = max(Sc, Dc)
1878*/
1879
1880static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1881    SkASSERT(require_0(src));
1882    return 0;
1883}
1884
1885static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1886    SkASSERT(require_255(src));
1887    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1888    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1889    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1890    return SkPackRGB16(r, g, b);
1891}
1892
1893static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1894    SkASSERT(require_0(src));
1895    return dst;
1896}
1897
1898static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1899    SkASSERT(require_255(src));
1900    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1901    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1902    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1903    return SkPackRGB16(r, g, b);
1904}
1905
1906struct Proc16Rec {
1907    SkXfermodeProc16    fProc16_0;
1908    SkXfermodeProc16    fProc16_255;
1909    SkXfermodeProc16    fProc16_General;
1910};
1911
1912static const Proc16Rec gModeProcs16[] = {
1913    { NULL,                 NULL,                   NULL            }, // CLEAR
1914    { NULL,                 src_modeproc16_255,     NULL            },
1915    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1916    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1917    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1918    { NULL,                 srcin_modeproc16_255,   NULL            },
1919    { NULL,                 dstin_modeproc16_255,   NULL            },
1920    { NULL,                 NULL,                   NULL            },// SRC_OUT
1921    { dstout_modeproc16_0,  NULL,                   NULL            },
1922    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1923    { NULL,                 dstatop_modeproc16_255, NULL            },
1924    { NULL,                 NULL,                   NULL            }, // XOR
1925
1926    { NULL,                 NULL,                   NULL            }, // plus
1927    { NULL,                 NULL,                   NULL            }, // modulate
1928    { NULL,                 NULL,                   NULL            }, // screen
1929    { NULL,                 NULL,                   NULL            }, // overlay
1930    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1931    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1932    { NULL,                 NULL,                   NULL            }, // colordodge
1933    { NULL,                 NULL,                   NULL            }, // colorburn
1934    { NULL,                 NULL,                   NULL            }, // hardlight
1935    { NULL,                 NULL,                   NULL            }, // softlight
1936    { NULL,                 NULL,                   NULL            }, // difference
1937    { NULL,                 NULL,                   NULL            }, // exclusion
1938    { NULL,                 NULL,                   NULL            }, // multiply
1939    { NULL,                 NULL,                   NULL            }, // hue
1940    { NULL,                 NULL,                   NULL            }, // saturation
1941    { NULL,                 NULL,                   NULL            }, // color
1942    { NULL,                 NULL,                   NULL            }, // luminosity
1943};
1944
1945SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1946    SkXfermodeProc16  proc16 = NULL;
1947    if ((unsigned)mode < kModeCount) {
1948        const Proc16Rec& rec = gModeProcs16[mode];
1949        unsigned a = SkColorGetA(srcColor);
1950
1951        if (0 == a) {
1952            proc16 = rec.fProc16_0;
1953        } else if (255 == a) {
1954            proc16 = rec.fProc16_255;
1955        } else {
1956            proc16 = rec.fProc16_General;
1957        }
1958    }
1959    return proc16;
1960}
1961
1962SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1963    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1964SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1965