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::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
683 bool SkXfermode::asFragmentProcessorOrCoeff(SkXfermode* xfermode, GrFragmentProcessor** fp,
684 Coeff* src, Coeff* dst, GrTexture* background) {
685 if (NULL == xfermode) {
686 return ModeAsCoeff(kSrcOver_Mode, src, dst);
687 } else if (xfermode->asCoeff(src, dst)) {
690 return xfermode->asFragmentProcessor(fp, background);
694 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
695 // no-op. subclasses should override this
699 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
700 const SkPMColor* SK_RESTRICT src, int count,
701 const SkAlpha* SK_RESTRICT aa) const {
702 SkASSERT(dst && src && count >= 0);
705 for (int i = count - 1; i >= 0; --i) {
706 dst[i] = this->xferColor(src[i], dst[i]);
709 for (int i = count - 1; i >= 0; --i) {
712 SkPMColor dstC = dst[i];
713 SkPMColor C = this->xferColor(src[i], dstC);
715 C = SkFourByteInterp(C, dstC, a);
723 void SkXfermode::xfer16(uint16_t* dst,
724 const SkPMColor* SK_RESTRICT src, int count,
725 const SkAlpha* SK_RESTRICT aa) const {
726 SkASSERT(dst && src && count >= 0);
729 for (int i = count - 1; i >= 0; --i) {
730 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
731 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
734 for (int i = count - 1; i >= 0; --i) {
737 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
738 SkPMColor C = this->xferColor(src[i], dstC);
740 C = SkFourByteInterp(C, dstC, a);
742 dst[i] = SkPixel32ToPixel16_ToU16(C);
748 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
749 const SkPMColor src[], int count,
750 const SkAlpha* SK_RESTRICT aa) const {
751 SkASSERT(dst && src && count >= 0);
754 for (int i = count - 1; i >= 0; --i) {
755 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
756 dst[i] = SkToU8(SkGetPackedA32(res));
759 for (int i = count - 1; i >= 0; --i) {
762 SkAlpha dstA = dst[i];
763 unsigned A = SkGetPackedA32(this->xferColor(src[i],
764 (SkPMColor)(dstA << SK_A32_SHIFT)));
766 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
774 //////////////////////////////////////////////////////////////////////////////
778 #include "GrFragmentProcessor.h"
779 #include "GrCoordTransform.h"
780 #include "GrProcessorUnitTest.h"
781 #include "GrTBackendProcessorFactory.h"
782 #include "gl/GrGLProcessor.h"
783 #include "gl/builders/GrGLProgramBuilder.h"
786 * GrProcessor that implements the all the separable xfer modes that cannot be expressed as Coeffs.
788 class XferEffect : public GrFragmentProcessor {
790 static bool IsSupportedMode(SkXfermode::Mode mode) {
791 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
794 static GrFragmentProcessor* Create(SkXfermode::Mode mode, GrTexture* background) {
795 if (!IsSupportedMode(mode)) {
798 return SkNEW_ARGS(XferEffect, (mode, background));
802 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
803 return GrTBackendFragmentProcessorFactory<XferEffect>::getInstance();
806 static const char* Name() { return "XferEffect"; }
808 SkXfermode::Mode mode() const { return fMode; }
809 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; }
811 class GLProcessor : public GrGLFragmentProcessor {
813 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
814 : INHERITED(factory) {
816 virtual void emitCode(GrGLFPBuilder* builder,
817 const GrFragmentProcessor& fp,
818 const GrProcessorKey& key,
819 const char* outputColor,
820 const char* inputColor,
821 const TransformedCoordsArray& coords,
822 const TextureSamplerArray& samplers) SK_OVERRIDE {
823 SkXfermode::Mode mode = fp.cast<XferEffect>().mode();
824 const GrTexture* backgroundTex =
825 fp.cast<XferEffect>().backgroundAccess().getTexture();
826 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
827 const char* dstColor;
829 dstColor = "bgColor";
830 fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor);
831 fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
832 fsBuilder->codeAppendf(";\n");
834 dstColor = fsBuilder->dstColor();
838 // We don't try to optimize for this case at all
839 if (NULL == inputColor) {
840 fsBuilder->codeAppendf("\t\tconst vec4 ones = vec4(1);\n");
843 fsBuilder->codeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
845 // These all perform src-over on the alpha channel.
846 fsBuilder->codeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
847 outputColor, inputColor, inputColor, dstColor);
850 case SkXfermode::kOverlay_Mode:
851 // Overlay is Hard-Light with the src and dst reversed
852 HardLight(fsBuilder, outputColor, dstColor, inputColor);
854 case SkXfermode::kDarken_Mode:
855 fsBuilder->codeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
856 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
858 inputColor, dstColor, inputColor,
859 dstColor, inputColor, dstColor);
861 case SkXfermode::kLighten_Mode:
862 fsBuilder->codeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
863 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
865 inputColor, dstColor, inputColor,
866 dstColor, inputColor, dstColor);
868 case SkXfermode::kColorDodge_Mode:
869 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
870 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
871 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
873 case SkXfermode::kColorBurn_Mode:
874 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
875 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
876 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
878 case SkXfermode::kHardLight_Mode:
879 HardLight(fsBuilder, outputColor, inputColor, dstColor);
881 case SkXfermode::kSoftLight_Mode:
882 fsBuilder->codeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
883 fsBuilder->codeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
884 fsBuilder->codeAppendf("\t\t} else {\n");
885 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'r');
886 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'g');
887 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'b');
888 fsBuilder->codeAppendf("\t\t}\n");
890 case SkXfermode::kDifference_Mode:
891 fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
892 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
893 outputColor, inputColor, dstColor, inputColor, dstColor,
894 dstColor, inputColor);
896 case SkXfermode::kExclusion_Mode:
897 fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
898 "2.0 * %s.rgb * %s.rgb;\n",
899 outputColor, dstColor, inputColor, dstColor, inputColor);
901 case SkXfermode::kMultiply_Mode:
902 fsBuilder->codeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
903 "(1.0 - %s.a) * %s.rgb + "
904 "%s.rgb * %s.rgb;\n",
905 outputColor, inputColor, dstColor, dstColor, inputColor,
906 inputColor, dstColor);
908 case SkXfermode::kHue_Mode: {
909 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
910 SkString setSat, setLum;
911 AddSatFunction(fsBuilder, &setSat);
912 AddLumFunction(fsBuilder, &setLum);
913 fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
914 dstColor, inputColor);
915 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
916 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
918 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
919 outputColor, inputColor, dstColor, dstColor, inputColor);
922 case SkXfermode::kSaturation_Mode: {
923 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
924 SkString setSat, setLum;
925 AddSatFunction(fsBuilder, &setSat);
926 AddLumFunction(fsBuilder, &setLum);
927 fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
928 dstColor, inputColor);
929 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
930 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
932 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
933 outputColor, inputColor, dstColor, dstColor, inputColor);
936 case SkXfermode::kColor_Mode: {
937 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
939 AddLumFunction(fsBuilder, &setLum);
940 fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
941 inputColor, dstColor);
942 fsBuilder->codeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
943 outputColor, setLum.c_str(), dstColor, inputColor);
944 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
945 outputColor, inputColor, dstColor, dstColor, inputColor);
948 case SkXfermode::kLuminosity_Mode: {
949 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
951 AddLumFunction(fsBuilder, &setLum);
952 fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
953 inputColor, dstColor);
954 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
955 outputColor, setLum.c_str(), dstColor, inputColor);
956 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
957 outputColor, inputColor, dstColor, dstColor, inputColor);
961 SkFAIL("Unknown XferEffect mode.");
966 static inline void GenKey(const GrProcessor& proc, const GrGLCaps&,
967 GrProcessorKeyBuilder* b) {
968 // The background may come from the dst or from a texture.
969 uint32_t key = proc.numTextures();
971 key |= proc.cast<XferEffect>().mode() << 1;
976 static void HardLight(GrGLFPFragmentBuilder* fsBuilder,
980 static const char kComponents[] = {'r', 'g', 'b'};
981 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
982 char component = kComponents[i];
983 fsBuilder->codeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
984 fsBuilder->codeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
985 fsBuilder->codeAppend("\t\t} else {\n");
986 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
987 final, component, src, dst, dst, dst, component, src, src, component);
988 fsBuilder->codeAppend("\t\t}\n");
990 fsBuilder->codeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
991 final, src, dst, dst, src);
994 // Does one component of color-dodge
995 static void ColorDodgeComponent(GrGLFPFragmentBuilder* fsBuilder,
999 const char component) {
1000 fsBuilder->codeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1001 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1002 final, component, src, component, dst);
1003 fsBuilder->codeAppend("\t\t} else {\n");
1004 fsBuilder->codeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1005 fsBuilder->codeAppend("\t\t\tif (0.0 == d) {\n");
1006 fsBuilder->codeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1007 final, component, src, dst, src, component, dst, dst, component,
1009 fsBuilder->codeAppend("\t\t\t} else {\n");
1010 fsBuilder->codeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1011 dst, dst, component, src);
1012 fsBuilder->codeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1013 final, component, src, src, component, dst, dst, component, src);
1014 fsBuilder->codeAppend("\t\t\t}\n");
1015 fsBuilder->codeAppend("\t\t}\n");
1018 // Does one component of color-burn
1019 static void ColorBurnComponent(GrGLFPFragmentBuilder* fsBuilder,
1023 const char component) {
1024 fsBuilder->codeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1025 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1026 final, component, src, dst, src, component, dst, dst, component,
1028 fsBuilder->codeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1029 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1030 final, component, dst, component, src);
1031 fsBuilder->codeAppend("\t\t} else {\n");
1032 fsBuilder->codeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1033 dst, dst, dst, component, src, src, component);
1034 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1035 final, component, src, src, component, dst, dst, component, src);
1036 fsBuilder->codeAppend("\t\t}\n");
1039 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1040 static void SoftLightComponentPosDstAlpha(GrGLFPFragmentBuilder* fsBuilder,
1044 const char component) {
1046 fsBuilder->codeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1047 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1048 fsBuilder->codeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
1049 final, component, dst, component, dst, component, src, src,
1050 component, dst, dst, src, component, dst, component, src, src,
1052 // else if (4D < Da)
1053 fsBuilder->codeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1054 dst, component, dst);
1055 fsBuilder->codeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1056 dst, component, dst, component);
1057 fsBuilder->codeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1058 fsBuilder->codeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1059 fsBuilder->codeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1060 // (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
1061 fsBuilder->codeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
1062 final, component, src, component, src, component, dst, component,
1063 src, src, component, dst, src, src, component, src, src,
1065 fsBuilder->codeAppendf("\t\t\t} else {\n");
1066 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1067 fsBuilder->codeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
1068 final, component, dst, dst, component, src, src, component, dst,
1069 src, component, dst, component, src, src, component, src,
1071 fsBuilder->codeAppendf("\t\t\t}\n");
1074 // Adds a function that takes two colors and an alpha as input. It produces a color with the
1075 // hue and saturation of the first color, the luminosity of the second color, and the input
1076 // alpha. It has this signature:
1077 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1078 static void AddLumFunction(GrGLFPFragmentBuilder* fsBuilder, SkString* setLumFunction) {
1079 // Emit a helper that gets the luminance of a color.
1080 SkString getFunction;
1081 GrGLShaderVar getLumArgs[] = {
1082 GrGLShaderVar("color", kVec3f_GrSLType),
1084 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1085 fsBuilder->emitFunction(kFloat_GrSLType,
1087 SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1091 // Emit the set luminance function.
1092 GrGLShaderVar setLumArgs[] = {
1093 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1094 GrGLShaderVar("alpha", kFloat_GrSLType),
1095 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1097 SkString setLumBody;
1098 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1099 setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1100 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1101 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1102 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1103 "\tif (minComp < 0.0) {\n"
1104 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1106 "\tif (maxComp > alpha) {\n"
1107 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1109 "\treturn outColor;\n");
1110 fsBuilder->emitFunction(kVec3f_GrSLType,
1112 SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1117 // Adds a function that creates a color with the hue and luminosity of one input color and
1118 // the saturation of another color. It will have this signature:
1119 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1120 static void AddSatFunction(GrGLFPFragmentBuilder* fsBuilder, SkString* setSatFunction) {
1121 // Emit a helper that gets the saturation of a color
1122 SkString getFunction;
1123 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1124 SkString getSatBody;
1125 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1126 "min(min(color.r, color.g), color.b);\n");
1127 fsBuilder->emitFunction(kFloat_GrSLType,
1129 SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1133 // Emit a helper that sets the saturation given sorted input channels. This used
1134 // to use inout params for min, mid, and max components but that seems to cause
1135 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1136 // adjusted min, mid, and max inputs, respectively.
1137 SkString helperFunction;
1138 GrGLShaderVar helperArgs[] = {
1139 GrGLShaderVar("minComp", kFloat_GrSLType),
1140 GrGLShaderVar("midComp", kFloat_GrSLType),
1141 GrGLShaderVar("maxComp", kFloat_GrSLType),
1142 GrGLShaderVar("sat", kFloat_GrSLType),
1144 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1145 "\t\tvec3 result;\n"
1146 "\t\tresult.r = 0.0;\n"
1147 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1148 "\t\tresult.b = sat;\n"
1149 "\t\treturn result;\n"
1151 "\t\treturn vec3(0, 0, 0);\n"
1153 fsBuilder->emitFunction(kVec3f_GrSLType,
1154 "set_saturation_helper",
1155 SK_ARRAY_COUNT(helperArgs), helperArgs,
1159 GrGLShaderVar setSatArgs[] = {
1160 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1161 GrGLShaderVar("satColor", kVec3f_GrSLType),
1163 const char* helpFunc = helperFunction.c_str();
1164 SkString setSatBody;
1165 setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1166 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1167 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1168 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1169 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1170 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1172 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1174 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1175 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1176 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1177 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1179 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1181 "\treturn hueLumColor;\n",
1182 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1183 helpFunc, helpFunc);
1184 fsBuilder->emitFunction(kVec3f_GrSLType,
1186 SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1192 typedef GrGLFragmentProcessor INHERITED;
1195 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1198 XferEffect(SkXfermode::Mode mode, GrTexture* background)
1201 fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1202 this->addCoordTransform(&fBackgroundTransform);
1203 fBackgroundAccess.reset(background);
1204 this->addTextureAccess(&fBackgroundAccess);
1206 this->setWillReadDstColor();
1209 virtual bool onIsEqual(const GrFragmentProcessor& other) const SK_OVERRIDE {
1210 const XferEffect& s = other.cast<XferEffect>();
1211 return fMode == s.fMode;
1214 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE {
1215 inout->setToUnknown(InvariantOutput::kWill_ReadInput);
1218 SkXfermode::Mode fMode;
1219 GrCoordTransform fBackgroundTransform;
1220 GrTextureAccess fBackgroundAccess;
1222 typedef GrFragmentProcessor INHERITED;
1225 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(XferEffect);
1226 GrFragmentProcessor* XferEffect::TestCreate(SkRandom* rand,
1228 const GrDrawTargetCaps&,
1230 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1232 return SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL));
1237 ///////////////////////////////////////////////////////////////////////////////
1238 ///////////////////////////////////////////////////////////////////////////////
1240 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1241 SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1242 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1243 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1244 // out of range, just set to something harmless
1245 mode32 = SkXfermode::kSrcOut_Mode;
1247 fMode = (SkXfermode::Mode)mode32;
1249 const ProcCoeff& rec = gProcCoeffs[fMode];
1251 // these may be valid, or may be CANNOT_USE_COEFF
1252 fSrcCoeff = rec.fSC;
1253 fDstCoeff = rec.fDC;
1257 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
1258 uint32_t mode32 = buffer.read32();
1259 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
1262 return SkXfermode::Create((SkXfermode::Mode)mode32);
1265 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1266 buffer.write32(fMode);
1269 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1276 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1277 if (CANNOT_USE_COEFF == fSrcCoeff) {
1290 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1291 const SkPMColor* SK_RESTRICT src, int count,
1292 const SkAlpha* SK_RESTRICT aa) const {
1293 SkASSERT(dst && src && count >= 0);
1295 SkXfermodeProc proc = fProc;
1299 for (int i = count - 1; i >= 0; --i) {
1300 dst[i] = proc(src[i], dst[i]);
1303 for (int i = count - 1; i >= 0; --i) {
1306 SkPMColor dstC = dst[i];
1307 SkPMColor C = proc(src[i], dstC);
1309 C = SkFourByteInterp(C, dstC, a);
1318 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1319 const SkPMColor* SK_RESTRICT src, int count,
1320 const SkAlpha* SK_RESTRICT aa) const {
1321 SkASSERT(dst && src && count >= 0);
1323 SkXfermodeProc proc = fProc;
1327 for (int i = count - 1; i >= 0; --i) {
1328 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1329 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1332 for (int i = count - 1; i >= 0; --i) {
1335 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1336 SkPMColor C = proc(src[i], dstC);
1338 C = SkFourByteInterp(C, dstC, a);
1340 dst[i] = SkPixel32ToPixel16_ToU16(C);
1347 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1348 const SkPMColor* SK_RESTRICT src, int count,
1349 const SkAlpha* SK_RESTRICT aa) const {
1350 SkASSERT(dst && src && count >= 0);
1352 SkXfermodeProc proc = fProc;
1356 for (int i = count - 1; i >= 0; --i) {
1357 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1358 dst[i] = SkToU8(SkGetPackedA32(res));
1361 for (int i = count - 1; i >= 0; --i) {
1364 SkAlpha dstA = dst[i];
1365 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1366 unsigned A = SkGetPackedA32(res);
1368 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1378 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
1379 GrTexture* background) const {
1380 if (XferEffect::IsSupportedMode(fMode)) {
1382 *fp = XferEffect::Create(fMode, background);
1391 const char* SkXfermode::ModeName(Mode mode) {
1392 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1393 const char* gModeStrings[] = {
1394 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1395 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1396 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1397 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1398 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1400 return gModeStrings[mode];
1401 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1404 #ifndef SK_IGNORE_TO_STRING
1405 void SkProcCoeffXfermode::toString(SkString* str) const {
1406 str->append("SkProcCoeffXfermode: ");
1408 str->append("mode: ");
1409 str->append(ModeName(fMode));
1411 static const char* gCoeffStrings[kCoeffCount] = {
1412 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1415 str->append(" src: ");
1416 if (CANNOT_USE_COEFF == fSrcCoeff) {
1417 str->append("can't use");
1419 str->append(gCoeffStrings[fSrcCoeff]);
1422 str->append(" dst: ");
1423 if (CANNOT_USE_COEFF == fDstCoeff) {
1424 str->append("can't use");
1426 str->append(gCoeffStrings[fDstCoeff]);
1431 ///////////////////////////////////////////////////////////////////////////////
1433 class SkClearXfermode : public SkProcCoeffXfermode {
1435 static SkClearXfermode* Create(const ProcCoeff& rec) {
1436 return SkNEW_ARGS(SkClearXfermode, (rec));
1439 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1440 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1442 SK_TO_STRING_OVERRIDE()
1445 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1446 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1447 SkClearXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1450 typedef SkProcCoeffXfermode INHERITED;
1453 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1454 const SkPMColor* SK_RESTRICT, int count,
1455 const SkAlpha* SK_RESTRICT aa) const {
1456 SkASSERT(dst && count >= 0);
1459 memset(dst, 0, count << 2);
1461 for (int i = count - 1; i >= 0; --i) {
1465 } else if (a != 0) {
1466 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1471 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1472 const SkPMColor* SK_RESTRICT, int count,
1473 const SkAlpha* SK_RESTRICT aa) const {
1474 SkASSERT(dst && count >= 0);
1477 memset(dst, 0, count);
1479 for (int i = count - 1; i >= 0; --i) {
1483 } else if (0 != a) {
1484 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1490 #ifndef SK_IGNORE_TO_STRING
1491 void SkClearXfermode::toString(SkString* str) const {
1492 this->INHERITED::toString(str);
1496 ///////////////////////////////////////////////////////////////////////////////
1498 class SkSrcXfermode : public SkProcCoeffXfermode {
1500 static SkSrcXfermode* Create(const ProcCoeff& rec) {
1501 return SkNEW_ARGS(SkSrcXfermode, (rec));
1504 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1505 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1507 SK_TO_STRING_OVERRIDE()
1510 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1511 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1512 SkSrcXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
1514 typedef SkProcCoeffXfermode INHERITED;
1517 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1518 const SkPMColor* SK_RESTRICT src, int count,
1519 const SkAlpha* SK_RESTRICT aa) const {
1520 SkASSERT(dst && src && count >= 0);
1523 memcpy(dst, src, count << 2);
1525 for (int i = count - 1; i >= 0; --i) {
1529 } else if (a != 0) {
1530 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1536 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1537 const SkPMColor* SK_RESTRICT src, int count,
1538 const SkAlpha* SK_RESTRICT aa) const {
1539 SkASSERT(dst && src && count >= 0);
1542 for (int i = count - 1; i >= 0; --i) {
1543 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1546 for (int i = count - 1; i >= 0; --i) {
1549 unsigned srcA = SkGetPackedA32(src[i]);
1551 dst[i] = SkToU8(srcA);
1553 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1559 #ifndef SK_IGNORE_TO_STRING
1560 void SkSrcXfermode::toString(SkString* str) const {
1561 this->INHERITED::toString(str);
1565 ///////////////////////////////////////////////////////////////////////////////
1567 class SkDstInXfermode : public SkProcCoeffXfermode {
1569 static SkDstInXfermode* Create(const ProcCoeff& rec) {
1570 return SkNEW_ARGS(SkDstInXfermode, (rec));
1573 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1575 SK_TO_STRING_OVERRIDE()
1578 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1579 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1580 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1583 typedef SkProcCoeffXfermode INHERITED;
1586 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1587 const SkPMColor* SK_RESTRICT src, int count,
1588 const SkAlpha* SK_RESTRICT aa) const {
1589 SkASSERT(dst && src);
1595 return this->INHERITED::xfer32(dst, src, count, aa);
1599 unsigned a = SkGetPackedA32(*src);
1600 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1603 } while (--count != 0);
1606 #ifndef SK_IGNORE_TO_STRING
1607 void SkDstInXfermode::toString(SkString* str) const {
1608 this->INHERITED::toString(str);
1612 ///////////////////////////////////////////////////////////////////////////////
1614 class SkDstOutXfermode : public SkProcCoeffXfermode {
1616 static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1617 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1620 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1622 SK_TO_STRING_OVERRIDE()
1625 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1626 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1627 SkDstOutXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1630 typedef SkProcCoeffXfermode INHERITED;
1633 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1634 const SkPMColor* SK_RESTRICT src, int count,
1635 const SkAlpha* SK_RESTRICT aa) const {
1636 SkASSERT(dst && src);
1642 return this->INHERITED::xfer32(dst, src, count, aa);
1646 unsigned a = SkGetPackedA32(*src);
1647 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1650 } while (--count != 0);
1653 #ifndef SK_IGNORE_TO_STRING
1654 void SkDstOutXfermode::toString(SkString* str) const {
1655 this->INHERITED::toString(str);
1659 ///////////////////////////////////////////////////////////////////////////////
1661 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1662 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1664 // Technically, can't be static and passed as a template parameter. So we use anonymous namespace.
1666 SkXfermode* create_mode(int iMode) {
1667 SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1669 ProcCoeff rec = gProcCoeffs[mode];
1670 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1675 SkXfermode* xfer = NULL;
1676 // check if we have a platform optim for that
1677 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1681 // All modes can in theory be represented by the ProcCoeff rec, since
1682 // it contains function ptrs. However, a few modes are both simple and
1683 // commonly used, so we call those out for their own subclasses here.
1685 case SkXfermode::kClear_Mode:
1686 xfer = SkClearXfermode::Create(rec);
1688 case SkXfermode::kSrc_Mode:
1689 xfer = SkSrcXfermode::Create(rec);
1691 case SkXfermode::kSrcOver_Mode:
1692 SkASSERT(false); // should not land here
1694 case SkXfermode::kDstIn_Mode:
1695 xfer = SkDstInXfermode::Create(rec);
1697 case SkXfermode::kDstOut_Mode:
1698 xfer = SkDstOutXfermode::Create(rec);
1701 // no special-case, just rely in the rec and its function-ptrs
1702 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1710 SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1712 SkXfermode* SkXfermode::Create(Mode mode) {
1713 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1715 if ((unsigned)mode >= kModeCount) {
1720 // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1721 // so we can just return NULL from the factory.
1722 if (kSrcOver_Mode == mode) {
1726 return SkSafeRef(cached[mode]);
1729 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1730 SkXfermodeProc proc = NULL;
1731 if ((unsigned)mode < kModeCount) {
1732 proc = gProcCoeffs[mode].fProc;
1737 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1738 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1740 if ((unsigned)mode >= (unsigned)kModeCount) {
1741 // illegal mode parameter
1745 const ProcCoeff& rec = gProcCoeffs[mode];
1747 if (CANNOT_USE_COEFF == rec.fSC) {
1751 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1761 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1764 *mode = kSrcOver_Mode;
1768 return xfer->asMode(mode);
1771 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1773 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1775 return xfer->asCoeff(src, dst);
1778 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1779 // if xfer==null then the mode is srcover
1780 Mode m = kSrcOver_Mode;
1781 if (xfer && !xfer->asMode(&m)) {
1787 ///////////////////////////////////////////////////////////////////////////////
1788 //////////// 16bit xfermode procs
1791 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1792 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1795 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1796 SkASSERT(require_255(src));
1797 return SkPixel32ToPixel16(src);
1800 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1804 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1805 SkASSERT(require_0(src));
1809 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1810 SkASSERT(require_255(src));
1811 return SkPixel32ToPixel16(src);
1814 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1815 SkASSERT(require_0(src));
1819 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1820 SkASSERT(require_255(src));
1824 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1825 SkASSERT(require_255(src));
1826 return SkPixel32ToPixel16(src);
1829 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1830 SkASSERT(require_255(src));
1834 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1835 SkASSERT(require_0(src));
1839 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1840 unsigned isa = 255 - SkGetPackedA32(src);
1843 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1844 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1845 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1848 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1849 SkASSERT(require_0(src));
1853 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1854 SkASSERT(require_255(src));
1855 return SkPixel32ToPixel16(src);
1858 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1859 SkASSERT(require_255(src));
1864 darken and lighten boil down to this.
1866 darken = (1 - Sa) * Dc + min(Sc, Dc)
1867 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1869 if (Sa == 0) these become
1870 darken = Dc + min(0, Dc) = 0
1871 lighten = Dc + max(0, Dc) = Dc
1873 if (Sa == 1) these become
1874 darken = min(Sc, Dc)
1875 lighten = max(Sc, Dc)
1878 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1879 SkASSERT(require_0(src));
1883 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1884 SkASSERT(require_255(src));
1885 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1886 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1887 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1888 return SkPackRGB16(r, g, b);
1891 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1892 SkASSERT(require_0(src));
1896 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1897 SkASSERT(require_255(src));
1898 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1899 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1900 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1901 return SkPackRGB16(r, g, b);
1905 SkXfermodeProc16 fProc16_0;
1906 SkXfermodeProc16 fProc16_255;
1907 SkXfermodeProc16 fProc16_General;
1910 static const Proc16Rec gModeProcs16[] = {
1911 { NULL, NULL, NULL }, // CLEAR
1912 { NULL, src_modeproc16_255, NULL },
1913 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1914 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1915 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1916 { NULL, srcin_modeproc16_255, NULL },
1917 { NULL, dstin_modeproc16_255, NULL },
1918 { NULL, NULL, NULL },// SRC_OUT
1919 { dstout_modeproc16_0, NULL, NULL },
1920 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1921 { NULL, dstatop_modeproc16_255, NULL },
1922 { NULL, NULL, NULL }, // XOR
1924 { NULL, NULL, NULL }, // plus
1925 { NULL, NULL, NULL }, // modulate
1926 { NULL, NULL, NULL }, // screen
1927 { NULL, NULL, NULL }, // overlay
1928 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1929 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1930 { NULL, NULL, NULL }, // colordodge
1931 { NULL, NULL, NULL }, // colorburn
1932 { NULL, NULL, NULL }, // hardlight
1933 { NULL, NULL, NULL }, // softlight
1934 { NULL, NULL, NULL }, // difference
1935 { NULL, NULL, NULL }, // exclusion
1936 { NULL, NULL, NULL }, // multiply
1937 { NULL, NULL, NULL }, // hue
1938 { NULL, NULL, NULL }, // saturation
1939 { NULL, NULL, NULL }, // color
1940 { NULL, NULL, NULL }, // luminosity
1943 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1944 SkXfermodeProc16 proc16 = NULL;
1945 if ((unsigned)mode < kModeCount) {
1946 const Proc16Rec& rec = gModeProcs16[mode];
1947 unsigned a = SkColorGetA(srcColor);
1950 proc16 = rec.fProc16_0;
1951 } else if (255 == a) {
1952 proc16 = rec.fProc16_255;
1954 proc16 = rec.fProc16_General;
1960 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1961 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1962 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END