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 "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkMathPriv.h"
17 #include "SkUtilsArm.h"
19 #if !SK_ARM_NEON_IS_NONE
20 #include "SkXfermode_opts_arm_neon.h"
23 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
26 // idea for higher precision blends in xfer procs (and slightly faster)
27 // see DstATop as a probable caller
28 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
33 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
34 unsigned result = (prod + (prod >> 8)) >> 8;
35 SkASSERT(result <= 255);
40 static inline unsigned saturated_add(unsigned a, unsigned b) {
50 static inline int clamp_signed_byte(int n) {
59 static inline int clamp_div255round(int prod) {
62 } else if (prod >= 255*255) {
65 return SkDiv255Round(prod);
69 ///////////////////////////////////////////////////////////////////////////////
71 // kClear_Mode, //!< [0, 0]
72 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
76 // kSrc_Mode, //!< [Sa, Sc]
77 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
81 // kDst_Mode, //!< [Da, Dc]
82 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
86 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
87 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
89 // this is the old, more-correct way, but it doesn't guarantee that dst==255
90 // will always stay opaque
91 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
93 // this is slightly faster, but more importantly guarantees that dst==255
94 // will always stay opaque
95 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
99 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
100 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
101 // this is the reverse of srcover, just flipping src and dst
102 // see srcover's comment about the 256 for opaqueness guarantees
103 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
106 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
107 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
108 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
111 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
112 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
113 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
116 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
117 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
118 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
121 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
122 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
123 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
126 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
127 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
128 unsigned sa = SkGetPackedA32(src);
129 unsigned da = SkGetPackedA32(dst);
130 unsigned isa = 255 - sa;
132 return SkPackARGB32(da,
133 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
134 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
135 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
136 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
137 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
138 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
141 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
142 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
143 unsigned sa = SkGetPackedA32(src);
144 unsigned da = SkGetPackedA32(dst);
145 unsigned ida = 255 - da;
147 return SkPackARGB32(sa,
148 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
149 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
150 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
151 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
152 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
153 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
156 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
157 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
158 unsigned sa = SkGetPackedA32(src);
159 unsigned da = SkGetPackedA32(dst);
160 unsigned isa = 255 - sa;
161 unsigned ida = 255 - da;
163 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
164 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
165 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
166 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
167 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
168 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
169 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
172 ///////////////////////////////////////////////////////////////////////////////
175 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
176 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
177 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
178 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
179 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
180 return SkPackARGB32(a, r, g, b);
184 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
185 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
186 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
187 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
188 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
189 return SkPackARGB32(a, r, g, b);
192 static inline int srcover_byte(int a, int b) {
193 return a + b - SkAlphaMulAlpha(a, b);
197 // B(Cb, Cs) = Cb x Cs
198 // multiply uses its own version of blendfunc_byte because sa and da are not needed
199 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
200 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
203 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
204 int sa = SkGetPackedA32(src);
205 int da = SkGetPackedA32(dst);
206 int a = srcover_byte(sa, da);
207 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
208 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
209 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
210 return SkPackARGB32(a, r, g, b);
214 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
215 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
216 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
217 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
218 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
219 return SkPackARGB32(a, r, g, b);
223 static inline int overlay_byte(int sc, int dc, int sa, int da) {
224 int tmp = sc * (255 - da) + dc * (255 - sa);
229 rc = sa * da - 2 * (da - dc) * (sa - sc);
231 return clamp_div255round(rc + tmp);
233 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
234 int sa = SkGetPackedA32(src);
235 int da = SkGetPackedA32(dst);
236 int a = srcover_byte(sa, da);
237 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
238 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
239 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
240 return SkPackARGB32(a, r, g, b);
244 static inline int darken_byte(int sc, int dc, int sa, int da) {
249 return sc + dc - SkDiv255Round(ds);
252 return dc + sc - SkDiv255Round(sd);
255 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
256 int sa = SkGetPackedA32(src);
257 int da = SkGetPackedA32(dst);
258 int a = srcover_byte(sa, da);
259 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
260 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
261 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
262 return SkPackARGB32(a, r, g, b);
266 static inline int lighten_byte(int sc, int dc, int sa, int da) {
271 return sc + dc - SkDiv255Round(ds);
274 return dc + sc - SkDiv255Round(sd);
277 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
278 int sa = SkGetPackedA32(src);
279 int da = SkGetPackedA32(dst);
280 int a = srcover_byte(sa, da);
281 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
282 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
283 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
284 return SkPackARGB32(a, r, g, b);
288 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
292 return SkAlphaMulAlpha(sc, 255 - da);
293 } else if (0 == diff) {
294 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
296 diff = dc * sa / diff;
297 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
299 return clamp_div255round(rc);
301 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
302 int sa = SkGetPackedA32(src);
303 int da = SkGetPackedA32(dst);
304 int a = srcover_byte(sa, da);
305 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
306 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
307 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
308 return SkPackARGB32(a, r, g, b);
312 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
315 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
316 } else if (0 == sc) {
317 return SkAlphaMulAlpha(dc, 255 - sa);
319 int tmp = (da - dc) * sa / sc;
320 rc = sa * (da - ((da < tmp) ? da : tmp))
321 + sc * (255 - da) + dc * (255 - sa);
323 return clamp_div255round(rc);
325 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
326 int sa = SkGetPackedA32(src);
327 int da = SkGetPackedA32(dst);
328 int a = srcover_byte(sa, da);
329 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
330 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
331 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
332 return SkPackARGB32(a, r, g, b);
336 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
341 rc = sa * da - 2 * (da - dc) * (sa - sc);
343 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
345 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
346 int sa = SkGetPackedA32(src);
347 int da = SkGetPackedA32(dst);
348 int a = srcover_byte(sa, da);
349 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
350 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
351 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
352 return SkPackARGB32(a, r, g, b);
355 // returns 255 * sqrt(n/255)
356 static U8CPU sqrt_unit_byte(U8CPU n) {
357 return SkSqrtBits(n, 15+4);
361 static inline int softlight_byte(int sc, int dc, int sa, int da) {
362 int m = da ? dc * 256 / da : 0;
365 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
366 } else if (4 * dc <= da) {
367 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
368 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
370 int tmp = sqrt_unit_byte(m) - m;
371 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
373 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
375 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
376 int sa = SkGetPackedA32(src);
377 int da = SkGetPackedA32(dst);
378 int a = srcover_byte(sa, da);
379 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
380 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
381 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
382 return SkPackARGB32(a, r, g, b);
386 static inline int difference_byte(int sc, int dc, int sa, int da) {
387 int tmp = SkMin32(sc * da, dc * sa);
388 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
390 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
391 int sa = SkGetPackedA32(src);
392 int da = SkGetPackedA32(dst);
393 int a = srcover_byte(sa, da);
394 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
395 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
396 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
397 return SkPackARGB32(a, r, g, b);
401 static inline int exclusion_byte(int sc, int dc, int, int) {
402 // this equations is wacky, wait for SVG to confirm it
403 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
405 // The above equation can be simplified as follows
406 int r = 255*(sc + dc) - 2 * sc * dc;
407 return clamp_div255round(r);
409 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
410 int sa = SkGetPackedA32(src);
411 int da = SkGetPackedA32(dst);
412 int a = srcover_byte(sa, da);
413 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
414 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
415 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
416 return SkPackARGB32(a, r, g, b);
419 // The CSS compositing spec introduces the following formulas:
420 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
421 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
422 // while PDF and CG uses the one from Rec. Rec. 601
423 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
424 static inline int Lum(int r, int g, int b)
426 return SkDiv255Round(r * 77 + g * 150 + b * 28);
429 static inline int min2(int a, int b) { return a < b ? a : b; }
430 static inline int max2(int a, int b) { return a > b ? a : b; }
431 #define minimum(a, b, c) min2(min2(a, b), c)
432 #define maximum(a, b, c) max2(max2(a, b), c)
434 static inline int Sat(int r, int g, int b) {
435 return maximum(r, g, b) - minimum(r, g, b);
438 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
440 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
450 static inline void SetSat(int* r, int* g, int* b, int s) {
453 setSaturationComponents(r, g, b, s);
454 } else if(*r <= *b) {
455 setSaturationComponents(r, b, g, s);
457 setSaturationComponents(b, r, g, s);
459 } else if(*r <= *b) {
460 setSaturationComponents(g, r, b, s);
461 } else if(*g <= *b) {
462 setSaturationComponents(g, b, r, s);
464 setSaturationComponents(b, g, r, s);
468 static inline void clipColor(int* r, int* g, int* b, int a) {
469 int L = Lum(*r, *g, *b);
470 int n = minimum(*r, *g, *b);
471 int x = maximum(*r, *g, *b);
473 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
474 *r = L + SkMulDiv(*r - L, L, denom);
475 *g = L + SkMulDiv(*g - L, L, denom);
476 *b = L + SkMulDiv(*b - L, L, denom);
479 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
481 *r = L + SkMulDiv(*r - L, numer, denom);
482 *g = L + SkMulDiv(*g - L, numer, denom);
483 *b = L + SkMulDiv(*b - L, numer, denom);
487 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
488 int d = l - Lum(*r, *g, *b);
493 clipColor(r, g, b, a);
496 // non-separable blend modes are done in non-premultiplied alpha
497 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
498 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
501 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
502 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
503 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
504 int sr = SkGetPackedR32(src);
505 int sg = SkGetPackedG32(src);
506 int sb = SkGetPackedB32(src);
507 int sa = SkGetPackedA32(src);
509 int dr = SkGetPackedR32(dst);
510 int dg = SkGetPackedG32(dst);
511 int db = SkGetPackedB32(dst);
512 int da = SkGetPackedA32(dst);
519 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
520 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
527 int a = srcover_byte(sa, da);
528 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
529 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
530 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
531 return SkPackARGB32(a, r, g, b);
535 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
536 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
537 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
538 int sr = SkGetPackedR32(src);
539 int sg = SkGetPackedG32(src);
540 int sb = SkGetPackedB32(src);
541 int sa = SkGetPackedA32(src);
543 int dr = SkGetPackedR32(dst);
544 int dg = SkGetPackedG32(dst);
545 int db = SkGetPackedB32(dst);
546 int da = SkGetPackedA32(dst);
553 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
554 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
561 int a = srcover_byte(sa, da);
562 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
563 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
564 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
565 return SkPackARGB32(a, r, g, b);
569 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
570 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
571 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
572 int sr = SkGetPackedR32(src);
573 int sg = SkGetPackedG32(src);
574 int sb = SkGetPackedB32(src);
575 int sa = SkGetPackedA32(src);
577 int dr = SkGetPackedR32(dst);
578 int dg = SkGetPackedG32(dst);
579 int db = SkGetPackedB32(dst);
580 int da = SkGetPackedA32(dst);
587 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
594 int a = srcover_byte(sa, da);
595 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
596 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
597 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
598 return SkPackARGB32(a, r, g, b);
602 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
603 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
604 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
605 int sr = SkGetPackedR32(src);
606 int sg = SkGetPackedG32(src);
607 int sb = SkGetPackedB32(src);
608 int sa = SkGetPackedA32(src);
610 int dr = SkGetPackedR32(dst);
611 int dg = SkGetPackedG32(dst);
612 int db = SkGetPackedB32(dst);
613 int da = SkGetPackedA32(dst);
620 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
627 int a = srcover_byte(sa, da);
628 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
629 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
630 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
631 return SkPackARGB32(a, r, g, b);
634 const ProcCoeff gProcCoeffs[] = {
635 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
636 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
637 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
638 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
639 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
640 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
641 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
642 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
643 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
644 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
645 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
646 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
648 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
649 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
650 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
651 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
652 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
653 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
654 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
655 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
656 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
657 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
658 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
659 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
660 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
661 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
662 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
663 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
664 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
667 ///////////////////////////////////////////////////////////////////////////////
669 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
673 bool SkXfermode::asMode(Mode* mode) const {
677 bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
681 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
682 GrEffectRef** effect,
685 GrTexture* background) {
686 if (NULL == xfermode) {
687 return ModeAsCoeff(kSrcOver_Mode, src, dst);
688 } else if (xfermode->asCoeff(src, dst)) {
691 return xfermode->asNewEffect(effect, background);
695 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
696 // no-op. subclasses should override this
700 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
701 const SkPMColor* SK_RESTRICT src, int count,
702 const SkAlpha* SK_RESTRICT aa) const {
703 SkASSERT(dst && src && count >= 0);
706 for (int i = count - 1; i >= 0; --i) {
707 dst[i] = this->xferColor(src[i], dst[i]);
710 for (int i = count - 1; i >= 0; --i) {
713 SkPMColor dstC = dst[i];
714 SkPMColor C = this->xferColor(src[i], dstC);
716 C = SkFourByteInterp(C, dstC, a);
724 void SkXfermode::xfer16(uint16_t* dst,
725 const SkPMColor* SK_RESTRICT src, int count,
726 const SkAlpha* SK_RESTRICT aa) const {
727 SkASSERT(dst && src && count >= 0);
730 for (int i = count - 1; i >= 0; --i) {
731 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
732 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
735 for (int i = count - 1; i >= 0; --i) {
738 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
739 SkPMColor C = this->xferColor(src[i], dstC);
741 C = SkFourByteInterp(C, dstC, a);
743 dst[i] = SkPixel32ToPixel16_ToU16(C);
749 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
750 const SkPMColor src[], int count,
751 const SkAlpha* SK_RESTRICT aa) const {
752 SkASSERT(dst && src && count >= 0);
755 for (int i = count - 1; i >= 0; --i) {
756 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
757 dst[i] = SkToU8(SkGetPackedA32(res));
760 for (int i = count - 1; i >= 0; --i) {
763 SkAlpha dstA = dst[i];
764 unsigned A = SkGetPackedA32(this->xferColor(src[i],
765 (SkPMColor)(dstA << SK_A32_SHIFT)));
767 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
775 ///////////////////////////////////////////////////////////////////////////////
777 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
778 const SkPMColor* SK_RESTRICT src, int count,
779 const SkAlpha* SK_RESTRICT aa) const {
780 SkASSERT(dst && src && count >= 0);
782 SkXfermodeProc proc = fProc;
786 for (int i = count - 1; i >= 0; --i) {
787 dst[i] = proc(src[i], dst[i]);
790 for (int i = count - 1; i >= 0; --i) {
793 SkPMColor dstC = dst[i];
794 SkPMColor C = proc(src[i], dstC);
796 C = SkFourByteInterp(C, dstC, a);
805 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
806 const SkPMColor* SK_RESTRICT src, int count,
807 const SkAlpha* SK_RESTRICT aa) const {
808 SkASSERT(dst && src && count >= 0);
810 SkXfermodeProc proc = fProc;
814 for (int i = count - 1; i >= 0; --i) {
815 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
816 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
819 for (int i = count - 1; i >= 0; --i) {
822 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
823 SkPMColor C = proc(src[i], dstC);
825 C = SkFourByteInterp(C, dstC, a);
827 dst[i] = SkPixel32ToPixel16_ToU16(C);
834 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
835 const SkPMColor* SK_RESTRICT src, int count,
836 const SkAlpha* SK_RESTRICT aa) const {
837 SkASSERT(dst && src && count >= 0);
839 SkXfermodeProc proc = fProc;
843 for (int i = count - 1; i >= 0; --i) {
844 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
845 dst[i] = SkToU8(SkGetPackedA32(res));
848 for (int i = count - 1; i >= 0; --i) {
851 SkAlpha dstA = dst[i];
852 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
853 unsigned A = SkGetPackedA32(res);
855 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
864 SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer)
865 : SkXfermode(buffer) {
867 if (!buffer.isCrossProcess()) {
868 fProc = (SkXfermodeProc)buffer.readFunctionPtr();
872 void SkProcXfermode::flatten(SkWriteBuffer& buffer) const {
873 this->INHERITED::flatten(buffer);
874 if (!buffer.isCrossProcess()) {
875 buffer.writeFunctionPtr((void*)fProc);
880 void SkProcXfermode::toString(SkString* str) const {
881 str->appendf("SkProcXfermode: %p", fProc);
885 //////////////////////////////////////////////////////////////////////////////
889 #include "GrEffect.h"
890 #include "GrCoordTransform.h"
891 #include "GrEffectUnitTest.h"
892 #include "GrTBackendEffectFactory.h"
893 #include "gl/GrGLEffect.h"
896 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
898 class XferEffect : public GrEffect {
900 static bool IsSupportedMode(SkXfermode::Mode mode) {
901 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
904 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
905 if (!IsSupportedMode(mode)) {
908 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
909 return CreateEffectRef(effect);
913 virtual void getConstantColorComponents(GrColor* color,
914 uint32_t* validFlags) const SK_OVERRIDE {
918 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
919 return GrTBackendEffectFactory<XferEffect>::getInstance();
922 static const char* Name() { return "XferEffect"; }
924 SkXfermode::Mode mode() const { return fMode; }
925 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; }
927 class GLEffect : public GrGLEffect {
929 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
930 : GrGLEffect(factory) {
932 virtual void emitCode(GrGLShaderBuilder* builder,
933 const GrDrawEffect& drawEffect,
935 const char* outputColor,
936 const char* inputColor,
937 const TransformedCoordsArray& coords,
938 const TextureSamplerArray& samplers) SK_OVERRIDE {
939 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
940 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
941 const char* dstColor;
943 dstColor = "bgColor";
944 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
945 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
946 builder->fsCodeAppendf(";\n");
948 dstColor = builder->dstColor();
950 SkASSERT(NULL != dstColor);
952 // We don't try to optimize for this case at all
953 if (NULL == inputColor) {
954 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
957 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
959 // These all perform src-over on the alpha channel.
960 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
961 outputColor, inputColor, inputColor, dstColor);
964 case SkXfermode::kOverlay_Mode:
965 // Overlay is Hard-Light with the src and dst reversed
966 HardLight(builder, outputColor, dstColor, inputColor);
968 case SkXfermode::kDarken_Mode:
969 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
970 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
972 inputColor, dstColor, inputColor,
973 dstColor, inputColor, dstColor);
975 case SkXfermode::kLighten_Mode:
976 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
977 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
979 inputColor, dstColor, inputColor,
980 dstColor, inputColor, dstColor);
982 case SkXfermode::kColorDodge_Mode:
983 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
984 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
985 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
987 case SkXfermode::kColorBurn_Mode:
988 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
989 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
990 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
992 case SkXfermode::kHardLight_Mode:
993 HardLight(builder, outputColor, inputColor, dstColor);
995 case SkXfermode::kSoftLight_Mode:
996 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
997 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
998 builder->fsCodeAppendf("\t\t} else {\n");
999 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
1000 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1001 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1002 builder->fsCodeAppendf("\t\t}\n");
1004 case SkXfermode::kDifference_Mode:
1005 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1006 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1007 outputColor, inputColor, dstColor, inputColor, dstColor,
1008 dstColor, inputColor);
1010 case SkXfermode::kExclusion_Mode:
1011 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1012 "2.0 * %s.rgb * %s.rgb;\n",
1013 outputColor, dstColor, inputColor, dstColor, inputColor);
1015 case SkXfermode::kMultiply_Mode:
1016 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1017 "(1.0 - %s.a) * %s.rgb + "
1018 "%s.rgb * %s.rgb;\n",
1019 outputColor, inputColor, dstColor, dstColor, inputColor,
1020 inputColor, dstColor);
1022 case SkXfermode::kHue_Mode: {
1023 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1024 SkString setSat, setLum;
1025 AddSatFunction(builder, &setSat);
1026 AddLumFunction(builder, &setLum);
1027 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1028 dstColor, inputColor);
1029 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1030 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1032 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1033 outputColor, inputColor, dstColor, dstColor, inputColor);
1036 case SkXfermode::kSaturation_Mode: {
1037 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1038 SkString setSat, setLum;
1039 AddSatFunction(builder, &setSat);
1040 AddLumFunction(builder, &setLum);
1041 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1042 dstColor, inputColor);
1043 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1044 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1046 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1047 outputColor, inputColor, dstColor, dstColor, inputColor);
1050 case SkXfermode::kColor_Mode: {
1051 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1053 AddLumFunction(builder, &setLum);
1054 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1055 inputColor, dstColor);
1056 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
1057 outputColor, setLum.c_str(), dstColor, inputColor);
1058 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1059 outputColor, inputColor, dstColor, dstColor, inputColor);
1062 case SkXfermode::kLuminosity_Mode: {
1063 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1065 AddLumFunction(builder, &setLum);
1066 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1067 inputColor, dstColor);
1068 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
1069 outputColor, setLum.c_str(), dstColor, inputColor);
1070 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1071 outputColor, inputColor, dstColor, dstColor, inputColor);
1075 GrCrash("Unknown XferEffect mode.");
1080 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1081 return drawEffect.castEffect<XferEffect>().mode();
1085 static void HardLight(GrGLShaderBuilder* builder,
1089 static const char kComponents[] = {'r', 'g', 'b'};
1090 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
1091 char component = kComponents[i];
1092 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1093 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
1094 builder->fsCodeAppend("\t\t} else {\n");
1095 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
1096 final, component, src, dst, dst, dst, component, src, src, component);
1097 builder->fsCodeAppend("\t\t}\n");
1099 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1100 final, src, dst, dst, src);
1103 // Does one component of color-dodge
1104 static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1108 const char component) {
1109 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1110 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1111 final, component, src, component, dst);
1112 builder->fsCodeAppend("\t\t} else {\n");
1113 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1114 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1115 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",
1116 final, component, src, dst, src, component, dst, dst, component,
1118 builder->fsCodeAppend("\t\t\t} else {\n");
1119 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1120 dst, dst, component, src);
1121 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1122 final, component, src, src, component, dst, dst, component, src);
1123 builder->fsCodeAppend("\t\t\t}\n");
1124 builder->fsCodeAppend("\t\t}\n");
1127 // Does one component of color-burn
1128 static void ColorBurnComponent(GrGLShaderBuilder* builder,
1132 const char component) {
1133 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1134 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1135 final, component, src, dst, src, component, dst, dst, component,
1137 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1138 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1139 final, component, dst, component, src);
1140 builder->fsCodeAppend("\t\t} else {\n");
1141 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1142 dst, dst, dst, component, src, src, component);
1143 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1144 final, component, src, src, component, dst, dst, component, src);
1145 builder->fsCodeAppend("\t\t}\n");
1148 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1149 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1153 const char component) {
1155 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1156 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1157 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",
1158 final, component, dst, component, dst, component, src, src,
1159 component, dst, dst, src, component, dst, component, src, src,
1161 // else if (4D < Da)
1162 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1163 dst, component, dst);
1164 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1165 dst, component, dst, component);
1166 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1167 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1168 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1169 // (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
1170 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",
1171 final, component, src, component, src, component, dst, component,
1172 src, src, component, dst, src, src, component, src, src,
1174 builder->fsCodeAppendf("\t\t\t} else {\n");
1175 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1176 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",
1177 final, component, dst, dst, component, src, src, component, dst,
1178 src, component, dst, component, src, src, component, src,
1180 builder->fsCodeAppendf("\t\t\t}\n");
1183 // Adds a function that takes two colors and an alpha as input. It produces a color with the
1184 // hue and saturation of the first color, the luminosity of the second color, and the input
1185 // alpha. It has this signature:
1186 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1187 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1188 // Emit a helper that gets the luminance of a color.
1189 SkString getFunction;
1190 GrGLShaderVar getLumArgs[] = {
1191 GrGLShaderVar("color", kVec3f_GrSLType),
1193 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1194 builder->fsEmitFunction(kFloat_GrSLType,
1196 SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1200 // Emit the set luminance function.
1201 GrGLShaderVar setLumArgs[] = {
1202 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1203 GrGLShaderVar("alpha", kFloat_GrSLType),
1204 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1206 SkString setLumBody;
1207 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1208 setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1209 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1210 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1211 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1212 "\tif (minComp < 0.0) {\n"
1213 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1215 "\tif (maxComp > alpha) {\n"
1216 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1218 "\treturn outColor;\n");
1219 builder->fsEmitFunction(kVec3f_GrSLType,
1221 SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1226 // Adds a function that creates a color with the hue and luminosity of one input color and
1227 // the saturation of another color. It will have this signature:
1228 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1229 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1230 // Emit a helper that gets the saturation of a color
1231 SkString getFunction;
1232 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1233 SkString getSatBody;
1234 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1235 "min(min(color.r, color.g), color.b);\n");
1236 builder->fsEmitFunction(kFloat_GrSLType,
1238 SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1242 // Emit a helper that sets the saturation given sorted input channels. This used
1243 // to use inout params for min, mid, and max components but that seems to cause
1244 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1245 // adjusted min, mid, and max inputs, respectively.
1246 SkString helperFunction;
1247 GrGLShaderVar helperArgs[] = {
1248 GrGLShaderVar("minComp", kFloat_GrSLType),
1249 GrGLShaderVar("midComp", kFloat_GrSLType),
1250 GrGLShaderVar("maxComp", kFloat_GrSLType),
1251 GrGLShaderVar("sat", kFloat_GrSLType),
1253 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1254 "\t\tvec3 result;\n"
1255 "\t\tresult.r = 0.0;\n"
1256 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1257 "\t\tresult.b = sat;\n"
1258 "\t\treturn result;\n"
1260 "\t\treturn vec3(0, 0, 0);\n"
1262 builder->fsEmitFunction(kVec3f_GrSLType,
1263 "set_saturation_helper",
1264 SK_ARRAY_COUNT(helperArgs), helperArgs,
1268 GrGLShaderVar setSatArgs[] = {
1269 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1270 GrGLShaderVar("satColor", kVec3f_GrSLType),
1272 const char* helpFunc = helperFunction.c_str();
1273 SkString setSatBody;
1274 setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1275 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1276 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1277 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1278 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1279 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1281 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1283 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1284 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1285 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1286 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1288 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1290 "\treturn hueLumColor;\n",
1291 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1292 helpFunc, helpFunc);
1293 builder->fsEmitFunction(kVec3f_GrSLType,
1295 SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1301 typedef GrGLEffect INHERITED;
1304 GR_DECLARE_EFFECT_TEST;
1307 XferEffect(SkXfermode::Mode mode, GrTexture* background)
1310 fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1311 this->addCoordTransform(&fBackgroundTransform);
1312 fBackgroundAccess.reset(background);
1313 this->addTextureAccess(&fBackgroundAccess);
1315 this->setWillReadDstColor();
1318 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1319 const XferEffect& s = CastEffect<XferEffect>(other);
1320 return fMode == s.fMode &&
1321 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1324 SkXfermode::Mode fMode;
1325 GrCoordTransform fBackgroundTransform;
1326 GrTextureAccess fBackgroundAccess;
1328 typedef GrEffect INHERITED;
1331 GR_DEFINE_EFFECT_TEST(XferEffect);
1332 GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
1334 const GrDrawTargetCaps&,
1336 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1338 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
1339 return CreateEffectRef(gEffect);
1344 ///////////////////////////////////////////////////////////////////////////////
1345 ///////////////////////////////////////////////////////////////////////////////
1347 SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1348 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1349 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1350 // out of range, just set to something harmless
1351 mode32 = SkXfermode::kSrcOut_Mode;
1353 fMode = (SkXfermode::Mode)mode32;
1355 const ProcCoeff& rec = gProcCoeffs[fMode];
1356 // these may be valid, or may be CANNOT_USE_COEFF
1357 fSrcCoeff = rec.fSC;
1358 fDstCoeff = rec.fDC;
1359 // now update our function-ptr in the super class
1360 this->INHERITED::setProc(rec.fProc);
1363 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1370 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1371 if (CANNOT_USE_COEFF == fSrcCoeff) {
1385 bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
1386 GrTexture* background) const {
1387 if (XferEffect::IsSupportedMode(fMode)) {
1388 if (NULL != effect) {
1389 *effect = XferEffect::Create(fMode, background);
1390 SkASSERT(NULL != *effect);
1398 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1399 this->INHERITED::flatten(buffer);
1400 buffer.write32(fMode);
1403 const char* SkXfermode::ModeName(Mode mode) {
1404 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1405 const char* gModeStrings[] = {
1406 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1407 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1408 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1409 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1410 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1412 return gModeStrings[mode];
1413 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1417 void SkProcCoeffXfermode::toString(SkString* str) const {
1418 str->append("SkProcCoeffXfermode: ");
1420 str->append("mode: ");
1421 str->append(ModeName(fMode));
1423 static const char* gCoeffStrings[kCoeffCount] = {
1424 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1427 str->append(" src: ");
1428 if (CANNOT_USE_COEFF == fSrcCoeff) {
1429 str->append("can't use");
1431 str->append(gCoeffStrings[fSrcCoeff]);
1434 str->append(" dst: ");
1435 if (CANNOT_USE_COEFF == fDstCoeff) {
1436 str->append("can't use");
1438 str->append(gCoeffStrings[fDstCoeff]);
1443 ///////////////////////////////////////////////////////////////////////////////
1445 class SkClearXfermode : public SkProcCoeffXfermode {
1447 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1449 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1450 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1452 SK_DEVELOPER_TO_STRING()
1453 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1456 SkClearXfermode(SkReadBuffer& buffer)
1457 : SkProcCoeffXfermode(buffer) {}
1459 typedef SkProcCoeffXfermode INHERITED;
1462 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1463 const SkPMColor* SK_RESTRICT, int count,
1464 const SkAlpha* SK_RESTRICT aa) const {
1465 SkASSERT(dst && count >= 0);
1468 memset(dst, 0, count << 2);
1470 for (int i = count - 1; i >= 0; --i) {
1474 } else if (a != 0) {
1475 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1480 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1481 const SkPMColor* SK_RESTRICT, int count,
1482 const SkAlpha* SK_RESTRICT aa) const {
1483 SkASSERT(dst && count >= 0);
1486 memset(dst, 0, count);
1488 for (int i = count - 1; i >= 0; --i) {
1492 } else if (0 != a) {
1493 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1500 void SkClearXfermode::toString(SkString* str) const {
1501 this->INHERITED::toString(str);
1505 ///////////////////////////////////////////////////////////////////////////////
1507 class SkSrcXfermode : public SkProcCoeffXfermode {
1509 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1511 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1512 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1514 SK_DEVELOPER_TO_STRING()
1515 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1518 SkSrcXfermode(SkReadBuffer& buffer)
1519 : SkProcCoeffXfermode(buffer) {}
1521 typedef SkProcCoeffXfermode INHERITED;
1524 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1525 const SkPMColor* SK_RESTRICT src, int count,
1526 const SkAlpha* SK_RESTRICT aa) const {
1527 SkASSERT(dst && src && count >= 0);
1530 memcpy(dst, src, count << 2);
1532 for (int i = count - 1; i >= 0; --i) {
1536 } else if (a != 0) {
1537 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1543 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1544 const SkPMColor* SK_RESTRICT src, int count,
1545 const SkAlpha* SK_RESTRICT aa) const {
1546 SkASSERT(dst && src && count >= 0);
1549 for (int i = count - 1; i >= 0; --i) {
1550 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1553 for (int i = count - 1; i >= 0; --i) {
1556 unsigned srcA = SkGetPackedA32(src[i]);
1558 dst[i] = SkToU8(srcA);
1560 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1567 void SkSrcXfermode::toString(SkString* str) const {
1568 this->INHERITED::toString(str);
1572 ///////////////////////////////////////////////////////////////////////////////
1574 class SkDstInXfermode : public SkProcCoeffXfermode {
1576 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1578 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1580 SK_DEVELOPER_TO_STRING()
1581 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1584 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1586 typedef SkProcCoeffXfermode INHERITED;
1589 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1590 const SkPMColor* SK_RESTRICT src, int count,
1591 const SkAlpha* SK_RESTRICT aa) const {
1592 SkASSERT(dst && src);
1598 return this->INHERITED::xfer32(dst, src, count, aa);
1602 unsigned a = SkGetPackedA32(*src);
1603 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1606 } while (--count != 0);
1610 void SkDstInXfermode::toString(SkString* str) const {
1611 this->INHERITED::toString(str);
1615 ///////////////////////////////////////////////////////////////////////////////
1617 class SkDstOutXfermode : public SkProcCoeffXfermode {
1619 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1621 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1623 SK_DEVELOPER_TO_STRING()
1624 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1627 SkDstOutXfermode(SkReadBuffer& buffer)
1628 : 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);
1654 void SkDstOutXfermode::toString(SkString* str) const {
1655 this->INHERITED::toString(str);
1659 ///////////////////////////////////////////////////////////////////////////////
1661 SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex);
1662 static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1];
1664 void SkXfermode::Term() {
1665 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1667 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) {
1668 SkSafeUnref(gCachedXfermodes[i]);
1669 gCachedXfermodes[i] = NULL;
1673 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
1674 SkXfermode::Mode mode);
1675 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1677 SkXfermode* SkXfermode::Create(Mode mode) {
1678 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1679 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount);
1681 if ((unsigned)mode >= kModeCount) {
1686 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover
1687 // so we can just return NULL from the factory.
1688 if (kSrcOver_Mode == mode) {
1692 // guard our access to gCachedXfermodes, since we may write into it
1693 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1695 SkXfermode* xfer = gCachedXfermodes[mode];
1697 ProcCoeff rec = gProcCoeffs[mode];
1699 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1705 // check if we have a platform optim for that
1706 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1710 // All modes can in theory be represented by the ProcCoeff rec, since
1711 // it contains function ptrs. However, a few modes are both simple and
1712 // commonly used, so we call those out for their own subclasses here.
1715 xfer = SkNEW_ARGS(SkClearXfermode, (rec));
1718 xfer = SkNEW_ARGS(SkSrcXfermode, (rec));
1721 SkASSERT(false); // should not land here
1724 xfer = SkNEW_ARGS(SkDstInXfermode, (rec));
1727 xfer = SkNEW_ARGS(SkDstOutXfermode, (rec));
1730 // no special-case, just rely in the rec and its function-ptrs
1731 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1735 gCachedXfermodes[mode] = xfer;
1737 return SkSafeRef(xfer);
1740 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1741 SkXfermodeProc proc = NULL;
1742 if ((unsigned)mode < kModeCount) {
1743 proc = gProcCoeffs[mode].fProc;
1748 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1749 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1751 if ((unsigned)mode >= (unsigned)kModeCount) {
1752 // illegal mode parameter
1756 const ProcCoeff& rec = gProcCoeffs[mode];
1758 if (CANNOT_USE_COEFF == rec.fSC) {
1762 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1772 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1775 *mode = kSrcOver_Mode;
1779 return xfer->asMode(mode);
1782 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1784 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1786 return xfer->asCoeff(src, dst);
1789 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1790 // if xfer==null then the mode is srcover
1791 Mode m = kSrcOver_Mode;
1792 if (xfer && !xfer->asMode(&m)) {
1798 ///////////////////////////////////////////////////////////////////////////////
1799 //////////// 16bit xfermode procs
1802 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1803 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1806 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1807 SkASSERT(require_255(src));
1808 return SkPixel32ToPixel16(src);
1811 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1815 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1816 SkASSERT(require_0(src));
1820 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1821 SkASSERT(require_255(src));
1822 return SkPixel32ToPixel16(src);
1825 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1826 SkASSERT(require_0(src));
1830 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1831 SkASSERT(require_255(src));
1835 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1836 SkASSERT(require_255(src));
1837 return SkPixel32ToPixel16(src);
1840 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1841 SkASSERT(require_255(src));
1845 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1846 SkASSERT(require_0(src));
1850 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1851 unsigned isa = 255 - SkGetPackedA32(src);
1854 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1855 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1856 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1859 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1860 SkASSERT(require_0(src));
1864 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1865 SkASSERT(require_255(src));
1866 return SkPixel32ToPixel16(src);
1869 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1870 SkASSERT(require_255(src));
1875 darken and lighten boil down to this.
1877 darken = (1 - Sa) * Dc + min(Sc, Dc)
1878 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1880 if (Sa == 0) these become
1881 darken = Dc + min(0, Dc) = 0
1882 lighten = Dc + max(0, Dc) = Dc
1884 if (Sa == 1) these become
1885 darken = min(Sc, Dc)
1886 lighten = max(Sc, Dc)
1889 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1890 SkASSERT(require_0(src));
1894 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1895 SkASSERT(require_255(src));
1896 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1897 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1898 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1899 return SkPackRGB16(r, g, b);
1902 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1903 SkASSERT(require_0(src));
1907 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1908 SkASSERT(require_255(src));
1909 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1910 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1911 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1912 return SkPackRGB16(r, g, b);
1916 SkXfermodeProc16 fProc16_0;
1917 SkXfermodeProc16 fProc16_255;
1918 SkXfermodeProc16 fProc16_General;
1921 static const Proc16Rec gModeProcs16[] = {
1922 { NULL, NULL, NULL }, // CLEAR
1923 { NULL, src_modeproc16_255, NULL },
1924 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1925 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1926 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1927 { NULL, srcin_modeproc16_255, NULL },
1928 { NULL, dstin_modeproc16_255, NULL },
1929 { NULL, NULL, NULL },// SRC_OUT
1930 { dstout_modeproc16_0, NULL, NULL },
1931 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1932 { NULL, dstatop_modeproc16_255, NULL },
1933 { NULL, NULL, NULL }, // XOR
1935 { NULL, NULL, NULL }, // plus
1936 { NULL, NULL, NULL }, // modulate
1937 { NULL, NULL, NULL }, // screen
1938 { NULL, NULL, NULL }, // overlay
1939 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1940 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1941 { NULL, NULL, NULL }, // colordodge
1942 { NULL, NULL, NULL }, // colorburn
1943 { NULL, NULL, NULL }, // hardlight
1944 { NULL, NULL, NULL }, // softlight
1945 { NULL, NULL, NULL }, // difference
1946 { NULL, NULL, NULL }, // exclusion
1947 { NULL, NULL, NULL }, // multiply
1948 { NULL, NULL, NULL }, // hue
1949 { NULL, NULL, NULL }, // saturation
1950 { NULL, NULL, NULL }, // color
1951 { NULL, NULL, NULL }, // luminosity
1954 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1955 SkXfermodeProc16 proc16 = NULL;
1956 if ((unsigned)mode < kModeCount) {
1957 const Proc16Rec& rec = gModeProcs16[mode];
1958 unsigned a = SkColorGetA(srcColor);
1961 proc16 = rec.fProc16_0;
1962 } else if (255 == a) {
1963 proc16 = rec.fProc16_255;
1965 proc16 = rec.fProc16_General;
1971 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1972 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1973 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1974 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1975 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1976 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1977 #if !SK_ARM_NEON_IS_NONE
1978 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
1980 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END