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