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