3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
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"
18 #include "SkUtilsArm.h"
19 #include "SkWriteBuffer.h"
21 #if !SK_ARM_NEON_IS_NONE
22 #include "SkXfermode_opts_arm_neon.h"
25 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
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) {
35 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
36 unsigned result = (prod + (prod >> 8)) >> 8;
37 SkASSERT(result <= 255);
42 static inline unsigned saturated_add(unsigned a, unsigned b) {
52 static inline int clamp_signed_byte(int n) {
61 static inline int clamp_div255round(int prod) {
64 } else if (prod >= 255*255) {
67 return SkDiv255Round(prod);
71 ///////////////////////////////////////////////////////////////////////////////
73 // kClear_Mode, //!< [0, 0]
74 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
78 // kSrc_Mode, //!< [Sa, Sc]
79 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
83 // kDst_Mode, //!< [Da, Dc]
84 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
88 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
89 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
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)));
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));
101 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
102 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
103 // this is the reverse of srcover, just flipping src and dst
104 // see srcover's comment about the 256 for opaqueness guarantees
105 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
108 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
109 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
110 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
113 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
114 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
115 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
118 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
119 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
120 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
123 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
124 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
125 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
128 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
129 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
130 unsigned sa = SkGetPackedA32(src);
131 unsigned da = SkGetPackedA32(dst);
132 unsigned isa = 255 - sa;
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)));
143 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
144 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
145 unsigned sa = SkGetPackedA32(src);
146 unsigned da = SkGetPackedA32(dst);
147 unsigned ida = 255 - da;
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)));
158 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
159 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
160 unsigned sa = SkGetPackedA32(src);
161 unsigned da = SkGetPackedA32(dst);
162 unsigned isa = 255 - sa;
163 unsigned ida = 255 - da;
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)));
174 ///////////////////////////////////////////////////////////////////////////////
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);
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);
194 static inline int srcover_byte(int a, int b) {
195 return a + b - SkAlphaMulAlpha(a, b);
199 // B(Cb, Cs) = Cb x Cs
200 // multiply uses its own version of blendfunc_byte because sa and da are not needed
201 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
202 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
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);
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);
225 static inline int overlay_byte(int sc, int dc, int sa, int da) {
226 int tmp = sc * (255 - da) + dc * (255 - sa);
231 rc = sa * da - 2 * (da - dc) * (sa - sc);
233 return clamp_div255round(rc + tmp);
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);
246 static inline int darken_byte(int sc, int dc, int sa, int da) {
251 return sc + dc - SkDiv255Round(ds);
254 return dc + sc - SkDiv255Round(sd);
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);
268 static inline int lighten_byte(int sc, int dc, int sa, int da) {
273 return sc + dc - SkDiv255Round(ds);
276 return dc + sc - SkDiv255Round(sd);
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);
290 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
294 return SkAlphaMulAlpha(sc, 255 - da);
295 } else if (0 == diff) {
296 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
298 diff = dc * sa / diff;
299 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
301 return clamp_div255round(rc);
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);
314 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
317 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
318 } else if (0 == sc) {
319 return SkAlphaMulAlpha(dc, 255 - sa);
321 int tmp = (da - dc) * sa / sc;
322 rc = sa * (da - ((da < tmp) ? da : tmp))
323 + sc * (255 - da) + dc * (255 - sa);
325 return clamp_div255round(rc);
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);
338 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
343 rc = sa * da - 2 * (da - dc) * (sa - sc);
345 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
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);
357 // returns 255 * sqrt(n/255)
358 static U8CPU sqrt_unit_byte(U8CPU n) {
359 return SkSqrtBits(n, 15+4);
363 static inline int softlight_byte(int sc, int dc, int sa, int da) {
364 int m = da ? dc * 256 / da : 0;
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);
372 int tmp = sqrt_unit_byte(m) - m;
373 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
375 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
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);
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));
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);
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);
407 // The above equation can be simplified as follows
408 int r = 255*(sc + dc) - 2 * sc * dc;
409 return clamp_div255round(r);
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);
421 // The CSS compositing spec introduces the following formulas:
422 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
423 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
424 // while PDF and CG uses the one from Rec. Rec. 601
425 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
426 static inline int Lum(int r, int g, int b)
428 return SkDiv255Round(r * 77 + g * 150 + b * 28);
431 static inline int min2(int a, int b) { return a < b ? a : b; }
432 static inline int max2(int a, int b) { return a > b ? a : b; }
433 #define minimum(a, b, c) min2(min2(a, b), c)
434 #define maximum(a, b, c) max2(max2(a, b), c)
436 static inline int Sat(int r, int g, int b) {
437 return maximum(r, g, b) - minimum(r, g, b);
440 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
442 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
452 static inline void SetSat(int* r, int* g, int* b, int s) {
455 setSaturationComponents(r, g, b, s);
456 } else if(*r <= *b) {
457 setSaturationComponents(r, b, g, s);
459 setSaturationComponents(b, r, g, s);
461 } else if(*r <= *b) {
462 setSaturationComponents(g, r, b, s);
463 } else if(*g <= *b) {
464 setSaturationComponents(g, b, r, s);
466 setSaturationComponents(b, g, r, s);
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);
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);
481 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
483 *r = L + SkMulDiv(*r - L, numer, denom);
484 *g = L + SkMulDiv(*g - L, numer, denom);
485 *b = L + SkMulDiv(*b - L, numer, denom);
489 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
490 int d = l - Lum(*r, *g, *b);
495 clipColor(r, g, b, a);
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)
503 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
504 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
505 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
506 int sr = SkGetPackedR32(src);
507 int sg = SkGetPackedG32(src);
508 int sb = SkGetPackedB32(src);
509 int sa = SkGetPackedA32(src);
511 int dr = SkGetPackedR32(dst);
512 int dg = SkGetPackedG32(dst);
513 int db = SkGetPackedB32(dst);
514 int da = SkGetPackedA32(dst);
521 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
522 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
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);
537 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
538 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
539 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
540 int sr = SkGetPackedR32(src);
541 int sg = SkGetPackedG32(src);
542 int sb = SkGetPackedB32(src);
543 int sa = SkGetPackedA32(src);
545 int dr = SkGetPackedR32(dst);
546 int dg = SkGetPackedG32(dst);
547 int db = SkGetPackedB32(dst);
548 int da = SkGetPackedA32(dst);
555 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
556 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
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);
571 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
572 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
573 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
574 int sr = SkGetPackedR32(src);
575 int sg = SkGetPackedG32(src);
576 int sb = SkGetPackedB32(src);
577 int sa = SkGetPackedA32(src);
579 int dr = SkGetPackedR32(dst);
580 int dg = SkGetPackedG32(dst);
581 int db = SkGetPackedB32(dst);
582 int da = SkGetPackedA32(dst);
589 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
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);
604 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
605 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
606 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
607 int sr = SkGetPackedR32(src);
608 int sg = SkGetPackedG32(src);
609 int sb = SkGetPackedB32(src);
610 int sa = SkGetPackedA32(src);
612 int dr = SkGetPackedR32(dst);
613 int dg = SkGetPackedG32(dst);
614 int db = SkGetPackedB32(dst);
615 int da = SkGetPackedA32(dst);
622 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
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);
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 },
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 },
669 ///////////////////////////////////////////////////////////////////////////////
671 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
675 bool SkXfermode::asMode(Mode* mode) const {
679 bool SkXfermode::asNewEffect(GrEffect** effect, GrTexture* background) const {
683 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
687 GrTexture* background) {
688 if (NULL == xfermode) {
689 return ModeAsCoeff(kSrcOver_Mode, src, dst);
690 } else if (xfermode->asCoeff(src, dst)) {
693 return xfermode->asNewEffect(effect, background);
697 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
698 // no-op. subclasses should override this
702 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);
708 for (int i = count - 1; i >= 0; --i) {
709 dst[i] = this->xferColor(src[i], dst[i]);
712 for (int i = count - 1; i >= 0; --i) {
715 SkPMColor dstC = dst[i];
716 SkPMColor C = this->xferColor(src[i], dstC);
718 C = SkFourByteInterp(C, dstC, a);
726 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);
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));
737 for (int i = count - 1; i >= 0; --i) {
740 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
741 SkPMColor C = this->xferColor(src[i], dstC);
743 C = SkFourByteInterp(C, dstC, a);
745 dst[i] = SkPixel32ToPixel16_ToU16(C);
751 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);
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));
762 for (int i = count - 1; i >= 0; --i) {
765 SkAlpha dstA = dst[i];
766 unsigned A = SkGetPackedA32(this->xferColor(src[i],
767 (SkPMColor)(dstA << SK_A32_SHIFT)));
769 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
777 //////////////////////////////////////////////////////////////////////////////
781 #include "GrEffect.h"
782 #include "GrCoordTransform.h"
783 #include "GrEffectUnitTest.h"
784 #include "GrTBackendEffectFactory.h"
785 #include "gl/GrGLEffect.h"
786 #include "gl/GrGLShaderBuilder.h"
789 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
791 class XferEffect : public GrEffect {
793 static bool IsSupportedMode(SkXfermode::Mode mode) {
794 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
797 static GrEffect* Create(SkXfermode::Mode mode, GrTexture* background) {
798 if (!IsSupportedMode(mode)) {
801 return SkNEW_ARGS(XferEffect, (mode, background));
805 virtual void getConstantColorComponents(GrColor* color,
806 uint32_t* validFlags) const SK_OVERRIDE {
810 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
811 return GrTBackendEffectFactory<XferEffect>::getInstance();
814 static const char* Name() { return "XferEffect"; }
816 SkXfermode::Mode mode() const { return fMode; }
817 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; }
819 class GLEffect : public GrGLEffect {
821 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
822 : GrGLEffect(factory) {
824 virtual void emitCode(GrGLShaderBuilder* builder,
825 const GrDrawEffect& drawEffect,
826 const GrEffectKey& 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;
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");
840 dstColor = builder->dstColor();
842 SkASSERT(NULL != dstColor);
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");
849 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
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);
856 case SkXfermode::kOverlay_Mode:
857 // Overlay is Hard-Light with the src and dst reversed
858 HardLight(builder, outputColor, dstColor, inputColor);
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",
864 inputColor, dstColor, inputColor,
865 dstColor, inputColor, dstColor);
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",
871 inputColor, dstColor, inputColor,
872 dstColor, inputColor, dstColor);
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');
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');
884 case SkXfermode::kHardLight_Mode:
885 HardLight(builder, outputColor, inputColor, dstColor);
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");
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);
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);
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);
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,
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);
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,
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);
942 case SkXfermode::kColor_Mode: {
943 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
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);
954 case SkXfermode::kLuminosity_Mode: {
955 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
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);
967 SkFAIL("Unknown XferEffect mode.");
972 static inline void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&,
973 GrEffectKeyBuilder* b) {
974 // The background may come from the dst or from a texture.
975 uint32_t key = drawEffect.effect()->numTextures();
977 key |= drawEffect.castEffect<XferEffect>().mode() << 1;
982 static void HardLight(GrGLShaderBuilder* builder,
986 static const char kComponents[] = {'r', 'g', 'b'};
987 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
988 char component = kComponents[i];
989 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
990 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
991 builder->fsCodeAppend("\t\t} else {\n");
992 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
993 final, component, src, dst, dst, dst, component, src, src, component);
994 builder->fsCodeAppend("\t\t}\n");
996 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
997 final, src, dst, dst, src);
1000 // Does one component of color-dodge
1001 static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1005 const char component) {
1006 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1007 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1008 final, component, src, component, dst);
1009 builder->fsCodeAppend("\t\t} else {\n");
1010 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1011 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1012 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",
1013 final, component, src, dst, src, component, dst, dst, component,
1015 builder->fsCodeAppend("\t\t\t} else {\n");
1016 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1017 dst, dst, component, src);
1018 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1019 final, component, src, src, component, dst, dst, component, src);
1020 builder->fsCodeAppend("\t\t\t}\n");
1021 builder->fsCodeAppend("\t\t}\n");
1024 // Does one component of color-burn
1025 static void ColorBurnComponent(GrGLShaderBuilder* builder,
1029 const char component) {
1030 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1031 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1032 final, component, src, dst, src, component, dst, dst, component,
1034 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1035 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1036 final, component, dst, component, src);
1037 builder->fsCodeAppend("\t\t} else {\n");
1038 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1039 dst, dst, dst, component, src, src, component);
1040 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1041 final, component, src, src, component, dst, dst, component, src);
1042 builder->fsCodeAppend("\t\t}\n");
1045 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1046 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1050 const char component) {
1052 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1053 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1054 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",
1055 final, component, dst, component, dst, component, src, src,
1056 component, dst, dst, src, component, dst, component, src, src,
1058 // else if (4D < Da)
1059 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1060 dst, component, dst);
1061 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1062 dst, component, dst, component);
1063 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1064 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1065 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1066 // (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
1067 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",
1068 final, component, src, component, src, component, dst, component,
1069 src, src, component, dst, src, src, component, src, src,
1071 builder->fsCodeAppendf("\t\t\t} else {\n");
1072 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1073 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",
1074 final, component, dst, dst, component, src, src, component, dst,
1075 src, component, dst, component, src, src, component, src,
1077 builder->fsCodeAppendf("\t\t\t}\n");
1080 // Adds a function that takes two colors and an alpha as input. It produces a color with the
1081 // hue and saturation of the first color, the luminosity of the second color, and the input
1082 // alpha. It has this signature:
1083 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1084 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1085 // Emit a helper that gets the luminance of a color.
1086 SkString getFunction;
1087 GrGLShaderVar getLumArgs[] = {
1088 GrGLShaderVar("color", kVec3f_GrSLType),
1090 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1091 builder->fsEmitFunction(kFloat_GrSLType,
1093 SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1097 // Emit the set luminance function.
1098 GrGLShaderVar setLumArgs[] = {
1099 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1100 GrGLShaderVar("alpha", kFloat_GrSLType),
1101 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1103 SkString setLumBody;
1104 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1105 setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1106 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1107 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1108 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1109 "\tif (minComp < 0.0) {\n"
1110 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1112 "\tif (maxComp > alpha) {\n"
1113 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1115 "\treturn outColor;\n");
1116 builder->fsEmitFunction(kVec3f_GrSLType,
1118 SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1123 // Adds a function that creates a color with the hue and luminosity of one input color and
1124 // the saturation of another color. It will have this signature:
1125 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1126 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1127 // Emit a helper that gets the saturation of a color
1128 SkString getFunction;
1129 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1130 SkString getSatBody;
1131 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1132 "min(min(color.r, color.g), color.b);\n");
1133 builder->fsEmitFunction(kFloat_GrSLType,
1135 SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1139 // Emit a helper that sets the saturation given sorted input channels. This used
1140 // to use inout params for min, mid, and max components but that seems to cause
1141 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1142 // adjusted min, mid, and max inputs, respectively.
1143 SkString helperFunction;
1144 GrGLShaderVar helperArgs[] = {
1145 GrGLShaderVar("minComp", kFloat_GrSLType),
1146 GrGLShaderVar("midComp", kFloat_GrSLType),
1147 GrGLShaderVar("maxComp", kFloat_GrSLType),
1148 GrGLShaderVar("sat", kFloat_GrSLType),
1150 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1151 "\t\tvec3 result;\n"
1152 "\t\tresult.r = 0.0;\n"
1153 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1154 "\t\tresult.b = sat;\n"
1155 "\t\treturn result;\n"
1157 "\t\treturn vec3(0, 0, 0);\n"
1159 builder->fsEmitFunction(kVec3f_GrSLType,
1160 "set_saturation_helper",
1161 SK_ARRAY_COUNT(helperArgs), helperArgs,
1165 GrGLShaderVar setSatArgs[] = {
1166 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1167 GrGLShaderVar("satColor", kVec3f_GrSLType),
1169 const char* helpFunc = helperFunction.c_str();
1170 SkString setSatBody;
1171 setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1172 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1173 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1174 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1175 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1176 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1178 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1180 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1181 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1182 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1183 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1185 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1187 "\treturn hueLumColor;\n",
1188 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1189 helpFunc, helpFunc);
1190 builder->fsEmitFunction(kVec3f_GrSLType,
1192 SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1198 typedef GrGLEffect INHERITED;
1201 GR_DECLARE_EFFECT_TEST;
1204 XferEffect(SkXfermode::Mode mode, GrTexture* background)
1207 fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1208 this->addCoordTransform(&fBackgroundTransform);
1209 fBackgroundAccess.reset(background);
1210 this->addTextureAccess(&fBackgroundAccess);
1212 this->setWillReadDstColor();
1215 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1216 const XferEffect& s = CastEffect<XferEffect>(other);
1217 return fMode == s.fMode &&
1218 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1221 SkXfermode::Mode fMode;
1222 GrCoordTransform fBackgroundTransform;
1223 GrTextureAccess fBackgroundAccess;
1225 typedef GrEffect INHERITED;
1228 GR_DEFINE_EFFECT_TEST(XferEffect);
1229 GrEffect* XferEffect::TestCreate(SkRandom* rand,
1231 const GrDrawTargetCaps&,
1233 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1235 return SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL));
1240 ///////////////////////////////////////////////////////////////////////////////
1241 ///////////////////////////////////////////////////////////////////////////////
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;
1249 fMode = (SkXfermode::Mode)mode32;
1251 const ProcCoeff& rec = gProcCoeffs[fMode];
1253 // these may be valid, or may be CANNOT_USE_COEFF
1254 fSrcCoeff = rec.fSC;
1255 fDstCoeff = rec.fDC;
1258 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1265 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1266 if (CANNOT_USE_COEFF == fSrcCoeff) {
1279 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1280 const SkPMColor* SK_RESTRICT src, int count,
1281 const SkAlpha* SK_RESTRICT aa) const {
1282 SkASSERT(dst && src && count >= 0);
1284 SkXfermodeProc proc = fProc;
1288 for (int i = count - 1; i >= 0; --i) {
1289 dst[i] = proc(src[i], dst[i]);
1292 for (int i = count - 1; i >= 0; --i) {
1295 SkPMColor dstC = dst[i];
1296 SkPMColor C = proc(src[i], dstC);
1298 C = SkFourByteInterp(C, dstC, a);
1307 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1308 const SkPMColor* SK_RESTRICT src, int count,
1309 const SkAlpha* SK_RESTRICT aa) const {
1310 SkASSERT(dst && src && count >= 0);
1312 SkXfermodeProc proc = fProc;
1316 for (int i = count - 1; i >= 0; --i) {
1317 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1318 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1321 for (int i = count - 1; i >= 0; --i) {
1324 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1325 SkPMColor C = proc(src[i], dstC);
1327 C = SkFourByteInterp(C, dstC, a);
1329 dst[i] = SkPixel32ToPixel16_ToU16(C);
1336 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1337 const SkPMColor* SK_RESTRICT src, int count,
1338 const SkAlpha* SK_RESTRICT aa) const {
1339 SkASSERT(dst && src && count >= 0);
1341 SkXfermodeProc proc = fProc;
1345 for (int i = count - 1; i >= 0; --i) {
1346 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1347 dst[i] = SkToU8(SkGetPackedA32(res));
1350 for (int i = count - 1; i >= 0; --i) {
1353 SkAlpha dstA = dst[i];
1354 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1355 unsigned A = SkGetPackedA32(res);
1357 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1367 bool SkProcCoeffXfermode::asNewEffect(GrEffect** effect, GrTexture* background) const {
1368 if (XferEffect::IsSupportedMode(fMode)) {
1369 if (NULL != effect) {
1370 *effect = XferEffect::Create(fMode, background);
1371 SkASSERT(NULL != *effect);
1379 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1380 this->INHERITED::flatten(buffer);
1381 buffer.write32(fMode);
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"
1393 return gModeStrings[mode];
1394 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1397 #ifndef SK_IGNORE_TO_STRING
1398 void SkProcCoeffXfermode::toString(SkString* str) const {
1399 str->append("SkProcCoeffXfermode: ");
1401 str->append("mode: ");
1402 str->append(ModeName(fMode));
1404 static const char* gCoeffStrings[kCoeffCount] = {
1405 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1408 str->append(" src: ");
1409 if (CANNOT_USE_COEFF == fSrcCoeff) {
1410 str->append("can't use");
1412 str->append(gCoeffStrings[fSrcCoeff]);
1415 str->append(" dst: ");
1416 if (CANNOT_USE_COEFF == fDstCoeff) {
1417 str->append("can't use");
1419 str->append(gCoeffStrings[fDstCoeff]);
1424 ///////////////////////////////////////////////////////////////////////////////
1426 class SkClearXfermode : public SkProcCoeffXfermode {
1428 static SkClearXfermode* Create(const ProcCoeff& rec) {
1429 return SkNEW_ARGS(SkClearXfermode, (rec));
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;
1435 SK_TO_STRING_OVERRIDE()
1436 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1439 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1440 SkClearXfermode(SkReadBuffer& buffer)
1441 : SkProcCoeffXfermode(buffer) {}
1443 typedef SkProcCoeffXfermode INHERITED;
1446 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);
1452 memset(dst, 0, count << 2);
1454 for (int i = count - 1; i >= 0; --i) {
1458 } else if (a != 0) {
1459 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1464 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);
1470 memset(dst, 0, count);
1472 for (int i = count - 1; i >= 0; --i) {
1476 } else if (0 != a) {
1477 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1483 #ifndef SK_IGNORE_TO_STRING
1484 void SkClearXfermode::toString(SkString* str) const {
1485 this->INHERITED::toString(str);
1489 ///////////////////////////////////////////////////////////////////////////////
1491 class SkSrcXfermode : public SkProcCoeffXfermode {
1493 static SkSrcXfermode* Create(const ProcCoeff& rec) {
1494 return SkNEW_ARGS(SkSrcXfermode, (rec));
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;
1500 SK_TO_STRING_OVERRIDE()
1501 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1504 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1505 SkSrcXfermode(SkReadBuffer& buffer)
1506 : SkProcCoeffXfermode(buffer) {}
1508 typedef SkProcCoeffXfermode INHERITED;
1511 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);
1517 memcpy(dst, src, count << 2);
1519 for (int i = count - 1; i >= 0; --i) {
1523 } else if (a != 0) {
1524 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1530 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);
1536 for (int i = count - 1; i >= 0; --i) {
1537 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1540 for (int i = count - 1; i >= 0; --i) {
1543 unsigned srcA = SkGetPackedA32(src[i]);
1545 dst[i] = SkToU8(srcA);
1547 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1553 #ifndef SK_IGNORE_TO_STRING
1554 void SkSrcXfermode::toString(SkString* str) const {
1555 this->INHERITED::toString(str);
1559 ///////////////////////////////////////////////////////////////////////////////
1561 class SkDstInXfermode : public SkProcCoeffXfermode {
1563 static SkDstInXfermode* Create(const ProcCoeff& rec) {
1564 return SkNEW_ARGS(SkDstInXfermode, (rec));
1567 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1569 SK_TO_STRING_OVERRIDE()
1570 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1573 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1574 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1576 typedef SkProcCoeffXfermode INHERITED;
1579 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);
1588 return this->INHERITED::xfer32(dst, src, count, aa);
1592 unsigned a = SkGetPackedA32(*src);
1593 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1596 } while (--count != 0);
1599 #ifndef SK_IGNORE_TO_STRING
1600 void SkDstInXfermode::toString(SkString* str) const {
1601 this->INHERITED::toString(str);
1605 ///////////////////////////////////////////////////////////////////////////////
1607 class SkDstOutXfermode : public SkProcCoeffXfermode {
1609 static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1610 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1613 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1615 SK_TO_STRING_OVERRIDE()
1616 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1619 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1620 SkDstOutXfermode(SkReadBuffer& buffer)
1621 : INHERITED(buffer) {}
1623 typedef SkProcCoeffXfermode INHERITED;
1626 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);
1635 return this->INHERITED::xfer32(dst, src, count, aa);
1639 unsigned a = SkGetPackedA32(*src);
1640 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1643 } while (--count != 0);
1646 #ifndef SK_IGNORE_TO_STRING
1647 void SkDstOutXfermode::toString(SkString* str) const {
1648 this->INHERITED::toString(str);
1652 ///////////////////////////////////////////////////////////////////////////////
1654 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1655 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1657 // Technically, can't be static and passed as a template parameter. So we use anonymous namespace.
1659 SkXfermode* create_mode(int iMode) {
1660 SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1662 ProcCoeff rec = gProcCoeffs[mode];
1663 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1668 SkXfermode* xfer = NULL;
1669 // check if we have a platform optim for that
1670 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
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.
1678 case SkXfermode::kClear_Mode:
1679 xfer = SkClearXfermode::Create(rec);
1681 case SkXfermode::kSrc_Mode:
1682 xfer = SkSrcXfermode::Create(rec);
1684 case SkXfermode::kSrcOver_Mode:
1685 SkASSERT(false); // should not land here
1687 case SkXfermode::kDstIn_Mode:
1688 xfer = SkDstInXfermode::Create(rec);
1690 case SkXfermode::kDstOut_Mode:
1691 xfer = SkDstOutXfermode::Create(rec);
1694 // no special-case, just rely in the rec and its function-ptrs
1695 xfer = SkProcCoeffXfermode::Create(rec, mode);
1704 SkXfermode* SkXfermode::Create(Mode mode) {
1705 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1707 if ((unsigned)mode >= kModeCount) {
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) {
1718 SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode);
1719 return SkSafeRef(cached[mode]);
1722 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1723 SkXfermodeProc proc = NULL;
1724 if ((unsigned)mode < kModeCount) {
1725 proc = gProcCoeffs[mode].fProc;
1730 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1731 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1733 if ((unsigned)mode >= (unsigned)kModeCount) {
1734 // illegal mode parameter
1738 const ProcCoeff& rec = gProcCoeffs[mode];
1740 if (CANNOT_USE_COEFF == rec.fSC) {
1744 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1754 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1757 *mode = kSrcOver_Mode;
1761 return xfer->asMode(mode);
1764 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1766 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1768 return xfer->asCoeff(src, dst);
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)) {
1780 ///////////////////////////////////////////////////////////////////////////////
1781 //////////// 16bit xfermode procs
1784 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1785 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1788 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1789 SkASSERT(require_255(src));
1790 return SkPixel32ToPixel16(src);
1793 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1797 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1798 SkASSERT(require_0(src));
1802 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1803 SkASSERT(require_255(src));
1804 return SkPixel32ToPixel16(src);
1807 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1808 SkASSERT(require_0(src));
1812 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1813 SkASSERT(require_255(src));
1817 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1818 SkASSERT(require_255(src));
1819 return SkPixel32ToPixel16(src);
1822 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1823 SkASSERT(require_255(src));
1827 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1828 SkASSERT(require_0(src));
1832 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1833 unsigned isa = 255 - SkGetPackedA32(src);
1836 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1837 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1838 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1841 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1842 SkASSERT(require_0(src));
1846 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1847 SkASSERT(require_255(src));
1848 return SkPixel32ToPixel16(src);
1851 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1852 SkASSERT(require_255(src));
1857 darken and lighten boil down to this.
1859 darken = (1 - Sa) * Dc + min(Sc, Dc)
1860 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1862 if (Sa == 0) these become
1863 darken = Dc + min(0, Dc) = 0
1864 lighten = Dc + max(0, Dc) = Dc
1866 if (Sa == 1) these become
1867 darken = min(Sc, Dc)
1868 lighten = max(Sc, Dc)
1871 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1872 SkASSERT(require_0(src));
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);
1884 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1885 SkASSERT(require_0(src));
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);
1898 SkXfermodeProc16 fProc16_0;
1899 SkXfermodeProc16 fProc16_255;
1900 SkXfermodeProc16 fProc16_General;
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
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
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);
1943 proc16 = rec.fProc16_0;
1944 } else if (255 == a) {
1945 proc16 = rec.fProc16_255;
1947 proc16 = rec.fProc16_General;
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)
1962 #if defined(SK_CPU_X86) && !defined(SK_BUILD_FOR_IOS)
1963 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode)
1965 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END