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