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::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
680    return false;
681}
682
683bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
684                                    GrEffectRef** effect,
685                                    Coeff* src,
686                                    Coeff* dst,
687                                    GrTexture* background) {
688    if (NULL == xfermode) {
689        return ModeAsCoeff(kSrcOver_Mode, src, dst);
690    } else if (xfermode->asCoeff(src, dst)) {
691        return true;
692    } else {
693        return xfermode->asNewEffect(effect, background);
694    }
695}
696
697SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
698    // no-op. subclasses should override this
699    return dst;
700}
701
702void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
703                        const SkPMColor* SK_RESTRICT src, int count,
704                        const SkAlpha* SK_RESTRICT aa) const {
705    SkASSERT(dst && src && count >= 0);
706
707    if (NULL == aa) {
708        for (int i = count - 1; i >= 0; --i) {
709            dst[i] = this->xferColor(src[i], dst[i]);
710        }
711    } else {
712        for (int i = count - 1; i >= 0; --i) {
713            unsigned a = aa[i];
714            if (0 != a) {
715                SkPMColor dstC = dst[i];
716                SkPMColor C = this->xferColor(src[i], dstC);
717                if (0xFF != a) {
718                    C = SkFourByteInterp(C, dstC, a);
719                }
720                dst[i] = C;
721            }
722        }
723    }
724}
725
726void SkXfermode::xfer16(uint16_t* dst,
727                        const SkPMColor* SK_RESTRICT src, int count,
728                        const SkAlpha* SK_RESTRICT aa) const {
729    SkASSERT(dst && src && count >= 0);
730
731    if (NULL == aa) {
732        for (int i = count - 1; i >= 0; --i) {
733            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
734            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
735        }
736    } else {
737        for (int i = count - 1; i >= 0; --i) {
738            unsigned a = aa[i];
739            if (0 != a) {
740                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
741                SkPMColor C = this->xferColor(src[i], dstC);
742                if (0xFF != a) {
743                    C = SkFourByteInterp(C, dstC, a);
744                }
745                dst[i] = SkPixel32ToPixel16_ToU16(C);
746            }
747        }
748    }
749}
750
751void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
752                        const SkPMColor src[], int count,
753                        const SkAlpha* SK_RESTRICT aa) const {
754    SkASSERT(dst && src && count >= 0);
755
756    if (NULL == aa) {
757        for (int i = count - 1; i >= 0; --i) {
758            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
759            dst[i] = SkToU8(SkGetPackedA32(res));
760        }
761    } else {
762        for (int i = count - 1; i >= 0; --i) {
763            unsigned a = aa[i];
764            if (0 != a) {
765                SkAlpha dstA = dst[i];
766                unsigned A = SkGetPackedA32(this->xferColor(src[i],
767                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
768                if (0xFF != a) {
769                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
770                }
771                dst[i] = SkToU8(A);
772            }
773        }
774    }
775}
776
777//////////////////////////////////////////////////////////////////////////////
778
779#if SK_SUPPORT_GPU
780
781#include "GrEffect.h"
782#include "GrCoordTransform.h"
783#include "GrEffectUnitTest.h"
784#include "GrTBackendEffectFactory.h"
785#include "gl/GrGLEffect.h"
786
787/**
788 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
789 */
790class XferEffect : public GrEffect {
791public:
792    static bool IsSupportedMode(SkXfermode::Mode mode) {
793        return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
794    }
795
796    static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
797        if (!IsSupportedMode(mode)) {
798            return NULL;
799        } else {
800            AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
801            return CreateEffectRef(effect);
802        }
803    }
804
805    virtual void getConstantColorComponents(GrColor* color,
806                                            uint32_t* validFlags) const SK_OVERRIDE {
807        *validFlags = 0;
808    }
809
810    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
811        return GrTBackendEffectFactory<XferEffect>::getInstance();
812    }
813
814    static const char* Name() { return "XferEffect"; }
815
816    SkXfermode::Mode mode() const { return fMode; }
817    const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
818
819    class GLEffect : public GrGLEffect {
820    public:
821        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
822            : GrGLEffect(factory) {
823        }
824        virtual void emitCode(GrGLShaderBuilder* builder,
825                              const GrDrawEffect& drawEffect,
826                              EffectKey key,
827                              const char* outputColor,
828                              const char* inputColor,
829                              const TransformedCoordsArray& coords,
830                              const TextureSamplerArray& samplers) SK_OVERRIDE {
831            SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
832            const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
833            const char* dstColor;
834            if (backgroundTex) {
835                dstColor = "bgColor";
836                builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
837                builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
838                builder->fsCodeAppendf(";\n");
839            } else {
840                dstColor = builder->dstColor();
841            }
842            SkASSERT(NULL != dstColor);
843
844            // We don't try to optimize for this case at all
845            if (NULL == inputColor) {
846                builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
847                inputColor = "ones";
848            }
849            builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
850
851            // These all perform src-over on the alpha channel.
852            builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
853                                    outputColor, inputColor, inputColor, dstColor);
854
855            switch (mode) {
856                case SkXfermode::kOverlay_Mode:
857                    // Overlay is Hard-Light with the src and dst reversed
858                    HardLight(builder, outputColor, dstColor, inputColor);
859                    break;
860                case SkXfermode::kDarken_Mode:
861                    builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
862                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
863                                            outputColor,
864                                            inputColor, dstColor, inputColor,
865                                            dstColor, inputColor, dstColor);
866                    break;
867                case SkXfermode::kLighten_Mode:
868                    builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
869                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
870                                            outputColor,
871                                            inputColor, dstColor, inputColor,
872                                            dstColor, inputColor, dstColor);
873                    break;
874                case SkXfermode::kColorDodge_Mode:
875                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
876                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
877                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
878                    break;
879                case SkXfermode::kColorBurn_Mode:
880                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
881                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
882                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
883                    break;
884                case SkXfermode::kHardLight_Mode:
885                    HardLight(builder, outputColor, inputColor, dstColor);
886                    break;
887                case SkXfermode::kSoftLight_Mode:
888                    builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
889                    builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
890                    builder->fsCodeAppendf("\t\t} else {\n");
891                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
892                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
893                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
894                    builder->fsCodeAppendf("\t\t}\n");
895                    break;
896                case SkXfermode::kDifference_Mode:
897                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
898                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
899                                           outputColor, inputColor, dstColor, inputColor, dstColor,
900                                           dstColor, inputColor);
901                    break;
902                case SkXfermode::kExclusion_Mode:
903                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
904                                                        "2.0 * %s.rgb * %s.rgb;\n",
905                                           outputColor, dstColor, inputColor, dstColor, inputColor);
906                    break;
907                case SkXfermode::kMultiply_Mode:
908                    builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
909                                                        "(1.0 - %s.a) * %s.rgb + "
910                                                         "%s.rgb * %s.rgb;\n",
911                                           outputColor, inputColor, dstColor, dstColor, inputColor,
912                                           inputColor, dstColor);
913                    break;
914                case SkXfermode::kHue_Mode: {
915                    //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
916                    SkString setSat, setLum;
917                    AddSatFunction(builder, &setSat);
918                    AddLumFunction(builder, &setLum);
919                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
920                                           dstColor, inputColor);
921                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
922                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
923                                           dstColor);
924                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
925                                           outputColor, inputColor, dstColor, dstColor, inputColor);
926                    break;
927                }
928                case SkXfermode::kSaturation_Mode: {
929                    // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
930                    SkString setSat, setLum;
931                    AddSatFunction(builder, &setSat);
932                    AddLumFunction(builder, &setLum);
933                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
934                                           dstColor, inputColor);
935                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
936                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
937                                           dstColor);
938                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
939                                           outputColor, inputColor, dstColor, dstColor, inputColor);
940                    break;
941                }
942                case SkXfermode::kColor_Mode: {
943                    //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
944                    SkString setLum;
945                    AddLumFunction(builder, &setLum);
946                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
947                                           inputColor, dstColor);
948                    builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
949                                           outputColor, setLum.c_str(), dstColor, inputColor);
950                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
951                                           outputColor, inputColor, dstColor, dstColor, inputColor);
952                    break;
953                }
954                case SkXfermode::kLuminosity_Mode: {
955                    //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
956                    SkString setLum;
957                    AddLumFunction(builder, &setLum);
958                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
959                                           inputColor, dstColor);
960                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
961                                           outputColor, setLum.c_str(), dstColor, inputColor);
962                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
963                                           outputColor, inputColor, dstColor, dstColor, inputColor);
964                    break;
965                }
966                default:
967                    SkFAIL("Unknown XferEffect mode.");
968                    break;
969            }
970        }
971
972        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
973            // The background may come from the dst or from a texture.
974            int numTextures = (*drawEffect.effect())->numTextures();
975            SkASSERT(numTextures <= 1);
976            return (drawEffect.castEffect<XferEffect>().mode() << 1) | numTextures;
977        }
978
979    private:
980        static void HardLight(GrGLShaderBuilder* builder,
981                              const char* final,
982                              const char* src,
983                              const char* dst) {
984            static const char kComponents[] = {'r', 'g', 'b'};
985            for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
986                char component = kComponents[i];
987                builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
988                builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
989                builder->fsCodeAppend("\t\t} else {\n");
990                builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
991                                       final, component, src, dst, dst, dst, component, src, src, component);
992                builder->fsCodeAppend("\t\t}\n");
993            }
994            builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
995                                   final, src, dst, dst, src);
996        }
997
998        // Does one component of color-dodge
999        static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1000                                        const char* final,
1001                                        const char* src,
1002                                        const char* dst,
1003                                        const char component) {
1004            builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1005            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1006                                   final, component, src, component, dst);
1007            builder->fsCodeAppend("\t\t} else {\n");
1008            builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1009            builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1010            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",
1011                                   final, component, src, dst, src, component, dst, dst, component,
1012                                   src);
1013            builder->fsCodeAppend("\t\t\t} else {\n");
1014            builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1015                                   dst, dst, component, src);
1016            builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1017                                   final, component, src, src, component, dst, dst, component, src);
1018            builder->fsCodeAppend("\t\t\t}\n");
1019            builder->fsCodeAppend("\t\t}\n");
1020        }
1021
1022        // Does one component of color-burn
1023        static void ColorBurnComponent(GrGLShaderBuilder* builder,
1024                                       const char* final,
1025                                       const char* src,
1026                                       const char* dst,
1027                                       const char component) {
1028            builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1029            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1030                                   final, component, src, dst, src, component, dst, dst, component,
1031                                   src);
1032            builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1033            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1034                                   final, component, dst, component, src);
1035            builder->fsCodeAppend("\t\t} else {\n");
1036            builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1037                                   dst, dst, dst, component, src, src, component);
1038            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1039                                   final, component, src, src, component, dst, dst, component, src);
1040            builder->fsCodeAppend("\t\t}\n");
1041        }
1042
1043        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1044        static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1045                                                  const char* final,
1046                                                  const char* src,
1047                                                  const char* dst,
1048                                                  const char component) {
1049            // if (2S < Sa)
1050            builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1051            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1052            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",
1053                                   final, component, dst, component, dst, component, src, src,
1054                                   component, dst, dst, src, component, dst, component, src, src,
1055                                   component);
1056            // else if (4D < Da)
1057            builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1058                                   dst, component, dst);
1059            builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1060                                   dst, component, dst, component);
1061            builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1062            builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1063            builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1064            // (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
1065            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",
1066                                   final, component, src, component, src, component, dst, component,
1067                                   src, src, component, dst, src, src, component, src, src,
1068                                   component);
1069            builder->fsCodeAppendf("\t\t\t} else {\n");
1070            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1071            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",
1072                                    final, component, dst, dst, component, src, src, component, dst,
1073                                    src, component, dst, component, src, src, component, src,
1074                                    component);
1075            builder->fsCodeAppendf("\t\t\t}\n");
1076        }
1077
1078        // Adds a function that takes two colors and an alpha as input. It produces a color with the
1079        // hue and saturation of the first color, the luminosity of the second color, and the input
1080        // alpha. It has this signature:
1081        //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1082        static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1083            // Emit a helper that gets the luminance of a color.
1084            SkString getFunction;
1085            GrGLShaderVar getLumArgs[] = {
1086                GrGLShaderVar("color", kVec3f_GrSLType),
1087            };
1088            SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1089            builder->fsEmitFunction(kFloat_GrSLType,
1090                                    "luminance",
1091                                    SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1092                                    getLumBody.c_str(),
1093                                    &getFunction);
1094
1095            // Emit the set luminance function.
1096            GrGLShaderVar setLumArgs[] = {
1097                GrGLShaderVar("hueSat", kVec3f_GrSLType),
1098                GrGLShaderVar("alpha", kFloat_GrSLType),
1099                GrGLShaderVar("lumColor", kVec3f_GrSLType),
1100            };
1101            SkString setLumBody;
1102            setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1103            setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1104            setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1105            setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1106                              "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1107                              "\tif (minComp < 0.0) {\n"
1108                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1109                              "\t}\n"
1110                              "\tif (maxComp > alpha) {\n"
1111                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1112                              "\t}\n"
1113                              "\treturn outColor;\n");
1114            builder->fsEmitFunction(kVec3f_GrSLType,
1115                                    "set_luminance",
1116                                    SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1117                                    setLumBody.c_str(),
1118                                    setLumFunction);
1119        }
1120
1121        // Adds a function that creates a color with the hue and luminosity of one input color and
1122        // the saturation of another color. It will have this signature:
1123        //      float set_saturation(vec3 hueLumColor, vec3 satColor)
1124        static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1125            // Emit a helper that gets the saturation of a color
1126            SkString getFunction;
1127            GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1128            SkString getSatBody;
1129            getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1130                              "min(min(color.r, color.g), color.b);\n");
1131            builder->fsEmitFunction(kFloat_GrSLType,
1132                                    "saturation",
1133                                    SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1134                                    getSatBody.c_str(),
1135                                    &getFunction);
1136
1137            // Emit a helper that sets the saturation given sorted input channels. This used
1138            // to use inout params for min, mid, and max components but that seems to cause
1139            // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1140            // adjusted min, mid, and max inputs, respectively.
1141            SkString helperFunction;
1142            GrGLShaderVar helperArgs[] = {
1143                GrGLShaderVar("minComp", kFloat_GrSLType),
1144                GrGLShaderVar("midComp", kFloat_GrSLType),
1145                GrGLShaderVar("maxComp", kFloat_GrSLType),
1146                GrGLShaderVar("sat", kFloat_GrSLType),
1147            };
1148            static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1149                                              "\t\tvec3 result;\n"
1150                                              "\t\tresult.r = 0.0;\n"
1151                                              "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1152                                              "\t\tresult.b = sat;\n"
1153                                              "\t\treturn result;\n"
1154                                              "\t} else {\n"
1155                                              "\t\treturn vec3(0, 0, 0);\n"
1156                                              "\t}\n";
1157            builder->fsEmitFunction(kVec3f_GrSLType,
1158                                    "set_saturation_helper",
1159                                    SK_ARRAY_COUNT(helperArgs), helperArgs,
1160                                    kHelperBody,
1161                                    &helperFunction);
1162
1163            GrGLShaderVar setSatArgs[] = {
1164                GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1165                GrGLShaderVar("satColor", kVec3f_GrSLType),
1166            };
1167            const char* helpFunc = helperFunction.c_str();
1168            SkString setSatBody;
1169            setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1170                               "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1171                               "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1172                               "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1173                               "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1174                               "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1175                               "\t\t} else {\n"
1176                               "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1177                               "\t\t}\n"
1178                               "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1179                               "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1180                               "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1181                               "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1182                               "\t} else {\n"
1183                               "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1184                               "\t}\n"
1185                               "\treturn hueLumColor;\n",
1186                               getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1187                               helpFunc, helpFunc);
1188            builder->fsEmitFunction(kVec3f_GrSLType,
1189                                    "set_saturation",
1190                                    SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1191                                    setSatBody.c_str(),
1192                                    setSatFunction);
1193
1194        }
1195
1196        typedef GrGLEffect INHERITED;
1197    };
1198
1199    GR_DECLARE_EFFECT_TEST;
1200
1201private:
1202    XferEffect(SkXfermode::Mode mode, GrTexture* background)
1203        : fMode(mode) {
1204        if (background) {
1205            fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1206            this->addCoordTransform(&fBackgroundTransform);
1207            fBackgroundAccess.reset(background);
1208            this->addTextureAccess(&fBackgroundAccess);
1209        } else {
1210            this->setWillReadDstColor();
1211        }
1212    }
1213    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1214        const XferEffect& s = CastEffect<XferEffect>(other);
1215        return fMode == s.fMode &&
1216               fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1217    }
1218
1219    SkXfermode::Mode fMode;
1220    GrCoordTransform fBackgroundTransform;
1221    GrTextureAccess  fBackgroundAccess;
1222
1223    typedef GrEffect INHERITED;
1224};
1225
1226GR_DEFINE_EFFECT_TEST(XferEffect);
1227GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
1228                                    GrContext*,
1229                                    const GrDrawTargetCaps&,
1230                                    GrTexture*[]) {
1231    int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1232
1233    AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
1234    return CreateEffectRef(gEffect);
1235}
1236
1237#endif
1238
1239///////////////////////////////////////////////////////////////////////////////
1240///////////////////////////////////////////////////////////////////////////////
1241
1242SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1243    uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1244    if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1245        // out of range, just set to something harmless
1246        mode32 = SkXfermode::kSrcOut_Mode;
1247    }
1248    fMode = (SkXfermode::Mode)mode32;
1249
1250    const ProcCoeff& rec = gProcCoeffs[fMode];
1251    fProc = rec.fProc;
1252    // these may be valid, or may be CANNOT_USE_COEFF
1253    fSrcCoeff = rec.fSC;
1254    fDstCoeff = rec.fDC;
1255}
1256
1257bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1258    if (mode) {
1259        *mode = fMode;
1260    }
1261    return true;
1262}
1263
1264bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1265    if (CANNOT_USE_COEFF == fSrcCoeff) {
1266        return false;
1267    }
1268
1269    if (sc) {
1270        *sc = fSrcCoeff;
1271    }
1272    if (dc) {
1273        *dc = fDstCoeff;
1274    }
1275    return true;
1276}
1277
1278void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1279                                 const SkPMColor* SK_RESTRICT src, int count,
1280                                 const SkAlpha* SK_RESTRICT aa) const {
1281    SkASSERT(dst && src && count >= 0);
1282
1283    SkXfermodeProc proc = fProc;
1284
1285    if (NULL != proc) {
1286        if (NULL == aa) {
1287            for (int i = count - 1; i >= 0; --i) {
1288                dst[i] = proc(src[i], dst[i]);
1289            }
1290        } else {
1291            for (int i = count - 1; i >= 0; --i) {
1292                unsigned a = aa[i];
1293                if (0 != a) {
1294                    SkPMColor dstC = dst[i];
1295                    SkPMColor C = proc(src[i], dstC);
1296                    if (a != 0xFF) {
1297                        C = SkFourByteInterp(C, dstC, a);
1298                    }
1299                    dst[i] = C;
1300                }
1301            }
1302        }
1303    }
1304}
1305
1306void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1307                                 const SkPMColor* SK_RESTRICT src, int count,
1308                                 const SkAlpha* SK_RESTRICT aa) const {
1309    SkASSERT(dst && src && count >= 0);
1310
1311    SkXfermodeProc proc = fProc;
1312
1313    if (NULL != proc) {
1314        if (NULL == aa) {
1315            for (int i = count - 1; i >= 0; --i) {
1316                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1317                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1318            }
1319        } else {
1320            for (int i = count - 1; i >= 0; --i) {
1321                unsigned a = aa[i];
1322                if (0 != a) {
1323                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1324                    SkPMColor C = proc(src[i], dstC);
1325                    if (0xFF != a) {
1326                        C = SkFourByteInterp(C, dstC, a);
1327                    }
1328                    dst[i] = SkPixel32ToPixel16_ToU16(C);
1329                }
1330            }
1331        }
1332    }
1333}
1334
1335void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1336                                 const SkPMColor* SK_RESTRICT src, int count,
1337                                 const SkAlpha* SK_RESTRICT aa) const {
1338    SkASSERT(dst && src && count >= 0);
1339
1340    SkXfermodeProc proc = fProc;
1341
1342    if (NULL != proc) {
1343        if (NULL == aa) {
1344            for (int i = count - 1; i >= 0; --i) {
1345                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1346                dst[i] = SkToU8(SkGetPackedA32(res));
1347            }
1348        } else {
1349            for (int i = count - 1; i >= 0; --i) {
1350                unsigned a = aa[i];
1351                if (0 != a) {
1352                    SkAlpha dstA = dst[i];
1353                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1354                    unsigned A = SkGetPackedA32(res);
1355                    if (0xFF != a) {
1356                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1357                    }
1358                    dst[i] = SkToU8(A);
1359                }
1360            }
1361        }
1362    }
1363}
1364
1365#if SK_SUPPORT_GPU
1366bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
1367                                      GrTexture* background) const {
1368    if (XferEffect::IsSupportedMode(fMode)) {
1369        if (NULL != effect) {
1370            *effect = XferEffect::Create(fMode, background);
1371            SkASSERT(NULL != *effect);
1372        }
1373        return true;
1374    }
1375    return false;
1376}
1377#endif
1378
1379void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1380    this->INHERITED::flatten(buffer);
1381    buffer.write32(fMode);
1382}
1383
1384const char* SkXfermode::ModeName(Mode mode) {
1385    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1386    const char* gModeStrings[] = {
1387        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1388        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1389        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1390        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1391        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1392    };
1393    return gModeStrings[mode];
1394    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1395}
1396
1397#ifndef SK_IGNORE_TO_STRING
1398void SkProcCoeffXfermode::toString(SkString* str) const {
1399    str->append("SkProcCoeffXfermode: ");
1400
1401    str->append("mode: ");
1402    str->append(ModeName(fMode));
1403
1404    static const char* gCoeffStrings[kCoeffCount] = {
1405        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1406    };
1407
1408    str->append(" src: ");
1409    if (CANNOT_USE_COEFF == fSrcCoeff) {
1410        str->append("can't use");
1411    } else {
1412        str->append(gCoeffStrings[fSrcCoeff]);
1413    }
1414
1415    str->append(" dst: ");
1416    if (CANNOT_USE_COEFF == fDstCoeff) {
1417        str->append("can't use");
1418    } else {
1419        str->append(gCoeffStrings[fDstCoeff]);
1420    }
1421}
1422#endif
1423
1424///////////////////////////////////////////////////////////////////////////////
1425
1426class SkClearXfermode : public SkProcCoeffXfermode {
1427public:
1428    static SkClearXfermode* Create(const ProcCoeff& rec) {
1429        return SkNEW_ARGS(SkClearXfermode, (rec));
1430    }
1431
1432    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1433    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1434
1435    SK_TO_STRING_OVERRIDE()
1436    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1437
1438private:
1439    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1440    SkClearXfermode(SkReadBuffer& buffer)
1441        : SkProcCoeffXfermode(buffer) {}
1442
1443    typedef SkProcCoeffXfermode INHERITED;
1444};
1445
1446void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1447                             const SkPMColor* SK_RESTRICT, int count,
1448                             const SkAlpha* SK_RESTRICT aa) const {
1449    SkASSERT(dst && count >= 0);
1450
1451    if (NULL == aa) {
1452        memset(dst, 0, count << 2);
1453    } else {
1454        for (int i = count - 1; i >= 0; --i) {
1455            unsigned a = aa[i];
1456            if (0xFF == a) {
1457                dst[i] = 0;
1458            } else if (a != 0) {
1459                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1460            }
1461        }
1462    }
1463}
1464void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1465                             const SkPMColor* SK_RESTRICT, int count,
1466                             const SkAlpha* SK_RESTRICT aa) const {
1467    SkASSERT(dst && count >= 0);
1468
1469    if (NULL == aa) {
1470        memset(dst, 0, count);
1471    } else {
1472        for (int i = count - 1; i >= 0; --i) {
1473            unsigned a = aa[i];
1474            if (0xFF == a) {
1475                dst[i] = 0;
1476            } else if (0 != a) {
1477                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1478            }
1479        }
1480    }
1481}
1482
1483#ifndef SK_IGNORE_TO_STRING
1484void SkClearXfermode::toString(SkString* str) const {
1485    this->INHERITED::toString(str);
1486}
1487#endif
1488
1489///////////////////////////////////////////////////////////////////////////////
1490
1491class SkSrcXfermode : public SkProcCoeffXfermode {
1492public:
1493    static SkSrcXfermode* Create(const ProcCoeff& rec) {
1494        return SkNEW_ARGS(SkSrcXfermode, (rec));
1495    }
1496
1497    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1498    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1499
1500    SK_TO_STRING_OVERRIDE()
1501    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1502
1503private:
1504    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1505    SkSrcXfermode(SkReadBuffer& buffer)
1506        : SkProcCoeffXfermode(buffer) {}
1507
1508    typedef SkProcCoeffXfermode INHERITED;
1509};
1510
1511void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1512                           const SkPMColor* SK_RESTRICT src, int count,
1513                           const SkAlpha* SK_RESTRICT aa) const {
1514    SkASSERT(dst && src && count >= 0);
1515
1516    if (NULL == aa) {
1517        memcpy(dst, src, count << 2);
1518    } else {
1519        for (int i = count - 1; i >= 0; --i) {
1520            unsigned a = aa[i];
1521            if (a == 0xFF) {
1522                dst[i] = src[i];
1523            } else if (a != 0) {
1524                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1525            }
1526        }
1527    }
1528}
1529
1530void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1531                           const SkPMColor* SK_RESTRICT src, int count,
1532                           const SkAlpha* SK_RESTRICT aa) const {
1533    SkASSERT(dst && src && count >= 0);
1534
1535    if (NULL == aa) {
1536        for (int i = count - 1; i >= 0; --i) {
1537            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1538        }
1539    } else {
1540        for (int i = count - 1; i >= 0; --i) {
1541            unsigned a = aa[i];
1542            if (0 != a) {
1543                unsigned srcA = SkGetPackedA32(src[i]);
1544                if (a == 0xFF) {
1545                    dst[i] = SkToU8(srcA);
1546                } else {
1547                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1548                }
1549            }
1550        }
1551    }
1552}
1553#ifndef SK_IGNORE_TO_STRING
1554void SkSrcXfermode::toString(SkString* str) const {
1555    this->INHERITED::toString(str);
1556}
1557#endif
1558
1559///////////////////////////////////////////////////////////////////////////////
1560
1561class SkDstInXfermode : public SkProcCoeffXfermode {
1562public:
1563    static SkDstInXfermode* Create(const ProcCoeff& rec) {
1564        return SkNEW_ARGS(SkDstInXfermode, (rec));
1565    }
1566
1567    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1568
1569    SK_TO_STRING_OVERRIDE()
1570    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1571
1572private:
1573    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1574    SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1575
1576    typedef SkProcCoeffXfermode INHERITED;
1577};
1578
1579void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1580                             const SkPMColor* SK_RESTRICT src, int count,
1581                             const SkAlpha* SK_RESTRICT aa) const {
1582    SkASSERT(dst && src);
1583
1584    if (count <= 0) {
1585        return;
1586    }
1587    if (NULL != aa) {
1588        return this->INHERITED::xfer32(dst, src, count, aa);
1589    }
1590
1591    do {
1592        unsigned a = SkGetPackedA32(*src);
1593        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1594        dst++;
1595        src++;
1596    } while (--count != 0);
1597}
1598
1599#ifndef SK_IGNORE_TO_STRING
1600void SkDstInXfermode::toString(SkString* str) const {
1601    this->INHERITED::toString(str);
1602}
1603#endif
1604
1605///////////////////////////////////////////////////////////////////////////////
1606
1607class SkDstOutXfermode : public SkProcCoeffXfermode {
1608public:
1609    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1610        return SkNEW_ARGS(SkDstOutXfermode, (rec));
1611    }
1612
1613    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1614
1615    SK_TO_STRING_OVERRIDE()
1616    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1617
1618private:
1619    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1620    SkDstOutXfermode(SkReadBuffer& buffer)
1621        : INHERITED(buffer) {}
1622
1623    typedef SkProcCoeffXfermode INHERITED;
1624};
1625
1626void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1627                              const SkPMColor* SK_RESTRICT src, int count,
1628                              const SkAlpha* SK_RESTRICT aa) const {
1629    SkASSERT(dst && src);
1630
1631    if (count <= 0) {
1632        return;
1633    }
1634    if (NULL != aa) {
1635        return this->INHERITED::xfer32(dst, src, count, aa);
1636    }
1637
1638    do {
1639        unsigned a = SkGetPackedA32(*src);
1640        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1641        dst++;
1642        src++;
1643    } while (--count != 0);
1644}
1645
1646#ifndef SK_IGNORE_TO_STRING
1647void SkDstOutXfermode::toString(SkString* str) const {
1648    this->INHERITED::toString(str);
1649}
1650#endif
1651
1652///////////////////////////////////////////////////////////////////////////////
1653
1654extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1655extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1656
1657// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
1658namespace {
1659SkXfermode* create_mode(int iMode) {
1660    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1661
1662    ProcCoeff rec = gProcCoeffs[mode];
1663    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1664    if (pp != NULL) {
1665        rec.fProc = pp;
1666    }
1667
1668    SkXfermode* xfer = NULL;
1669    // check if we have a platform optim for that
1670    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1671    if (xfm != NULL) {
1672        xfer = xfm;
1673    } else {
1674        // All modes can in theory be represented by the ProcCoeff rec, since
1675        // it contains function ptrs. However, a few modes are both simple and
1676        // commonly used, so we call those out for their own subclasses here.
1677        switch (mode) {
1678            case SkXfermode::kClear_Mode:
1679                xfer = SkClearXfermode::Create(rec);
1680                break;
1681            case SkXfermode::kSrc_Mode:
1682                xfer = SkSrcXfermode::Create(rec);
1683                break;
1684            case SkXfermode::kSrcOver_Mode:
1685                SkASSERT(false);    // should not land here
1686                break;
1687            case SkXfermode::kDstIn_Mode:
1688                xfer = SkDstInXfermode::Create(rec);
1689                break;
1690            case SkXfermode::kDstOut_Mode:
1691                xfer = SkDstOutXfermode::Create(rec);
1692                break;
1693            default:
1694                // no special-case, just rely in the rec and its function-ptrs
1695                xfer = SkProcCoeffXfermode::Create(rec, mode);
1696                break;
1697        }
1698    }
1699    return xfer;
1700}
1701}  // namespace
1702
1703
1704SkXfermode* SkXfermode::Create(Mode mode) {
1705    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1706
1707    if ((unsigned)mode >= kModeCount) {
1708        // report error
1709        return NULL;
1710    }
1711
1712    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1713    // so we can just return NULL from the factory.
1714    if (kSrcOver_Mode == mode) {
1715        return NULL;
1716    }
1717
1718    SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode);
1719    return SkSafeRef(cached[mode]);
1720}
1721
1722SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1723    SkXfermodeProc  proc = NULL;
1724    if ((unsigned)mode < kModeCount) {
1725        proc = gProcCoeffs[mode].fProc;
1726    }
1727    return proc;
1728}
1729
1730bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1731    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1732
1733    if ((unsigned)mode >= (unsigned)kModeCount) {
1734        // illegal mode parameter
1735        return false;
1736    }
1737
1738    const ProcCoeff& rec = gProcCoeffs[mode];
1739
1740    if (CANNOT_USE_COEFF == rec.fSC) {
1741        return false;
1742    }
1743
1744    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1745    if (src) {
1746        *src = rec.fSC;
1747    }
1748    if (dst) {
1749        *dst = rec.fDC;
1750    }
1751    return true;
1752}
1753
1754bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1755    if (NULL == xfer) {
1756        if (mode) {
1757            *mode = kSrcOver_Mode;
1758        }
1759        return true;
1760    }
1761    return xfer->asMode(mode);
1762}
1763
1764bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1765    if (NULL == xfer) {
1766        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1767    }
1768    return xfer->asCoeff(src, dst);
1769}
1770
1771bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1772    // if xfer==null then the mode is srcover
1773    Mode m = kSrcOver_Mode;
1774    if (xfer && !xfer->asMode(&m)) {
1775        return false;
1776    }
1777    return mode == m;
1778}
1779
1780///////////////////////////////////////////////////////////////////////////////
1781//////////// 16bit xfermode procs
1782
1783#ifdef SK_DEBUG
1784static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1785static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1786#endif
1787
1788static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1789    SkASSERT(require_255(src));
1790    return SkPixel32ToPixel16(src);
1791}
1792
1793static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1794    return dst;
1795}
1796
1797static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1798    SkASSERT(require_0(src));
1799    return dst;
1800}
1801
1802static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1803    SkASSERT(require_255(src));
1804    return SkPixel32ToPixel16(src);
1805}
1806
1807static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1808    SkASSERT(require_0(src));
1809    return dst;
1810}
1811
1812static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1813    SkASSERT(require_255(src));
1814    return dst;
1815}
1816
1817static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1818    SkASSERT(require_255(src));
1819    return SkPixel32ToPixel16(src);
1820}
1821
1822static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1823    SkASSERT(require_255(src));
1824    return dst;
1825}
1826
1827static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1828    SkASSERT(require_0(src));
1829    return dst;
1830}
1831
1832static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1833    unsigned isa = 255 - SkGetPackedA32(src);
1834
1835    return SkPackRGB16(
1836           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1837           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1838           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1839}
1840
1841static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1842    SkASSERT(require_0(src));
1843    return dst;
1844}
1845
1846static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1847    SkASSERT(require_255(src));
1848    return SkPixel32ToPixel16(src);
1849}
1850
1851static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1852    SkASSERT(require_255(src));
1853    return dst;
1854}
1855
1856/*********
1857    darken and lighten boil down to this.
1858
1859    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1860    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1861
1862    if (Sa == 0) these become
1863        darken  = Dc + min(0, Dc) = 0
1864        lighten = Dc + max(0, Dc) = Dc
1865
1866    if (Sa == 1) these become
1867        darken  = min(Sc, Dc)
1868        lighten = max(Sc, Dc)
1869*/
1870
1871static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1872    SkASSERT(require_0(src));
1873    return 0;
1874}
1875
1876static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1877    SkASSERT(require_255(src));
1878    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1879    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1880    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1881    return SkPackRGB16(r, g, b);
1882}
1883
1884static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1885    SkASSERT(require_0(src));
1886    return dst;
1887}
1888
1889static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1890    SkASSERT(require_255(src));
1891    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1892    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1893    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1894    return SkPackRGB16(r, g, b);
1895}
1896
1897struct Proc16Rec {
1898    SkXfermodeProc16    fProc16_0;
1899    SkXfermodeProc16    fProc16_255;
1900    SkXfermodeProc16    fProc16_General;
1901};
1902
1903static const Proc16Rec gModeProcs16[] = {
1904    { NULL,                 NULL,                   NULL            }, // CLEAR
1905    { NULL,                 src_modeproc16_255,     NULL            },
1906    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1907    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1908    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1909    { NULL,                 srcin_modeproc16_255,   NULL            },
1910    { NULL,                 dstin_modeproc16_255,   NULL            },
1911    { NULL,                 NULL,                   NULL            },// SRC_OUT
1912    { dstout_modeproc16_0,  NULL,                   NULL            },
1913    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1914    { NULL,                 dstatop_modeproc16_255, NULL            },
1915    { NULL,                 NULL,                   NULL            }, // XOR
1916
1917    { NULL,                 NULL,                   NULL            }, // plus
1918    { NULL,                 NULL,                   NULL            }, // modulate
1919    { NULL,                 NULL,                   NULL            }, // screen
1920    { NULL,                 NULL,                   NULL            }, // overlay
1921    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1922    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1923    { NULL,                 NULL,                   NULL            }, // colordodge
1924    { NULL,                 NULL,                   NULL            }, // colorburn
1925    { NULL,                 NULL,                   NULL            }, // hardlight
1926    { NULL,                 NULL,                   NULL            }, // softlight
1927    { NULL,                 NULL,                   NULL            }, // difference
1928    { NULL,                 NULL,                   NULL            }, // exclusion
1929    { NULL,                 NULL,                   NULL            }, // multiply
1930    { NULL,                 NULL,                   NULL            }, // hue
1931    { NULL,                 NULL,                   NULL            }, // saturation
1932    { NULL,                 NULL,                   NULL            }, // color
1933    { NULL,                 NULL,                   NULL            }, // luminosity
1934};
1935
1936SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1937    SkXfermodeProc16  proc16 = NULL;
1938    if ((unsigned)mode < kModeCount) {
1939        const Proc16Rec& rec = gModeProcs16[mode];
1940        unsigned a = SkColorGetA(srcColor);
1941
1942        if (0 == a) {
1943            proc16 = rec.fProc16_0;
1944        } else if (255 == a) {
1945            proc16 = rec.fProc16_255;
1946        } else {
1947            proc16 = rec.fProc16_General;
1948        }
1949    }
1950    return proc16;
1951}
1952
1953SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1954    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1955    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1956    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1957    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1958    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1959#if !SK_ARM_NEON_IS_NONE
1960    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
1961#endif
1962#if defined(SK_CPU_X86) && !defined(SK_BUILD_FOR_IOS)
1963    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode)
1964#endif
1965SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1966