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