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