• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
saturated_add(unsigned a,unsigned b)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 
clamp_signed_byte(int n)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 
clamp_div255round(int prod)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]
clear_modeproc(SkPMColor src,SkPMColor dst)74 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75     return 0;
76 }
77 
78 //  kSrc_Mode,      //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)79 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80     return src;
81 }
82 
83 //  kDst_Mode,      //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)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]
srcover_modeproc(SkPMColor src,SkPMColor dst)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]
dstover_modeproc(SkPMColor src,SkPMColor dst)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]
srcin_modeproc(SkPMColor src,SkPMColor dst)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]
dstin_modeproc(SkPMColor src,SkPMColor dst)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)]
srcout_modeproc(SkPMColor src,SkPMColor dst)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)]
dstout_modeproc(SkPMColor src,SkPMColor dst)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]
srcatop_modeproc(SkPMColor src,SkPMColor dst)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)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)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]
xor_modeproc(SkPMColor src,SkPMColor dst)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
plus_modeproc(SkPMColor src,SkPMColor dst)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
modulate_modeproc(SkPMColor src,SkPMColor dst)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 
srcover_byte(int a,int b)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
blendfunc_multiply_byte(int sc,int dc,int sa,int da)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 
multiply_modeproc(SkPMColor src,SkPMColor dst)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
screen_modeproc(SkPMColor src,SkPMColor dst)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
overlay_byte(int sc,int dc,int sa,int da)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 }
overlay_modeproc(SkPMColor src,SkPMColor dst)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
darken_byte(int sc,int dc,int sa,int da)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 }
darken_modeproc(SkPMColor src,SkPMColor dst)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
lighten_byte(int sc,int dc,int sa,int da)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 }
lighten_modeproc(SkPMColor src,SkPMColor dst)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
colordodge_byte(int sc,int dc,int sa,int da)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 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)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
colorburn_byte(int sc,int dc,int sa,int da)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 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)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
hardlight_byte(int sc,int dc,int sa,int da)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 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)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)
sqrt_unit_byte(U8CPU n)358 static U8CPU sqrt_unit_byte(U8CPU n) {
359     return SkSqrtBits(n, 15+4);
360 }
361 
362 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)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 }
softlight_modeproc(SkPMColor src,SkPMColor dst)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
difference_byte(int sc,int dc,int sa,int da)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 }
difference_modeproc(SkPMColor src,SkPMColor dst)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
exclusion_byte(int sc,int dc,int,int)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 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)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
Lum(int r,int g,int b)426 static inline int Lum(int r, int g, int b)
427 {
428     return SkDiv255Round(r * 77 + g * 150 + b * 28);
429 }
430 
min2(int a,int b)431 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int 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 
Sat(int r,int g,int b)436 static inline int Sat(int r, int g, int b) {
437     return maximum(r, g, b) - minimum(r, g, b);
438 }
439 
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)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 
SetSat(int * r,int * g,int * b,int s)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 
clipColor(int * r,int * g,int * b,int a)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 
SetLum(int * r,int * g,int * b,int a,int l)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.
hue_modeproc(SkPMColor src,SkPMColor dst)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.
saturation_modeproc(SkPMColor src,SkPMColor dst)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.
color_modeproc(SkPMColor src,SkPMColor dst)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.
luminosity_modeproc(SkPMColor src,SkPMColor dst)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 
asCoeff(Coeff * src,Coeff * dst) const671 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
672     return false;
673 }
674 
asMode(Mode * mode) const675 bool SkXfermode::asMode(Mode* mode) const {
676     return false;
677 }
678 
asFragmentProcessor(GrFragmentProcessor **,GrTexture *) const679 bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
680     return false;
681 }
682 
asFragmentProcessorOrCoeff(SkXfermode * xfermode,GrFragmentProcessor ** fp,Coeff * src,Coeff * dst,GrTexture * background)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 
xferColor(SkPMColor src,SkPMColor dst) const694 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
695     // no-op. subclasses should override this
696     return dst;
697 }
698 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const699 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 
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const723 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 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const748 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:
IsSupportedMode(SkXfermode::Mode mode)790     static bool IsSupportedMode(SkXfermode::Mode mode) {
791         return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
792     }
793 
Create(SkXfermode::Mode mode,GrTexture * background)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 
getConstantColorComponents(GrColor * color,uint32_t * validFlags) const802     virtual void getConstantColorComponents(GrColor* color,
803                                             uint32_t* validFlags) const SK_OVERRIDE {
804         *validFlags = 0;
805     }
806 
getFactory() const807     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
808         return GrTBackendFragmentProcessorFactory<XferEffect>::getInstance();
809     }
810 
Name()811     static const char* Name() { return "XferEffect"; }
812 
mode() const813     SkXfermode::Mode mode() const { return fMode; }
backgroundAccess() const814     const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
815 
816     class GLProcessor : public GrGLFragmentProcessor {
817     public:
GLProcessor(const GrBackendProcessorFactory & factory,const GrProcessor &)818         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
819             : INHERITED(factory) {
820         }
emitCode(GrGLProgramBuilder * builder,const GrFragmentProcessor & fp,const GrProcessorKey & key,const char * outputColor,const char * inputColor,const TransformedCoordsArray & coords,const TextureSamplerArray & samplers)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 
GenKey(const GrProcessor & proc,const GrGLCaps &,GrProcessorKeyBuilder * b)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:
HardLight(GrGLFragmentShaderBuilder * fsBuilder,const char * final,const char * src,const char * dst)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
ColorDodgeComponent(GrGLFragmentShaderBuilder * fsBuilder,const char * final,const char * src,const char * dst,const char component)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
ColorBurnComponent(GrGLFragmentShaderBuilder * fsBuilder,const char * final,const char * src,const char * dst,const char component)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.
SoftLightComponentPosDstAlpha(GrGLFragmentShaderBuilder * fsBuilder,const char * final,const char * src,const char * dst,const char component)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).
AddLumFunction(GrGLFragmentShaderBuilder * fsBuilder,SkString * setLumFunction)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)
AddSatFunction(GrGLFragmentShaderBuilder * fsBuilder,SkString * setSatFunction)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:
XferEffect(SkXfermode::Mode mode,GrTexture * background)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     }
onIsEqual(const GrProcessor & other) const1214     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);
TestCreate(SkRandom * rand,GrContext *,const GrDrawTargetCaps &,GrTexture * [])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
SkProcCoeffXfermode(SkReadBuffer & buffer)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 
CreateProc(SkReadBuffer & buffer)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 
flatten(SkWriteBuffer & buffer) const1267 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1268     buffer.write32(fMode);
1269 }
1270 
asMode(Mode * mode) const1271 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1272     if (mode) {
1273         *mode = fMode;
1274     }
1275     return true;
1276 }
1277 
asCoeff(Coeff * sc,Coeff * dc) const1278 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 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1292 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 
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1320 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 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1349 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
asFragmentProcessor(GrFragmentProcessor ** fp,GrTexture * background) const1380 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 
ModeName(Mode mode)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
toString(SkString * str) const1407 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:
Create(const ProcCoeff & rec)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:
SkClearXfermode(const ProcCoeff & rec)1447     SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1448 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkClearXfermode(SkReadBuffer & buffer)1449     SkClearXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1450 #endif
1451 
1452     typedef SkProcCoeffXfermode INHERITED;
1453 };
1454 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1455 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 }
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1473 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
toString(SkString * str) const1493 void SkClearXfermode::toString(SkString* str) const {
1494     this->INHERITED::toString(str);
1495 }
1496 #endif
1497 
1498 ///////////////////////////////////////////////////////////////////////////////
1499 
1500 class SkSrcXfermode : public SkProcCoeffXfermode {
1501 public:
Create(const ProcCoeff & rec)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:
SkSrcXfermode(const ProcCoeff & rec)1512     SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1513 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkSrcXfermode(SkReadBuffer & buffer)1514     SkSrcXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1515 #endif
1516     typedef SkProcCoeffXfermode INHERITED;
1517 };
1518 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1519 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 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1538 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
toString(SkString * str) const1562 void SkSrcXfermode::toString(SkString* str) const {
1563     this->INHERITED::toString(str);
1564 }
1565 #endif
1566 
1567 ///////////////////////////////////////////////////////////////////////////////
1568 
1569 class SkDstInXfermode : public SkProcCoeffXfermode {
1570 public:
Create(const ProcCoeff & rec)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:
SkDstInXfermode(const ProcCoeff & rec)1580     SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1581 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkDstInXfermode(SkReadBuffer & buffer)1582     SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1583 #endif
1584 
1585     typedef SkProcCoeffXfermode INHERITED;
1586 };
1587 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1588 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
toString(SkString * str) const1609 void SkDstInXfermode::toString(SkString* str) const {
1610     this->INHERITED::toString(str);
1611 }
1612 #endif
1613 
1614 ///////////////////////////////////////////////////////////////////////////////
1615 
1616 class SkDstOutXfermode : public SkProcCoeffXfermode {
1617 public:
Create(const ProcCoeff & rec)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:
SkDstOutXfermode(const ProcCoeff & rec)1627     SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1628 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkDstOutXfermode(SkReadBuffer & buffer)1629     SkDstOutXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1630 #endif
1631 
1632     typedef SkProcCoeffXfermode INHERITED;
1633 };
1634 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1635 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
toString(SkString * str) const1656 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 {
create_mode(int iMode)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 
Create(Mode mode)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 
GetProc(Mode mode)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 
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)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 
AsMode(const SkXfermode * xfer,Mode * mode)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 
AsCoeff(const SkXfermode * xfer,Coeff * src,Coeff * dst)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 
IsMode(const SkXfermode * xfer,Mode mode)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
require_255(SkPMColor src)1793 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
require_0(SkPMColor src)1794 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1795 #endif
1796 
src_modeproc16_255(SkPMColor src,uint16_t dst)1797 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1798     SkASSERT(require_255(src));
1799     return SkPixel32ToPixel16(src);
1800 }
1801 
dst_modeproc16(SkPMColor src,uint16_t dst)1802 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1803     return dst;
1804 }
1805 
srcover_modeproc16_0(SkPMColor src,uint16_t dst)1806 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1807     SkASSERT(require_0(src));
1808     return dst;
1809 }
1810 
srcover_modeproc16_255(SkPMColor src,uint16_t dst)1811 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1812     SkASSERT(require_255(src));
1813     return SkPixel32ToPixel16(src);
1814 }
1815 
dstover_modeproc16_0(SkPMColor src,uint16_t dst)1816 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1817     SkASSERT(require_0(src));
1818     return dst;
1819 }
1820 
dstover_modeproc16_255(SkPMColor src,uint16_t dst)1821 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1822     SkASSERT(require_255(src));
1823     return dst;
1824 }
1825 
srcin_modeproc16_255(SkPMColor src,uint16_t dst)1826 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1827     SkASSERT(require_255(src));
1828     return SkPixel32ToPixel16(src);
1829 }
1830 
dstin_modeproc16_255(SkPMColor src,uint16_t dst)1831 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1832     SkASSERT(require_255(src));
1833     return dst;
1834 }
1835 
dstout_modeproc16_0(SkPMColor src,uint16_t dst)1836 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1837     SkASSERT(require_0(src));
1838     return dst;
1839 }
1840 
srcatop_modeproc16(SkPMColor src,uint16_t dst)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 
srcatop_modeproc16_0(SkPMColor src,uint16_t dst)1850 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1851     SkASSERT(require_0(src));
1852     return dst;
1853 }
1854 
srcatop_modeproc16_255(SkPMColor src,uint16_t dst)1855 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1856     SkASSERT(require_255(src));
1857     return SkPixel32ToPixel16(src);
1858 }
1859 
dstatop_modeproc16_255(SkPMColor src,uint16_t dst)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 
darken_modeproc16_0(SkPMColor src,uint16_t dst)1880 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1881     SkASSERT(require_0(src));
1882     return 0;
1883 }
1884 
darken_modeproc16_255(SkPMColor src,uint16_t dst)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 
lighten_modeproc16_0(SkPMColor src,uint16_t dst)1893 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1894     SkASSERT(require_0(src));
1895     return dst;
1896 }
1897 
lighten_modeproc16_255(SkPMColor src,uint16_t dst)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 
GetProc16(Mode mode,SkColor srcColor)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
1965