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_proccoeff.h"
12 #include "SkColorPriv.h"
13 #include "SkFlattenableBuffers.h"
14 #include "SkMathPriv.h"
16 #include "SkUtilsArm.h"
18 #if !SK_ARM_NEON_IS_NONE
19 #include "SkXfermode_opts_arm_neon.h"
22 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
25 // idea for higher precision blends in xfer procs (and slightly faster)
26 // see DstATop as a probable caller
27 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
32 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
33 unsigned result = (prod + (prod >> 8)) >> 8;
34 SkASSERT(result <= 255);
39 static inline unsigned saturated_add(unsigned a, unsigned b) {
49 static inline int clamp_signed_byte(int n) {
58 static inline int clamp_div255round(int prod) {
61 } else if (prod >= 255*255) {
64 return SkDiv255Round(prod);
68 ///////////////////////////////////////////////////////////////////////////////
70 // kClear_Mode, //!< [0, 0]
71 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75 // kSrc_Mode, //!< [Sa, Sc]
76 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80 // kDst_Mode, //!< [Da, Dc]
81 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
85 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
86 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
88 // this is the old, more-correct way, but it doesn't guarantee that dst==255
89 // will always stay opaque
90 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
92 // this is slightly faster, but more importantly guarantees that dst==255
93 // will always stay opaque
94 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
98 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
99 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
100 // this is the reverse of srcover, just flipping src and dst
101 // see srcover's comment about the 256 for opaqueness guarantees
102 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
105 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
106 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
107 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
110 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
111 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
112 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
115 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
116 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
117 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
120 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
121 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
122 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
125 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
126 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
127 unsigned sa = SkGetPackedA32(src);
128 unsigned da = SkGetPackedA32(dst);
129 unsigned isa = 255 - sa;
131 return SkPackARGB32(da,
132 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
133 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
134 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
135 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
136 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
137 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
140 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
141 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
142 unsigned sa = SkGetPackedA32(src);
143 unsigned da = SkGetPackedA32(dst);
144 unsigned ida = 255 - da;
146 return SkPackARGB32(sa,
147 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
148 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
149 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
150 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
151 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
152 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
155 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
156 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
157 unsigned sa = SkGetPackedA32(src);
158 unsigned da = SkGetPackedA32(dst);
159 unsigned isa = 255 - sa;
160 unsigned ida = 255 - da;
162 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
163 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
164 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
165 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
166 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
167 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
168 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
171 ///////////////////////////////////////////////////////////////////////////////
174 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
175 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
176 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
177 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
178 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
179 return SkPackARGB32(a, r, g, b);
183 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
184 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
185 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
186 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
187 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
188 return SkPackARGB32(a, r, g, b);
191 static inline int srcover_byte(int a, int b) {
192 return a + b - SkAlphaMulAlpha(a, b);
196 // B(Cb, Cs) = Cb x Cs
197 // multiply uses its own version of blendfunc_byte because sa and da are not needed
198 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
199 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
202 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
203 int sa = SkGetPackedA32(src);
204 int da = SkGetPackedA32(dst);
205 int a = srcover_byte(sa, da);
206 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
207 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
208 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
209 return SkPackARGB32(a, r, g, b);
213 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
214 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
215 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
216 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
217 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
218 return SkPackARGB32(a, r, g, b);
222 static inline int overlay_byte(int sc, int dc, int sa, int da) {
223 int tmp = sc * (255 - da) + dc * (255 - sa);
228 rc = sa * da - 2 * (da - dc) * (sa - sc);
230 return clamp_div255round(rc + tmp);
232 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
233 int sa = SkGetPackedA32(src);
234 int da = SkGetPackedA32(dst);
235 int a = srcover_byte(sa, da);
236 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
237 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
238 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
239 return SkPackARGB32(a, r, g, b);
243 static inline int darken_byte(int sc, int dc, int sa, int da) {
248 return sc + dc - SkDiv255Round(ds);
251 return dc + sc - SkDiv255Round(sd);
254 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
255 int sa = SkGetPackedA32(src);
256 int da = SkGetPackedA32(dst);
257 int a = srcover_byte(sa, da);
258 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
259 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
260 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
261 return SkPackARGB32(a, r, g, b);
265 static inline int lighten_byte(int sc, int dc, int sa, int da) {
270 return sc + dc - SkDiv255Round(ds);
273 return dc + sc - SkDiv255Round(sd);
276 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
277 int sa = SkGetPackedA32(src);
278 int da = SkGetPackedA32(dst);
279 int a = srcover_byte(sa, da);
280 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
281 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
282 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
283 return SkPackARGB32(a, r, g, b);
287 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
291 return SkAlphaMulAlpha(sc, 255 - da);
292 } else if (0 == diff) {
293 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
295 diff = dc * sa / diff;
296 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
298 return clamp_div255round(rc);
300 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
301 int sa = SkGetPackedA32(src);
302 int da = SkGetPackedA32(dst);
303 int a = srcover_byte(sa, da);
304 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
305 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
306 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
307 return SkPackARGB32(a, r, g, b);
311 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
314 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
315 } else if (0 == sc) {
316 return SkAlphaMulAlpha(dc, 255 - sa);
318 int tmp = (da - dc) * sa / sc;
319 rc = sa * (da - ((da < tmp) ? da : tmp))
320 + sc * (255 - da) + dc * (255 - sa);
322 return clamp_div255round(rc);
324 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
325 int sa = SkGetPackedA32(src);
326 int da = SkGetPackedA32(dst);
327 int a = srcover_byte(sa, da);
328 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
329 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
330 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
331 return SkPackARGB32(a, r, g, b);
335 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
340 rc = sa * da - 2 * (da - dc) * (sa - sc);
342 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
344 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
345 int sa = SkGetPackedA32(src);
346 int da = SkGetPackedA32(dst);
347 int a = srcover_byte(sa, da);
348 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
349 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
350 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
351 return SkPackARGB32(a, r, g, b);
354 // returns 255 * sqrt(n/255)
355 static U8CPU sqrt_unit_byte(U8CPU n) {
356 return SkSqrtBits(n, 15+4);
360 static inline int softlight_byte(int sc, int dc, int sa, int da) {
361 int m = da ? dc * 256 / da : 0;
364 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
365 } else if (4 * dc <= da) {
366 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
367 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
369 int tmp = sqrt_unit_byte(m) - m;
370 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
372 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
374 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
375 int sa = SkGetPackedA32(src);
376 int da = SkGetPackedA32(dst);
377 int a = srcover_byte(sa, da);
378 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
379 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
380 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
381 return SkPackARGB32(a, r, g, b);
385 static inline int difference_byte(int sc, int dc, int sa, int da) {
386 int tmp = SkMin32(sc * da, dc * sa);
387 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
389 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
390 int sa = SkGetPackedA32(src);
391 int da = SkGetPackedA32(dst);
392 int a = srcover_byte(sa, da);
393 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
394 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
395 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
396 return SkPackARGB32(a, r, g, b);
400 static inline int exclusion_byte(int sc, int dc, int, int) {
401 // this equations is wacky, wait for SVG to confirm it
402 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
404 // The above equation can be simplified as follows
405 int r = 255*(sc + dc) - 2 * sc * dc;
406 return clamp_div255round(r);
408 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
409 int sa = SkGetPackedA32(src);
410 int da = SkGetPackedA32(dst);
411 int a = srcover_byte(sa, da);
412 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
413 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
414 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
415 return SkPackARGB32(a, r, g, b);
418 // The CSS compositing spec introduces the following formulas:
419 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
420 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
421 // while PDF and CG uses the one from Rec. Rec. 601
422 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
423 static inline int Lum(int r, int g, int b)
425 return SkDiv255Round(r * 77 + g * 150 + b * 28);
428 static inline int min2(int a, int b) { return a < b ? a : b; }
429 static inline int max2(int a, int b) { return a > b ? a : b; }
430 #define minimum(a, b, c) min2(min2(a, b), c)
431 #define maximum(a, b, c) max2(max2(a, b), c)
433 static inline int Sat(int r, int g, int b) {
434 return maximum(r, g, b) - minimum(r, g, b);
437 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
439 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
449 static inline void SetSat(int* r, int* g, int* b, int s) {
452 setSaturationComponents(r, g, b, s);
453 } else if(*r <= *b) {
454 setSaturationComponents(r, b, g, s);
456 setSaturationComponents(b, r, g, s);
458 } else if(*r <= *b) {
459 setSaturationComponents(g, r, b, s);
460 } else if(*g <= *b) {
461 setSaturationComponents(g, b, r, s);
463 setSaturationComponents(b, g, r, s);
467 static inline void clipColor(int* r, int* g, int* b, int a) {
468 int L = Lum(*r, *g, *b);
469 int n = minimum(*r, *g, *b);
470 int x = maximum(*r, *g, *b);
472 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
473 *r = L + SkMulDiv(*r - L, L, denom);
474 *g = L + SkMulDiv(*g - L, L, denom);
475 *b = L + SkMulDiv(*b - L, L, denom);
478 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
480 *r = L + SkMulDiv(*r - L, numer, denom);
481 *g = L + SkMulDiv(*g - L, numer, denom);
482 *b = L + SkMulDiv(*b - L, numer, denom);
486 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
487 int d = l - Lum(*r, *g, *b);
492 clipColor(r, g, b, a);
495 // non-separable blend modes are done in non-premultiplied alpha
496 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
497 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
500 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
501 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
502 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
503 int sr = SkGetPackedR32(src);
504 int sg = SkGetPackedG32(src);
505 int sb = SkGetPackedB32(src);
506 int sa = SkGetPackedA32(src);
508 int dr = SkGetPackedR32(dst);
509 int dg = SkGetPackedG32(dst);
510 int db = SkGetPackedB32(dst);
511 int da = SkGetPackedA32(dst);
518 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
519 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
526 int a = srcover_byte(sa, da);
527 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
528 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
529 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
530 return SkPackARGB32(a, r, g, b);
534 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
535 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
536 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
537 int sr = SkGetPackedR32(src);
538 int sg = SkGetPackedG32(src);
539 int sb = SkGetPackedB32(src);
540 int sa = SkGetPackedA32(src);
542 int dr = SkGetPackedR32(dst);
543 int dg = SkGetPackedG32(dst);
544 int db = SkGetPackedB32(dst);
545 int da = SkGetPackedA32(dst);
552 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
553 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
560 int a = srcover_byte(sa, da);
561 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
562 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
563 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
564 return SkPackARGB32(a, r, g, b);
568 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
569 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
570 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
571 int sr = SkGetPackedR32(src);
572 int sg = SkGetPackedG32(src);
573 int sb = SkGetPackedB32(src);
574 int sa = SkGetPackedA32(src);
576 int dr = SkGetPackedR32(dst);
577 int dg = SkGetPackedG32(dst);
578 int db = SkGetPackedB32(dst);
579 int da = SkGetPackedA32(dst);
586 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
593 int a = srcover_byte(sa, da);
594 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
595 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
596 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
597 return SkPackARGB32(a, r, g, b);
601 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
602 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
603 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
604 int sr = SkGetPackedR32(src);
605 int sg = SkGetPackedG32(src);
606 int sb = SkGetPackedB32(src);
607 int sa = SkGetPackedA32(src);
609 int dr = SkGetPackedR32(dst);
610 int dg = SkGetPackedG32(dst);
611 int db = SkGetPackedB32(dst);
612 int da = SkGetPackedA32(dst);
619 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
626 int a = srcover_byte(sa, da);
627 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
628 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
629 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
630 return SkPackARGB32(a, r, g, b);
633 const ProcCoeff gProcCoeffs[] = {
634 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
635 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
636 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
637 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
638 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
639 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
640 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
641 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
642 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
643 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
644 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
645 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
647 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
648 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
649 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
650 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
651 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
652 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
653 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
654 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
655 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
656 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
657 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
658 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
659 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
660 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
661 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
662 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
663 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
666 ///////////////////////////////////////////////////////////////////////////////
668 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
672 bool SkXfermode::asMode(Mode* mode) const {
676 bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
680 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
681 GrEffectRef** effect,
684 GrTexture* background) {
685 if (NULL == xfermode) {
686 return ModeAsCoeff(kSrcOver_Mode, src, dst);
687 } else if (xfermode->asCoeff(src, dst)) {
690 return xfermode->asNewEffect(effect, 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 ///////////////////////////////////////////////////////////////////////////////
776 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
777 const SkPMColor* SK_RESTRICT src, int count,
778 const SkAlpha* SK_RESTRICT aa) const {
779 SkASSERT(dst && src && count >= 0);
781 SkXfermodeProc proc = fProc;
785 for (int i = count - 1; i >= 0; --i) {
786 dst[i] = proc(src[i], dst[i]);
789 for (int i = count - 1; i >= 0; --i) {
792 SkPMColor dstC = dst[i];
793 SkPMColor C = proc(src[i], dstC);
795 C = SkFourByteInterp(C, dstC, a);
804 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
805 const SkPMColor* SK_RESTRICT src, int count,
806 const SkAlpha* SK_RESTRICT aa) const {
807 SkASSERT(dst && src && count >= 0);
809 SkXfermodeProc proc = fProc;
813 for (int i = count - 1; i >= 0; --i) {
814 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
815 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
818 for (int i = count - 1; i >= 0; --i) {
821 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
822 SkPMColor C = proc(src[i], dstC);
824 C = SkFourByteInterp(C, dstC, a);
826 dst[i] = SkPixel32ToPixel16_ToU16(C);
833 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
834 const SkPMColor* SK_RESTRICT src, int count,
835 const SkAlpha* SK_RESTRICT aa) const {
836 SkASSERT(dst && src && count >= 0);
838 SkXfermodeProc proc = fProc;
842 for (int i = count - 1; i >= 0; --i) {
843 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
844 dst[i] = SkToU8(SkGetPackedA32(res));
847 for (int i = count - 1; i >= 0; --i) {
850 SkAlpha dstA = dst[i];
851 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
852 unsigned A = SkGetPackedA32(res);
854 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
863 SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
864 : SkXfermode(buffer) {
866 if (!buffer.isCrossProcess()) {
867 fProc = (SkXfermodeProc)buffer.readFunctionPtr();
871 void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
872 this->INHERITED::flatten(buffer);
873 if (!buffer.isCrossProcess()) {
874 buffer.writeFunctionPtr((void*)fProc);
879 void SkProcXfermode::toString(SkString* str) const {
880 str->appendf("SkProcXfermode: %p", fProc);
884 //////////////////////////////////////////////////////////////////////////////
888 #include "GrEffect.h"
889 #include "GrCoordTransform.h"
890 #include "GrEffectUnitTest.h"
891 #include "GrTBackendEffectFactory.h"
892 #include "gl/GrGLEffect.h"
895 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
897 class XferEffect : public GrEffect {
899 static bool IsSupportedMode(SkXfermode::Mode mode) {
900 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
903 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
904 if (!IsSupportedMode(mode)) {
907 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
908 return CreateEffectRef(effect);
912 virtual void getConstantColorComponents(GrColor* color,
913 uint32_t* validFlags) const SK_OVERRIDE {
917 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
918 return GrTBackendEffectFactory<XferEffect>::getInstance();
921 static const char* Name() { return "XferEffect"; }
923 SkXfermode::Mode mode() const { return fMode; }
924 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; }
926 class GLEffect : public GrGLEffect {
928 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
929 : GrGLEffect(factory) {
931 virtual void emitCode(GrGLShaderBuilder* builder,
932 const GrDrawEffect& drawEffect,
934 const char* outputColor,
935 const char* inputColor,
936 const TransformedCoordsArray& coords,
937 const TextureSamplerArray& samplers) SK_OVERRIDE {
938 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
939 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
940 const char* dstColor;
942 dstColor = "bgColor";
943 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
944 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
945 builder->fsCodeAppendf(";\n");
947 dstColor = builder->dstColor();
949 SkASSERT(NULL != dstColor);
951 // We don't try to optimize for this case at all
952 if (NULL == inputColor) {
953 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
956 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
958 // These all perform src-over on the alpha channel.
959 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
960 outputColor, inputColor, inputColor, dstColor);
963 case SkXfermode::kOverlay_Mode:
964 // Overlay is Hard-Light with the src and dst reversed
965 HardLight(builder, outputColor, dstColor, inputColor);
967 case SkXfermode::kDarken_Mode:
968 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
969 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
971 inputColor, dstColor, inputColor,
972 dstColor, inputColor, dstColor);
974 case SkXfermode::kLighten_Mode:
975 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
976 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
978 inputColor, dstColor, inputColor,
979 dstColor, inputColor, dstColor);
981 case SkXfermode::kColorDodge_Mode:
982 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
983 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
984 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
986 case SkXfermode::kColorBurn_Mode:
987 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
988 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
989 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
991 case SkXfermode::kHardLight_Mode:
992 HardLight(builder, outputColor, inputColor, dstColor);
994 case SkXfermode::kSoftLight_Mode:
995 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
996 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
997 builder->fsCodeAppendf("\t\t} else {\n");
998 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
999 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1000 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1001 builder->fsCodeAppendf("\t\t}\n");
1003 case SkXfermode::kDifference_Mode:
1004 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1005 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1006 outputColor, inputColor, dstColor, inputColor, dstColor,
1007 dstColor, inputColor);
1009 case SkXfermode::kExclusion_Mode:
1010 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1011 "2.0 * %s.rgb * %s.rgb;\n",
1012 outputColor, dstColor, inputColor, dstColor, inputColor);
1014 case SkXfermode::kMultiply_Mode:
1015 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1016 "(1.0 - %s.a) * %s.rgb + "
1017 "%s.rgb * %s.rgb;\n",
1018 outputColor, inputColor, dstColor, dstColor, inputColor,
1019 inputColor, dstColor);
1021 case SkXfermode::kHue_Mode: {
1022 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1023 SkString setSat, setLum;
1024 AddSatFunction(builder, &setSat);
1025 AddLumFunction(builder, &setLum);
1026 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1027 dstColor, inputColor);
1028 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1029 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1031 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1032 outputColor, inputColor, dstColor, dstColor, inputColor);
1035 case SkXfermode::kSaturation_Mode: {
1036 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1037 SkString setSat, setLum;
1038 AddSatFunction(builder, &setSat);
1039 AddLumFunction(builder, &setLum);
1040 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1041 dstColor, inputColor);
1042 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1043 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1045 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1046 outputColor, inputColor, dstColor, dstColor, inputColor);
1049 case SkXfermode::kColor_Mode: {
1050 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1052 AddLumFunction(builder, &setLum);
1053 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1054 inputColor, dstColor);
1055 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
1056 outputColor, setLum.c_str(), dstColor, inputColor);
1057 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1058 outputColor, inputColor, dstColor, dstColor, inputColor);
1061 case SkXfermode::kLuminosity_Mode: {
1062 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1064 AddLumFunction(builder, &setLum);
1065 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1066 inputColor, dstColor);
1067 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
1068 outputColor, setLum.c_str(), dstColor, inputColor);
1069 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1070 outputColor, inputColor, dstColor, dstColor, inputColor);
1074 GrCrash("Unknown XferEffect mode.");
1079 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1080 return drawEffect.castEffect<XferEffect>().mode();
1084 static void HardLight(GrGLShaderBuilder* builder,
1088 static const char kComponents[] = {'r', 'g', 'b'};
1089 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
1090 char component = kComponents[i];
1091 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1092 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
1093 builder->fsCodeAppend("\t\t} else {\n");
1094 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
1095 final, component, src, dst, dst, dst, component, src, src, component);
1096 builder->fsCodeAppend("\t\t}\n");
1098 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1099 final, src, dst, dst, src);
1102 // Does one component of color-dodge
1103 static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1107 const char component) {
1108 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1109 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1110 final, component, src, component, dst);
1111 builder->fsCodeAppend("\t\t} else {\n");
1112 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1113 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1114 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",
1115 final, component, src, dst, src, component, dst, dst, component,
1117 builder->fsCodeAppend("\t\t\t} else {\n");
1118 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1119 dst, dst, component, src);
1120 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1121 final, component, src, src, component, dst, dst, component, src);
1122 builder->fsCodeAppend("\t\t\t}\n");
1123 builder->fsCodeAppend("\t\t}\n");
1126 // Does one component of color-burn
1127 static void ColorBurnComponent(GrGLShaderBuilder* builder,
1131 const char component) {
1132 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1133 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1134 final, component, src, dst, src, component, dst, dst, component,
1136 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1137 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1138 final, component, dst, component, src);
1139 builder->fsCodeAppend("\t\t} else {\n");
1140 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1141 dst, dst, dst, component, src, src, component);
1142 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1143 final, component, src, src, component, dst, dst, component, src);
1144 builder->fsCodeAppend("\t\t}\n");
1147 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1148 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1152 const char component) {
1154 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1155 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1156 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",
1157 final, component, dst, component, dst, component, src, src,
1158 component, dst, dst, src, component, dst, component, src, src,
1160 // else if (4D < Da)
1161 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1162 dst, component, dst);
1163 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1164 dst, component, dst, component);
1165 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1166 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1167 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1168 // (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
1169 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",
1170 final, component, src, component, src, component, dst, component,
1171 src, src, component, dst, src, src, component, src, src,
1173 builder->fsCodeAppendf("\t\t\t} else {\n");
1174 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1175 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",
1176 final, component, dst, dst, component, src, src, component, dst,
1177 src, component, dst, component, src, src, component, src,
1179 builder->fsCodeAppendf("\t\t\t}\n");
1182 // Adds a function that takes two colors and an alpha as input. It produces a color with the
1183 // hue and saturation of the first color, the luminosity of the second color, and the input
1184 // alpha. It has this signature:
1185 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1186 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1187 // Emit a helper that gets the luminance of a color.
1188 SkString getFunction;
1189 GrGLShaderVar getLumArgs[] = {
1190 GrGLShaderVar("color", kVec3f_GrSLType),
1192 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1193 builder->fsEmitFunction(kFloat_GrSLType,
1195 SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1199 // Emit the set luminance function.
1200 GrGLShaderVar setLumArgs[] = {
1201 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1202 GrGLShaderVar("alpha", kFloat_GrSLType),
1203 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1205 SkString setLumBody;
1206 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1207 setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1208 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1209 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1210 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1211 "\tif (minComp < 0.0) {\n"
1212 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1214 "\tif (maxComp > alpha) {\n"
1215 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1217 "\treturn outColor;\n");
1218 builder->fsEmitFunction(kVec3f_GrSLType,
1220 SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1225 // Adds a function that creates a color with the hue and luminosity of one input color and
1226 // the saturation of another color. It will have this signature:
1227 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1228 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1229 // Emit a helper that gets the saturation of a color
1230 SkString getFunction;
1231 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1232 SkString getSatBody;
1233 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1234 "min(min(color.r, color.g), color.b);\n");
1235 builder->fsEmitFunction(kFloat_GrSLType,
1237 SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1241 // Emit a helper that sets the saturation given sorted input channels. This used
1242 // to use inout params for min, mid, and max components but that seems to cause
1243 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1244 // adjusted min, mid, and max inputs, respectively.
1245 SkString helperFunction;
1246 GrGLShaderVar helperArgs[] = {
1247 GrGLShaderVar("minComp", kFloat_GrSLType),
1248 GrGLShaderVar("midComp", kFloat_GrSLType),
1249 GrGLShaderVar("maxComp", kFloat_GrSLType),
1250 GrGLShaderVar("sat", kFloat_GrSLType),
1252 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1253 "\t\tvec3 result;\n"
1254 "\t\tresult.r = 0.0;\n"
1255 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1256 "\t\tresult.b = sat;\n"
1257 "\t\treturn result;\n"
1259 "\t\treturn vec3(0, 0, 0);\n"
1261 builder->fsEmitFunction(kVec3f_GrSLType,
1262 "set_saturation_helper",
1263 SK_ARRAY_COUNT(helperArgs), helperArgs,
1267 GrGLShaderVar setSatArgs[] = {
1268 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1269 GrGLShaderVar("satColor", kVec3f_GrSLType),
1271 const char* helpFunc = helperFunction.c_str();
1272 SkString setSatBody;
1273 setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1274 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1275 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1276 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1277 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1278 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1280 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1282 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1283 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1284 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1285 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1287 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1289 "\treturn hueLumColor;\n",
1290 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1291 helpFunc, helpFunc);
1292 builder->fsEmitFunction(kVec3f_GrSLType,
1294 SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1300 typedef GrGLEffect INHERITED;
1303 GR_DECLARE_EFFECT_TEST;
1306 XferEffect(SkXfermode::Mode mode, GrTexture* background)
1309 fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1310 this->addCoordTransform(&fBackgroundTransform);
1311 fBackgroundAccess.reset(background);
1312 this->addTextureAccess(&fBackgroundAccess);
1314 this->setWillReadDstColor();
1317 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1318 const XferEffect& s = CastEffect<XferEffect>(other);
1319 return fMode == s.fMode &&
1320 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1323 SkXfermode::Mode fMode;
1324 GrCoordTransform fBackgroundTransform;
1325 GrTextureAccess fBackgroundAccess;
1327 typedef GrEffect INHERITED;
1330 GR_DEFINE_EFFECT_TEST(XferEffect);
1331 GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
1333 const GrDrawTargetCaps&,
1335 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1337 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
1338 return CreateEffectRef(gEffect);
1343 ///////////////////////////////////////////////////////////////////////////////
1344 ///////////////////////////////////////////////////////////////////////////////
1346 SkProcCoeffXfermode::SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1347 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1348 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1349 // out of range, just set to something harmless
1350 mode32 = SkXfermode::kSrcOut_Mode;
1352 fMode = (SkXfermode::Mode)mode32;
1354 const ProcCoeff& rec = gProcCoeffs[fMode];
1355 // these may be valid, or may be CANNOT_USE_COEFF
1356 fSrcCoeff = rec.fSC;
1357 fDstCoeff = rec.fDC;
1358 // now update our function-ptr in the super class
1359 this->INHERITED::setProc(rec.fProc);
1362 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1369 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1370 if (CANNOT_USE_COEFF == fSrcCoeff) {
1384 bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
1385 GrTexture* background) const {
1386 if (XferEffect::IsSupportedMode(fMode)) {
1387 if (NULL != effect) {
1388 *effect = XferEffect::Create(fMode, background);
1389 SkASSERT(NULL != *effect);
1397 void SkProcCoeffXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
1398 this->INHERITED::flatten(buffer);
1399 buffer.write32(fMode);
1402 const char* SkXfermode::ModeName(Mode mode) {
1403 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1404 const char* gModeStrings[] = {
1405 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1406 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1407 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1408 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1409 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1411 return gModeStrings[mode];
1412 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1416 void SkProcCoeffXfermode::toString(SkString* str) const {
1417 str->append("SkProcCoeffXfermode: ");
1419 str->append("mode: ");
1420 str->append(ModeName(fMode));
1422 static const char* gCoeffStrings[kCoeffCount] = {
1423 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1426 str->append(" src: ");
1427 if (CANNOT_USE_COEFF == fSrcCoeff) {
1428 str->append("can't use");
1430 str->append(gCoeffStrings[fSrcCoeff]);
1433 str->append(" dst: ");
1434 if (CANNOT_USE_COEFF == fDstCoeff) {
1435 str->append("can't use");
1437 str->append(gCoeffStrings[fDstCoeff]);
1442 ///////////////////////////////////////////////////////////////////////////////
1444 class SkClearXfermode : public SkProcCoeffXfermode {
1446 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1448 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1449 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1451 SK_DEVELOPER_TO_STRING()
1452 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1455 SkClearXfermode(SkFlattenableReadBuffer& buffer)
1456 : SkProcCoeffXfermode(buffer) {}
1458 typedef SkProcCoeffXfermode INHERITED;
1461 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1462 const SkPMColor* SK_RESTRICT, int count,
1463 const SkAlpha* SK_RESTRICT aa) const {
1464 SkASSERT(dst && count >= 0);
1467 memset(dst, 0, count << 2);
1469 for (int i = count - 1; i >= 0; --i) {
1473 } else if (a != 0) {
1474 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1479 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1480 const SkPMColor* SK_RESTRICT, int count,
1481 const SkAlpha* SK_RESTRICT aa) const {
1482 SkASSERT(dst && count >= 0);
1485 memset(dst, 0, count);
1487 for (int i = count - 1; i >= 0; --i) {
1491 } else if (0 != a) {
1492 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1499 void SkClearXfermode::toString(SkString* str) const {
1500 this->INHERITED::toString(str);
1504 ///////////////////////////////////////////////////////////////////////////////
1506 class SkSrcXfermode : public SkProcCoeffXfermode {
1508 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1510 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1511 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1513 SK_DEVELOPER_TO_STRING()
1514 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1517 SkSrcXfermode(SkFlattenableReadBuffer& buffer)
1518 : SkProcCoeffXfermode(buffer) {}
1520 typedef SkProcCoeffXfermode INHERITED;
1523 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1524 const SkPMColor* SK_RESTRICT src, int count,
1525 const SkAlpha* SK_RESTRICT aa) const {
1526 SkASSERT(dst && src && count >= 0);
1529 memcpy(dst, src, count << 2);
1531 for (int i = count - 1; i >= 0; --i) {
1535 } else if (a != 0) {
1536 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1542 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1543 const SkPMColor* SK_RESTRICT src, int count,
1544 const SkAlpha* SK_RESTRICT aa) const {
1545 SkASSERT(dst && src && count >= 0);
1548 for (int i = count - 1; i >= 0; --i) {
1549 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1552 for (int i = count - 1; i >= 0; --i) {
1555 unsigned srcA = SkGetPackedA32(src[i]);
1557 dst[i] = SkToU8(srcA);
1559 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1566 void SkSrcXfermode::toString(SkString* str) const {
1567 this->INHERITED::toString(str);
1571 ///////////////////////////////////////////////////////////////////////////////
1573 class SkDstInXfermode : public SkProcCoeffXfermode {
1575 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1577 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1579 SK_DEVELOPER_TO_STRING()
1580 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1583 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1585 typedef SkProcCoeffXfermode INHERITED;
1588 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1589 const SkPMColor* SK_RESTRICT src, int count,
1590 const SkAlpha* SK_RESTRICT aa) const {
1591 SkASSERT(dst && src);
1597 return this->INHERITED::xfer32(dst, src, count, aa);
1601 unsigned a = SkGetPackedA32(*src);
1602 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1605 } while (--count != 0);
1609 void SkDstInXfermode::toString(SkString* str) const {
1610 this->INHERITED::toString(str);
1614 ///////////////////////////////////////////////////////////////////////////////
1616 class SkDstOutXfermode : public SkProcCoeffXfermode {
1618 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1620 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1622 SK_DEVELOPER_TO_STRING()
1623 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1626 SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
1627 : INHERITED(buffer) {}
1629 typedef SkProcCoeffXfermode INHERITED;
1632 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1633 const SkPMColor* SK_RESTRICT src, int count,
1634 const SkAlpha* SK_RESTRICT aa) const {
1635 SkASSERT(dst && src);
1641 return this->INHERITED::xfer32(dst, src, count, aa);
1645 unsigned a = SkGetPackedA32(*src);
1646 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1649 } while (--count != 0);
1653 void SkDstOutXfermode::toString(SkString* str) const {
1654 this->INHERITED::toString(str);
1658 ///////////////////////////////////////////////////////////////////////////////
1660 SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex);
1661 static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1];
1663 void SkXfermode::Term() {
1664 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1666 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) {
1667 SkSafeUnref(gCachedXfermodes[i]);
1668 gCachedXfermodes[i] = NULL;
1672 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
1673 SkXfermode::Mode mode);
1674 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1676 SkXfermode* SkXfermode::Create(Mode mode) {
1677 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1678 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount);
1680 if ((unsigned)mode >= kModeCount) {
1685 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover
1686 // so we can just return NULL from the factory.
1687 if (kSrcOver_Mode == mode) {
1691 // guard our access to gCachedXfermodes, since we may write into it
1692 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1694 SkXfermode* xfer = gCachedXfermodes[mode];
1696 ProcCoeff rec = gProcCoeffs[mode];
1698 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1704 // check if we have a platform optim for that
1705 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1709 // All modes can in theory be represented by the ProcCoeff rec, since
1710 // it contains function ptrs. However, a few modes are both simple and
1711 // commonly used, so we call those out for their own subclasses here.
1714 xfer = SkNEW_ARGS(SkClearXfermode, (rec));
1717 xfer = SkNEW_ARGS(SkSrcXfermode, (rec));
1720 SkASSERT(false); // should not land here
1723 xfer = SkNEW_ARGS(SkDstInXfermode, (rec));
1726 xfer = SkNEW_ARGS(SkDstOutXfermode, (rec));
1729 // no special-case, just rely in the rec and its function-ptrs
1730 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1734 gCachedXfermodes[mode] = xfer;
1736 return SkSafeRef(xfer);
1739 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1740 SkXfermodeProc proc = NULL;
1741 if ((unsigned)mode < kModeCount) {
1742 proc = gProcCoeffs[mode].fProc;
1747 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1748 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1750 if ((unsigned)mode >= (unsigned)kModeCount) {
1751 // illegal mode parameter
1755 const ProcCoeff& rec = gProcCoeffs[mode];
1757 if (CANNOT_USE_COEFF == rec.fSC) {
1761 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1771 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1774 *mode = kSrcOver_Mode;
1778 return xfer->asMode(mode);
1781 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1783 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1785 return xfer->asCoeff(src, dst);
1788 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1789 // if xfer==null then the mode is srcover
1790 Mode m = kSrcOver_Mode;
1791 if (xfer && !xfer->asMode(&m)) {
1797 ///////////////////////////////////////////////////////////////////////////////
1798 //////////// 16bit xfermode procs
1801 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1802 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1805 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1806 SkASSERT(require_255(src));
1807 return SkPixel32ToPixel16(src);
1810 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1814 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1815 SkASSERT(require_0(src));
1819 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1820 SkASSERT(require_255(src));
1821 return SkPixel32ToPixel16(src);
1824 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1825 SkASSERT(require_0(src));
1829 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1830 SkASSERT(require_255(src));
1834 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1835 SkASSERT(require_255(src));
1836 return SkPixel32ToPixel16(src);
1839 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1840 SkASSERT(require_255(src));
1844 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1845 SkASSERT(require_0(src));
1849 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1850 unsigned isa = 255 - SkGetPackedA32(src);
1853 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1854 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1855 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1858 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1859 SkASSERT(require_0(src));
1863 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1864 SkASSERT(require_255(src));
1865 return SkPixel32ToPixel16(src);
1868 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1869 SkASSERT(require_255(src));
1874 darken and lighten boil down to this.
1876 darken = (1 - Sa) * Dc + min(Sc, Dc)
1877 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1879 if (Sa == 0) these become
1880 darken = Dc + min(0, Dc) = 0
1881 lighten = Dc + max(0, Dc) = Dc
1883 if (Sa == 1) these become
1884 darken = min(Sc, Dc)
1885 lighten = max(Sc, Dc)
1888 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1889 SkASSERT(require_0(src));
1893 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1894 SkASSERT(require_255(src));
1895 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1896 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1897 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1898 return SkPackRGB16(r, g, b);
1901 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1902 SkASSERT(require_0(src));
1906 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1907 SkASSERT(require_255(src));
1908 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1909 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1910 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1911 return SkPackRGB16(r, g, b);
1915 SkXfermodeProc16 fProc16_0;
1916 SkXfermodeProc16 fProc16_255;
1917 SkXfermodeProc16 fProc16_General;
1920 static const Proc16Rec gModeProcs16[] = {
1921 { NULL, NULL, NULL }, // CLEAR
1922 { NULL, src_modeproc16_255, NULL },
1923 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1924 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1925 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1926 { NULL, srcin_modeproc16_255, NULL },
1927 { NULL, dstin_modeproc16_255, NULL },
1928 { NULL, NULL, NULL },// SRC_OUT
1929 { dstout_modeproc16_0, NULL, NULL },
1930 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1931 { NULL, dstatop_modeproc16_255, NULL },
1932 { NULL, NULL, NULL }, // XOR
1934 { NULL, NULL, NULL }, // plus
1935 { NULL, NULL, NULL }, // modulate
1936 { NULL, NULL, NULL }, // screen
1937 { NULL, NULL, NULL }, // overlay
1938 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1939 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1940 { NULL, NULL, NULL }, // colordodge
1941 { NULL, NULL, NULL }, // colorburn
1942 { NULL, NULL, NULL }, // hardlight
1943 { NULL, NULL, NULL }, // softlight
1944 { NULL, NULL, NULL }, // difference
1945 { NULL, NULL, NULL }, // exclusion
1946 { NULL, NULL, NULL }, // multiply
1947 { NULL, NULL, NULL }, // hue
1948 { NULL, NULL, NULL }, // saturation
1949 { NULL, NULL, NULL }, // color
1950 { NULL, NULL, NULL }, // luminosity
1953 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1954 SkXfermodeProc16 proc16 = NULL;
1955 if ((unsigned)mode < kModeCount) {
1956 const Proc16Rec& rec = gModeProcs16[mode];
1957 unsigned a = SkColorGetA(srcColor);
1960 proc16 = rec.fProc16_0;
1961 } else if (255 == a) {
1962 proc16 = rec.fProc16_255;
1964 proc16 = rec.fProc16_General;
1970 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1971 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1972 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1973 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1974 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1975 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1976 #if !SK_ARM_NEON_IS_NONE
1977 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
1979 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END