SkXfermode.cpp revision 84cc1ebc5a4789e93e23c65eb4014ef5b8b0bab4
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkXfermode.h" 11#include "SkXfermode_proccoeff.h" 12#include "SkColorPriv.h" 13#include "SkFlattenableBuffers.h" 14#include "SkMathPriv.h" 15#include "SkString.h" 16 17SK_DEFINE_INST_COUNT(SkXfermode) 18 19#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) 20 21#if 0 22// idea for higher precision blends in xfer procs (and slightly faster) 23// see DstATop as a probable caller 24static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { 25 SkASSERT(a <= 255); 26 SkASSERT(b <= 255); 27 SkASSERT(c <= 255); 28 SkASSERT(d <= 255); 29 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; 30 unsigned result = (prod + (prod >> 8)) >> 8; 31 SkASSERT(result <= 255); 32 return result; 33} 34#endif 35 36static inline unsigned saturated_add(unsigned a, unsigned b) { 37 SkASSERT(a <= 255); 38 SkASSERT(b <= 255); 39 unsigned sum = a + b; 40 if (sum > 255) { 41 sum = 255; 42 } 43 return sum; 44} 45 46static inline int clamp_signed_byte(int n) { 47 if (n < 0) { 48 n = 0; 49 } else if (n > 255) { 50 n = 255; 51 } 52 return n; 53} 54 55static inline int clamp_div255round(int prod) { 56 if (prod <= 0) { 57 return 0; 58 } else if (prod >= 255*255) { 59 return 255; 60 } else { 61 return SkDiv255Round(prod); 62 } 63} 64 65/////////////////////////////////////////////////////////////////////////////// 66 67// kClear_Mode, //!< [0, 0] 68static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 69 return 0; 70} 71 72// kSrc_Mode, //!< [Sa, Sc] 73static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 74 return src; 75} 76 77// kDst_Mode, //!< [Da, Dc] 78static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 79 return dst; 80} 81 82// kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 83static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) { 84#if 0 85 // this is the old, more-correct way, but it doesn't guarantee that dst==255 86 // will always stay opaque 87 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 88#else 89 // this is slightly faster, but more importantly guarantees that dst==255 90 // will always stay opaque 91 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src)); 92#endif 93} 94 95// kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc] 96static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) { 97 // this is the reverse of srcover, just flipping src and dst 98 // see srcover's comment about the 256 for opaqueness guarantees 99 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst)); 100} 101 102// kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 103static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 104 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 105} 106 107// kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 108static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) { 109 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src))); 110} 111 112// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 113static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) { 114 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst))); 115} 116 117// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 118static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { 119 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 120} 121 122// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 123static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) { 124 unsigned sa = SkGetPackedA32(src); 125 unsigned da = SkGetPackedA32(dst); 126 unsigned isa = 255 - sa; 127 128 return SkPackARGB32(da, 129 SkAlphaMulAlpha(da, SkGetPackedR32(src)) + 130 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 131 SkAlphaMulAlpha(da, SkGetPackedG32(src)) + 132 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 133 SkAlphaMulAlpha(da, SkGetPackedB32(src)) + 134 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 135} 136 137// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 138static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) { 139 unsigned sa = SkGetPackedA32(src); 140 unsigned da = SkGetPackedA32(dst); 141 unsigned ida = 255 - da; 142 143 return SkPackARGB32(sa, 144 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 145 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)), 146 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 147 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)), 148 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 149 SkAlphaMulAlpha(sa, SkGetPackedB32(dst))); 150} 151 152// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 153static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) { 154 unsigned sa = SkGetPackedA32(src); 155 unsigned da = SkGetPackedA32(dst); 156 unsigned isa = 255 - sa; 157 unsigned ida = 255 - da; 158 159 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1), 160 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 161 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 162 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 163 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 164 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 165 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 166} 167 168/////////////////////////////////////////////////////////////////////////////// 169 170// kPlus_Mode 171static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { 172 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); 173 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); 174 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); 175 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); 176 return SkPackARGB32(a, r, g, b); 177} 178 179// kModulate_Mode 180static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) { 181 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); 182 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); 183 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); 184 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); 185 return SkPackARGB32(a, r, g, b); 186} 187 188static inline int srcover_byte(int a, int b) { 189 return a + b - SkAlphaMulAlpha(a, b); 190} 191 192// kMultiply_Mode 193// B(Cb, Cs) = Cb x Cs 194// multiply uses its own version of blendfunc_byte because sa and da are not needed 195static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) { 196 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc); 197} 198 199static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { 200 int sa = SkGetPackedA32(src); 201 int da = SkGetPackedA32(dst); 202 int a = srcover_byte(sa, da); 203 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 204 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 205 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 206 return SkPackARGB32(a, r, g, b); 207} 208 209// kScreen_Mode 210static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { 211 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); 212 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); 213 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); 214 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); 215 return SkPackARGB32(a, r, g, b); 216} 217 218// kOverlay_Mode 219static inline int overlay_byte(int sc, int dc, int sa, int da) { 220 int tmp = sc * (255 - da) + dc * (255 - sa); 221 int rc; 222 if (2 * dc <= da) { 223 rc = 2 * sc * dc; 224 } else { 225 rc = sa * da - 2 * (da - dc) * (sa - sc); 226 } 227 return clamp_div255round(rc + tmp); 228} 229static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { 230 int sa = SkGetPackedA32(src); 231 int da = SkGetPackedA32(dst); 232 int a = srcover_byte(sa, da); 233 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 234 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 235 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 236 return SkPackARGB32(a, r, g, b); 237} 238 239// kDarken_Mode 240static inline int darken_byte(int sc, int dc, int sa, int da) { 241 int sd = sc * da; 242 int ds = dc * sa; 243 if (sd < ds) { 244 // srcover 245 return sc + dc - SkDiv255Round(ds); 246 } else { 247 // dstover 248 return dc + sc - SkDiv255Round(sd); 249 } 250} 251static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { 252 int sa = SkGetPackedA32(src); 253 int da = SkGetPackedA32(dst); 254 int a = srcover_byte(sa, da); 255 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 256 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 257 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 258 return SkPackARGB32(a, r, g, b); 259} 260 261// kLighten_Mode 262static inline int lighten_byte(int sc, int dc, int sa, int da) { 263 int sd = sc * da; 264 int ds = dc * sa; 265 if (sd > ds) { 266 // srcover 267 return sc + dc - SkDiv255Round(ds); 268 } else { 269 // dstover 270 return dc + sc - SkDiv255Round(sd); 271 } 272} 273static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { 274 int sa = SkGetPackedA32(src); 275 int da = SkGetPackedA32(dst); 276 int a = srcover_byte(sa, da); 277 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 278 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 279 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 280 return SkPackARGB32(a, r, g, b); 281} 282 283// kColorDodge_Mode 284static inline int colordodge_byte(int sc, int dc, int sa, int da) { 285 int diff = sa - sc; 286 int rc; 287 if (0 == dc) { 288 return SkAlphaMulAlpha(sc, 255 - da); 289 } else if (0 == diff) { 290 rc = sa * da + sc * (255 - da) + dc * (255 - sa); 291 } else { 292 diff = dc * sa / diff; 293 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa); 294 } 295 return clamp_div255round(rc); 296} 297static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { 298 int sa = SkGetPackedA32(src); 299 int da = SkGetPackedA32(dst); 300 int a = srcover_byte(sa, da); 301 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 302 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 303 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 304 return SkPackARGB32(a, r, g, b); 305} 306 307// kColorBurn_Mode 308static inline int colorburn_byte(int sc, int dc, int sa, int da) { 309 int rc; 310 if (dc == da) { 311 rc = sa * da + sc * (255 - da) + dc * (255 - sa); 312 } else if (0 == sc) { 313 return SkAlphaMulAlpha(dc, 255 - sa); 314 } else { 315 int tmp = (da - dc) * sa / sc; 316 rc = sa * (da - ((da < tmp) ? da : tmp)) 317 + sc * (255 - da) + dc * (255 - sa); 318 } 319 return clamp_div255round(rc); 320} 321static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { 322 int sa = SkGetPackedA32(src); 323 int da = SkGetPackedA32(dst); 324 int a = srcover_byte(sa, da); 325 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 326 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 327 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 328 return SkPackARGB32(a, r, g, b); 329} 330 331// kHardLight_Mode 332static inline int hardlight_byte(int sc, int dc, int sa, int da) { 333 int rc; 334 if (2 * sc <= sa) { 335 rc = 2 * sc * dc; 336 } else { 337 rc = sa * da - 2 * (da - dc) * (sa - sc); 338 } 339 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 340} 341static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { 342 int sa = SkGetPackedA32(src); 343 int da = SkGetPackedA32(dst); 344 int a = srcover_byte(sa, da); 345 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 346 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 347 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 348 return SkPackARGB32(a, r, g, b); 349} 350 351// returns 255 * sqrt(n/255) 352static U8CPU sqrt_unit_byte(U8CPU n) { 353 return SkSqrtBits(n, 15+4); 354} 355 356// kSoftLight_Mode 357static inline int softlight_byte(int sc, int dc, int sa, int da) { 358 int m = da ? dc * 256 / da : 0; 359 int rc; 360 if (2 * sc <= sa) { 361 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); 362 } else if (4 * dc <= da) { 363 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; 364 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 365 } else { 366 int tmp = sqrt_unit_byte(m) - m; 367 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 368 } 369 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 370} 371static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { 372 int sa = SkGetPackedA32(src); 373 int da = SkGetPackedA32(dst); 374 int a = srcover_byte(sa, da); 375 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 376 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 377 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 378 return SkPackARGB32(a, r, g, b); 379} 380 381// kDifference_Mode 382static inline int difference_byte(int sc, int dc, int sa, int da) { 383 int tmp = SkMin32(sc * da, dc * sa); 384 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); 385} 386static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { 387 int sa = SkGetPackedA32(src); 388 int da = SkGetPackedA32(dst); 389 int a = srcover_byte(sa, da); 390 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 391 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 392 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 393 return SkPackARGB32(a, r, g, b); 394} 395 396// kExclusion_Mode 397static inline int exclusion_byte(int sc, int dc, int, int) { 398 // this equations is wacky, wait for SVG to confirm it 399 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); 400 401 // The above equation can be simplified as follows 402 int r = 255*(sc + dc) - 2 * sc * dc; 403 return clamp_div255round(r); 404} 405static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { 406 int sa = SkGetPackedA32(src); 407 int da = SkGetPackedA32(dst); 408 int a = srcover_byte(sa, da); 409 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 410 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 411 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 412 return SkPackARGB32(a, r, g, b); 413} 414 415// The CSS compositing spec introduces the following formulas: 416// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable) 417// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709 418// while PDF and CG uses the one from Rec. Rec. 601 419// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm 420static inline int Lum(int r, int g, int b) 421{ 422 return SkDiv255Round(r * 77 + g * 150 + b * 28); 423} 424 425static inline int min2(int a, int b) { return a < b ? a : b; } 426static inline int max2(int a, int b) { return a > b ? a : b; } 427#define minimum(a, b, c) min2(min2(a, b), c) 428#define maximum(a, b, c) max2(max2(a, b), c) 429 430static inline int Sat(int r, int g, int b) { 431 return maximum(r, g, b) - minimum(r, g, b); 432} 433 434static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) { 435 if(*Cmax > *Cmin) { 436 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin); 437 *Cmax = s; 438 } else { 439 *Cmax = 0; 440 *Cmid = 0; 441 } 442 443 *Cmin = 0; 444} 445 446static inline void SetSat(int* r, int* g, int* b, int s) { 447 if(*r <= *g) { 448 if(*g <= *b) { 449 setSaturationComponents(r, g, b, s); 450 } else if(*r <= *b) { 451 setSaturationComponents(r, b, g, s); 452 } else { 453 setSaturationComponents(b, r, g, s); 454 } 455 } else if(*r <= *b) { 456 setSaturationComponents(g, r, b, s); 457 } else if(*g <= *b) { 458 setSaturationComponents(g, b, r, s); 459 } else { 460 setSaturationComponents(b, g, r, s); 461 } 462} 463 464static inline void clipColor(int* r, int* g, int* b, int a) { 465 int L = Lum(*r, *g, *b); 466 int n = minimum(*r, *g, *b); 467 int x = maximum(*r, *g, *b); 468 if(n < 0) { 469 *r = L + SkMulDiv(*r - L, L, L - n); 470 *g = L + SkMulDiv(*g - L, L, L - n); 471 *b = L + SkMulDiv(*b - L, L, L - n); 472 } 473 474 if (x > a) { 475 *r = L + SkMulDiv(*r - L, a - L, x - L); 476 *g = L + SkMulDiv(*g - L, a - L, x - L); 477 *b = L + SkMulDiv(*b - L, a - L, x - L); 478 } 479} 480 481static inline void SetLum(int* r, int* g, int* b, int a, int l) { 482 int d = l - Lum(*r, *g, *b); 483 *r += d; 484 *g += d; 485 *b += d; 486 487 clipColor(r, g, b, a); 488} 489 490// non-separable blend modes are done in non-premultiplied alpha 491#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ 492 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval) 493 494// kHue_Mode 495// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)) 496// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color. 497static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { 498 int sr = SkGetPackedR32(src); 499 int sg = SkGetPackedG32(src); 500 int sb = SkGetPackedB32(src); 501 int sa = SkGetPackedA32(src); 502 503 int dr = SkGetPackedR32(dst); 504 int dg = SkGetPackedG32(dst); 505 int db = SkGetPackedB32(dst); 506 int da = SkGetPackedA32(dst); 507 int Sr, Sg, Sb; 508 509 if(sa && da) { 510 Sr = sr * sa; 511 Sg = sg * sa; 512 Sb = sb * sa; 513 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa); 514 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 515 } else { 516 Sr = 0; 517 Sg = 0; 518 Sb = 0; 519 } 520 521 int a = srcover_byte(sa, da); 522 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 523 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 524 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 525 return SkPackARGB32(a, r, g, b); 526} 527 528// kSaturation_Mode 529// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)) 530// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color. 531static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { 532 int sr = SkGetPackedR32(src); 533 int sg = SkGetPackedG32(src); 534 int sb = SkGetPackedB32(src); 535 int sa = SkGetPackedA32(src); 536 537 int dr = SkGetPackedR32(dst); 538 int dg = SkGetPackedG32(dst); 539 int db = SkGetPackedB32(dst); 540 int da = SkGetPackedA32(dst); 541 int Dr, Dg, Db; 542 543 if(sa && da) { 544 Dr = dr * sa; 545 Dg = dg * sa; 546 Db = db * sa; 547 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da); 548 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa); 549 } else { 550 Dr = 0; 551 Dg = 0; 552 Db = 0; 553 } 554 555 int a = srcover_byte(sa, da); 556 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 557 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 558 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 559 return SkPackARGB32(a, r, g, b); 560} 561 562// kColor_Mode 563// B(Cb, Cs) = SetLum(Cs, Lum(Cb)) 564// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color. 565static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { 566 int sr = SkGetPackedR32(src); 567 int sg = SkGetPackedG32(src); 568 int sb = SkGetPackedB32(src); 569 int sa = SkGetPackedA32(src); 570 571 int dr = SkGetPackedR32(dst); 572 int dg = SkGetPackedG32(dst); 573 int db = SkGetPackedB32(dst); 574 int da = SkGetPackedA32(dst); 575 int Sr, Sg, Sb; 576 577 if(sa && da) { 578 Sr = sr * da; 579 Sg = sg * da; 580 Sb = sb * da; 581 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 582 } else { 583 Sr = 0; 584 Sg = 0; 585 Sb = 0; 586 } 587 588 int a = srcover_byte(sa, da); 589 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 590 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 591 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 592 return SkPackARGB32(a, r, g, b); 593} 594 595// kLuminosity_Mode 596// B(Cb, Cs) = SetLum(Cb, Lum(Cs)) 597// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color. 598static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { 599 int sr = SkGetPackedR32(src); 600 int sg = SkGetPackedG32(src); 601 int sb = SkGetPackedB32(src); 602 int sa = SkGetPackedA32(src); 603 604 int dr = SkGetPackedR32(dst); 605 int dg = SkGetPackedG32(dst); 606 int db = SkGetPackedB32(dst); 607 int da = SkGetPackedA32(dst); 608 int Dr, Dg, Db; 609 610 if(sa && da) { 611 Dr = dr * sa; 612 Dg = dg * sa; 613 Db = db * sa; 614 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da); 615 } else { 616 Dr = 0; 617 Dg = 0; 618 Db = 0; 619 } 620 621 int a = srcover_byte(sa, da); 622 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 623 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 624 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 625 return SkPackARGB32(a, r, g, b); 626} 627 628const ProcCoeff gProcCoeffs[] = { 629 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, 630 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, 631 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, 632 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, 633 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, 634 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, 635 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, 636 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, 637 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, 638 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, 639 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, 640 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, 641 642 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, 643 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, 644 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, 645 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 646 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 647 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 648 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 649 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 650 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 651 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 652 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 653 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 654 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 655 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 656 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 657 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 658 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 659}; 660 661/////////////////////////////////////////////////////////////////////////////// 662 663bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { 664 return false; 665} 666 667bool SkXfermode::asMode(Mode* mode) const { 668 return false; 669} 670 671bool SkXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef**, Coeff* src, Coeff* dst, GrTexture*) const { 672 return this->asCoeff(src, dst); 673} 674 675bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode, 676 GrContext* context, 677 GrEffectRef** effect, 678 Coeff* src, 679 Coeff* dst, 680 GrTexture* background) { 681 if (NULL == xfermode) { 682 return ModeAsCoeff(kSrcOver_Mode, src, dst); 683 } else { 684 return xfermode->asNewEffectOrCoeff(context, effect, src, dst, background); 685 } 686} 687 688SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ 689 // no-op. subclasses should override this 690 return dst; 691} 692 693void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 694 const SkPMColor* SK_RESTRICT src, int count, 695 const SkAlpha* SK_RESTRICT aa) const { 696 SkASSERT(dst && src && count >= 0); 697 698 if (NULL == aa) { 699 for (int i = count - 1; i >= 0; --i) { 700 dst[i] = this->xferColor(src[i], dst[i]); 701 } 702 } else { 703 for (int i = count - 1; i >= 0; --i) { 704 unsigned a = aa[i]; 705 if (0 != a) { 706 SkPMColor dstC = dst[i]; 707 SkPMColor C = this->xferColor(src[i], dstC); 708 if (0xFF != a) { 709 C = SkFourByteInterp(C, dstC, a); 710 } 711 dst[i] = C; 712 } 713 } 714 } 715} 716 717void SkXfermode::xfer16(uint16_t* dst, 718 const SkPMColor* SK_RESTRICT src, int count, 719 const SkAlpha* SK_RESTRICT aa) const { 720 SkASSERT(dst && src && count >= 0); 721 722 if (NULL == aa) { 723 for (int i = count - 1; i >= 0; --i) { 724 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 725 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 726 } 727 } else { 728 for (int i = count - 1; i >= 0; --i) { 729 unsigned a = aa[i]; 730 if (0 != a) { 731 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 732 SkPMColor C = this->xferColor(src[i], dstC); 733 if (0xFF != a) { 734 C = SkFourByteInterp(C, dstC, a); 735 } 736 dst[i] = SkPixel32ToPixel16_ToU16(C); 737 } 738 } 739 } 740} 741 742void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 743 const SkPMColor src[], int count, 744 const SkAlpha* SK_RESTRICT aa) const { 745 SkASSERT(dst && src && count >= 0); 746 747 if (NULL == aa) { 748 for (int i = count - 1; i >= 0; --i) { 749 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 750 dst[i] = SkToU8(SkGetPackedA32(res)); 751 } 752 } else { 753 for (int i = count - 1; i >= 0; --i) { 754 unsigned a = aa[i]; 755 if (0 != a) { 756 SkAlpha dstA = dst[i]; 757 unsigned A = SkGetPackedA32(this->xferColor(src[i], 758 (SkPMColor)(dstA << SK_A32_SHIFT))); 759 if (0xFF != a) { 760 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 761 } 762 dst[i] = SkToU8(A); 763 } 764 } 765 } 766} 767 768/////////////////////////////////////////////////////////////////////////////// 769 770void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 771 const SkPMColor* SK_RESTRICT src, int count, 772 const SkAlpha* SK_RESTRICT aa) const { 773 SkASSERT(dst && src && count >= 0); 774 775 SkXfermodeProc proc = fProc; 776 777 if (NULL != proc) { 778 if (NULL == aa) { 779 for (int i = count - 1; i >= 0; --i) { 780 dst[i] = proc(src[i], dst[i]); 781 } 782 } else { 783 for (int i = count - 1; i >= 0; --i) { 784 unsigned a = aa[i]; 785 if (0 != a) { 786 SkPMColor dstC = dst[i]; 787 SkPMColor C = proc(src[i], dstC); 788 if (a != 0xFF) { 789 C = SkFourByteInterp(C, dstC, a); 790 } 791 dst[i] = C; 792 } 793 } 794 } 795 } 796} 797 798void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, 799 const SkPMColor* SK_RESTRICT src, int count, 800 const SkAlpha* SK_RESTRICT aa) const { 801 SkASSERT(dst && src && count >= 0); 802 803 SkXfermodeProc proc = fProc; 804 805 if (NULL != proc) { 806 if (NULL == aa) { 807 for (int i = count - 1; i >= 0; --i) { 808 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 809 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 810 } 811 } else { 812 for (int i = count - 1; i >= 0; --i) { 813 unsigned a = aa[i]; 814 if (0 != a) { 815 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 816 SkPMColor C = proc(src[i], dstC); 817 if (0xFF != a) { 818 C = SkFourByteInterp(C, dstC, a); 819 } 820 dst[i] = SkPixel32ToPixel16_ToU16(C); 821 } 822 } 823 } 824 } 825} 826 827void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 828 const SkPMColor* SK_RESTRICT src, int count, 829 const SkAlpha* SK_RESTRICT aa) const { 830 SkASSERT(dst && src && count >= 0); 831 832 SkXfermodeProc proc = fProc; 833 834 if (NULL != proc) { 835 if (NULL == aa) { 836 for (int i = count - 1; i >= 0; --i) { 837 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 838 dst[i] = SkToU8(SkGetPackedA32(res)); 839 } 840 } else { 841 for (int i = count - 1; i >= 0; --i) { 842 unsigned a = aa[i]; 843 if (0 != a) { 844 SkAlpha dstA = dst[i]; 845 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 846 unsigned A = SkGetPackedA32(res); 847 if (0xFF != a) { 848 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 849 } 850 dst[i] = SkToU8(A); 851 } 852 } 853 } 854 } 855} 856 857SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) 858 : SkXfermode(buffer) { 859 fProc = NULL; 860 if (!buffer.isCrossProcess()) { 861 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 862 } 863} 864 865void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { 866 this->INHERITED::flatten(buffer); 867 if (!buffer.isCrossProcess()) { 868 buffer.writeFunctionPtr((void*)fProc); 869 } 870} 871 872#ifdef SK_DEVELOPER 873void SkProcXfermode::toString(SkString* str) const { 874 str->appendf("SkProcXfermode: %p", fProc); 875} 876#endif 877 878////////////////////////////////////////////////////////////////////////////// 879 880#if SK_SUPPORT_GPU 881 882#include "GrEffect.h" 883#include "GrCoordTransform.h" 884#include "GrEffectUnitTest.h" 885#include "GrTBackendEffectFactory.h" 886#include "gl/GrGLEffect.h" 887 888/** 889 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. 890 */ 891class XferEffect : public GrEffect { 892public: 893 static bool IsSupportedMode(SkXfermode::Mode mode) { 894 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; 895 } 896 897 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) { 898 if (!IsSupportedMode(mode)) { 899 return NULL; 900 } else { 901 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background))); 902 return CreateEffectRef(effect); 903 } 904 } 905 906 virtual void getConstantColorComponents(GrColor* color, 907 uint32_t* validFlags) const SK_OVERRIDE { 908 *validFlags = 0; 909 } 910 911 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 912 return GrTBackendEffectFactory<XferEffect>::getInstance(); 913 } 914 915 static const char* Name() { return "XferEffect"; } 916 917 SkXfermode::Mode mode() const { return fMode; } 918 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; } 919 920 class GLEffect : public GrGLEffect { 921 public: 922 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 923 : GrGLEffect(factory) { 924 } 925 virtual void emitCode(GrGLShaderBuilder* builder, 926 const GrDrawEffect& drawEffect, 927 EffectKey key, 928 const char* outputColor, 929 const char* inputColor, 930 const TransformedCoordsArray& coords, 931 const TextureSamplerArray& samplers) SK_OVERRIDE { 932 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode(); 933 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture(); 934 const char* dstColor; 935 if (backgroundTex) { 936 dstColor = "bgColor"; 937 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor); 938 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); 939 builder->fsCodeAppendf(";\n"); 940 } else { 941 dstColor = builder->dstColor(); 942 } 943 SkASSERT(NULL != dstColor); 944 945 // We don't try to optimize for this case at all 946 if (NULL == inputColor) { 947 builder->fsCodeAppendf("\t\tconst vec4 ones = %s;\n", GrGLSLOnesVecf(4)); 948 inputColor = "ones"; 949 } 950 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); 951 952 // These all perform src-over on the alpha channel. 953 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 954 outputColor, inputColor, inputColor, dstColor); 955 956 switch (mode) { 957 case SkXfermode::kOverlay_Mode: 958 // Overlay is Hard-Light with the src and dst reversed 959 HardLight(builder, outputColor, dstColor, inputColor); 960 break; 961 case SkXfermode::kDarken_Mode: 962 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " 963 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 964 outputColor, 965 inputColor, dstColor, inputColor, 966 dstColor, inputColor, dstColor); 967 break; 968 case SkXfermode::kLighten_Mode: 969 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " 970 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 971 outputColor, 972 inputColor, dstColor, inputColor, 973 dstColor, inputColor, dstColor); 974 break; 975 case SkXfermode::kColorDodge_Mode: 976 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); 977 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); 978 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); 979 break; 980 case SkXfermode::kColorBurn_Mode: 981 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); 982 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); 983 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); 984 break; 985 case SkXfermode::kHardLight_Mode: 986 HardLight(builder, outputColor, inputColor, dstColor); 987 break; 988 case SkXfermode::kSoftLight_Mode: 989 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); 990 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); 991 builder->fsCodeAppendf("\t\t} else {\n"); 992 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); 993 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); 994 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); 995 builder->fsCodeAppendf("\t\t}\n"); 996 break; 997 case SkXfermode::kDifference_Mode: 998 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" 999 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", 1000 outputColor, inputColor, dstColor, inputColor, dstColor, 1001 dstColor, inputColor); 1002 break; 1003 case SkXfermode::kExclusion_Mode: 1004 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " 1005 "2.0 * %s.rgb * %s.rgb;\n", 1006 outputColor, dstColor, inputColor, dstColor, inputColor); 1007 break; 1008 case SkXfermode::kMultiply_Mode: 1009 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1010 "(1.0 - %s.a) * %s.rgb + " 1011 "%s.rgb * %s.rgb;\n", 1012 outputColor, inputColor, dstColor, dstColor, inputColor, 1013 inputColor, dstColor); 1014 break; 1015 case SkXfermode::kHue_Mode: { 1016 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S 1017 SkString setSat, setLum; 1018 AddSatFunction(builder, &setSat); 1019 AddLumFunction(builder, &setLum); 1020 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1021 dstColor, inputColor); 1022 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1023 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1024 dstColor); 1025 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1026 outputColor, inputColor, dstColor, dstColor, inputColor); 1027 break; 1028 } 1029 case SkXfermode::kSaturation_Mode: { 1030 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S 1031 SkString setSat, setLum; 1032 AddSatFunction(builder, &setSat); 1033 AddLumFunction(builder, &setLum); 1034 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1035 dstColor, inputColor); 1036 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1037 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1038 dstColor); 1039 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1040 outputColor, inputColor, dstColor, dstColor, inputColor); 1041 break; 1042 } 1043 case SkXfermode::kColor_Mode: { 1044 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S 1045 SkString setLum; 1046 AddLumFunction(builder, &setLum); 1047 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1048 inputColor, dstColor); 1049 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", 1050 outputColor, setLum.c_str(), dstColor, inputColor); 1051 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1052 outputColor, inputColor, dstColor, dstColor, inputColor); 1053 break; 1054 } 1055 case SkXfermode::kLuminosity_Mode: { 1056 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S 1057 SkString setLum; 1058 AddLumFunction(builder, &setLum); 1059 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1060 inputColor, dstColor); 1061 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", 1062 outputColor, setLum.c_str(), dstColor, inputColor); 1063 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1064 outputColor, inputColor, dstColor, dstColor, inputColor); 1065 break; 1066 } 1067 default: 1068 GrCrash("Unknown XferEffect mode."); 1069 break; 1070 } 1071 } 1072 1073 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1074 return drawEffect.castEffect<XferEffect>().mode(); 1075 } 1076 1077 private: 1078 static void HardLight(GrGLShaderBuilder* builder, 1079 const char* final, 1080 const char* src, 1081 const char* dst) { 1082 static const char kComponents[] = {'r', 'g', 'b'}; 1083 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { 1084 char component = kComponents[i]; 1085 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1086 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); 1087 builder->fsCodeAppend("\t\t} else {\n"); 1088 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", 1089 final, component, src, dst, dst, dst, component, src, src, component); 1090 builder->fsCodeAppend("\t\t}\n"); 1091 } 1092 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", 1093 final, src, dst, dst, src); 1094 } 1095 1096 // Does one component of color-dodge 1097 static void ColorDodgeComponent(GrGLShaderBuilder* builder, 1098 const char* final, 1099 const char* src, 1100 const char* dst, 1101 const char component) { 1102 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); 1103 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1104 final, component, src, component, dst); 1105 builder->fsCodeAppend("\t\t} else {\n"); 1106 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); 1107 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); 1108 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", 1109 final, component, src, dst, src, component, dst, dst, component, 1110 src); 1111 builder->fsCodeAppend("\t\t\t} else {\n"); 1112 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", 1113 dst, dst, component, src); 1114 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1115 final, component, src, src, component, dst, dst, component, src); 1116 builder->fsCodeAppend("\t\t\t}\n"); 1117 builder->fsCodeAppend("\t\t}\n"); 1118 } 1119 1120 // Does one component of color-burn 1121 static void ColorBurnComponent(GrGLShaderBuilder* builder, 1122 const char* final, 1123 const char* src, 1124 const char* dst, 1125 const char component) { 1126 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); 1127 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1128 final, component, src, dst, src, component, dst, dst, component, 1129 src); 1130 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); 1131 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1132 final, component, dst, component, src); 1133 builder->fsCodeAppend("\t\t} else {\n"); 1134 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", 1135 dst, dst, dst, component, src, src, component); 1136 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1137 final, component, src, src, component, dst, dst, component, src); 1138 builder->fsCodeAppend("\t\t}\n"); 1139 } 1140 1141 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. 1142 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, 1143 const char* final, 1144 const char* src, 1145 const char* dst, 1146 const char component) { 1147 // if (2S < Sa) 1148 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1149 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) 1150 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", 1151 final, component, dst, component, dst, component, src, src, 1152 component, dst, dst, src, component, dst, component, src, src, 1153 component); 1154 // else if (4D < Da) 1155 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", 1156 dst, component, dst); 1157 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", 1158 dst, component, dst, component); 1159 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); 1160 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); 1161 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); 1162 // (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 1163 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", 1164 final, component, src, component, src, component, dst, component, 1165 src, src, component, dst, src, src, component, src, src, 1166 component); 1167 builder->fsCodeAppendf("\t\t\t} else {\n"); 1168 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1169 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", 1170 final, component, dst, dst, component, src, src, component, dst, 1171 src, component, dst, component, src, src, component, src, 1172 component); 1173 builder->fsCodeAppendf("\t\t\t}\n"); 1174 } 1175 1176 // Adds a function that takes two colors and an alpha as input. It produces a color with the 1177 // hue and saturation of the first color, the luminosity of the second color, and the input 1178 // alpha. It has this signature: 1179 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). 1180 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { 1181 // Emit a helper that gets the luminance of a color. 1182 SkString getFunction; 1183 GrGLShaderVar getLumArgs[] = { 1184 GrGLShaderVar("color", kVec3f_GrSLType), 1185 }; 1186 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); 1187 builder->fsEmitFunction(kFloat_GrSLType, 1188 "luminance", 1189 SK_ARRAY_COUNT(getLumArgs), getLumArgs, 1190 getLumBody.c_str(), 1191 &getFunction); 1192 1193 // Emit the set luminance function. 1194 GrGLShaderVar setLumArgs[] = { 1195 GrGLShaderVar("hueSat", kVec3f_GrSLType), 1196 GrGLShaderVar("alpha", kFloat_GrSLType), 1197 GrGLShaderVar("lumColor", kVec3f_GrSLType), 1198 }; 1199 SkString setLumBody; 1200 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str()); 1201 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); 1202 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str()); 1203 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n" 1204 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n" 1205 "\tif (minComp < 0.0) {\n" 1206 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n" 1207 "\t}\n" 1208 "\tif (maxComp > alpha) {\n" 1209 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" 1210 "\t}\n" 1211 "\treturn outColor;\n"); 1212 builder->fsEmitFunction(kVec3f_GrSLType, 1213 "set_luminance", 1214 SK_ARRAY_COUNT(setLumArgs), setLumArgs, 1215 setLumBody.c_str(), 1216 setLumFunction); 1217 } 1218 1219 // Adds a function that creates a color with the hue and luminosity of one input color and 1220 // the saturation of another color. It will have this signature: 1221 // float set_saturation(vec3 hueLumColor, vec3 satColor) 1222 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { 1223 // Emit a helper that gets the saturation of a color 1224 SkString getFunction; 1225 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; 1226 SkString getSatBody; 1227 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " 1228 "min(min(color.r, color.g), color.b);\n"); 1229 builder->fsEmitFunction(kFloat_GrSLType, 1230 "saturation", 1231 SK_ARRAY_COUNT(getSatArgs), getSatArgs, 1232 getSatBody.c_str(), 1233 &getFunction); 1234 1235 // Emit a helper that sets the saturation given sorted input channels. This used 1236 // to use inout params for min, mid, and max components but that seems to cause 1237 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the 1238 // adjusted min, mid, and max inputs, respectively. 1239 SkString helperFunction; 1240 GrGLShaderVar helperArgs[] = { 1241 GrGLShaderVar("minComp", kFloat_GrSLType), 1242 GrGLShaderVar("midComp", kFloat_GrSLType), 1243 GrGLShaderVar("maxComp", kFloat_GrSLType), 1244 GrGLShaderVar("sat", kFloat_GrSLType), 1245 }; 1246 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n" 1247 "\t\tvec3 result;\n" 1248 "\t\tresult.r = 0.0;\n" 1249 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n" 1250 "\t\tresult.b = sat;\n" 1251 "\t\treturn result;\n" 1252 "\t} else {\n" 1253 "\t\treturn vec3(0, 0, 0);\n" 1254 "\t}\n"; 1255 builder->fsEmitFunction(kVec3f_GrSLType, 1256 "set_saturation_helper", 1257 SK_ARRAY_COUNT(helperArgs), helperArgs, 1258 kHelperBody, 1259 &helperFunction); 1260 1261 GrGLShaderVar setSatArgs[] = { 1262 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), 1263 GrGLShaderVar("satColor", kVec3f_GrSLType), 1264 }; 1265 const char* helpFunc = helperFunction.c_str(); 1266 SkString setSatBody; 1267 setSatBody.appendf("\tfloat sat = %s(satColor);\n" 1268 "\tif (hueLumColor.r <= hueLumColor.g) {\n" 1269 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" 1270 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n" 1271 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1272 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n" 1273 "\t\t} else {\n" 1274 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n" 1275 "\t\t}\n" 1276 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1277 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n" 1278 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n" 1279 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n" 1280 "\t} else {\n" 1281 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n" 1282 "\t}\n" 1283 "\treturn hueLumColor;\n", 1284 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, 1285 helpFunc, helpFunc); 1286 builder->fsEmitFunction(kVec3f_GrSLType, 1287 "set_saturation", 1288 SK_ARRAY_COUNT(setSatArgs), setSatArgs, 1289 setSatBody.c_str(), 1290 setSatFunction); 1291 1292 } 1293 1294 typedef GrGLEffect INHERITED; 1295 }; 1296 1297 GR_DECLARE_EFFECT_TEST; 1298 1299private: 1300 XferEffect(SkXfermode::Mode mode, GrTexture* background) 1301 : fMode(mode) { 1302 if (background) { 1303 fBackgroundTransform.reset(kLocal_GrCoordSet, background); 1304 this->addCoordTransform(&fBackgroundTransform); 1305 fBackgroundAccess.reset(background); 1306 this->addTextureAccess(&fBackgroundAccess); 1307 } else { 1308 this->setWillReadDstColor(); 1309 } 1310 } 1311 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 1312 const XferEffect& s = CastEffect<XferEffect>(other); 1313 return fMode == s.fMode && 1314 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture(); 1315 } 1316 1317 SkXfermode::Mode fMode; 1318 GrCoordTransform fBackgroundTransform; 1319 GrTextureAccess fBackgroundAccess; 1320 1321 typedef GrEffect INHERITED; 1322}; 1323 1324GR_DEFINE_EFFECT_TEST(XferEffect); 1325GrEffectRef* XferEffect::TestCreate(SkRandom* rand, 1326 GrContext*, 1327 const GrDrawTargetCaps&, 1328 GrTexture*[]) { 1329 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); 1330 1331 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL))); 1332 return CreateEffectRef(gEffect); 1333} 1334 1335#endif 1336 1337/////////////////////////////////////////////////////////////////////////////// 1338/////////////////////////////////////////////////////////////////////////////// 1339 1340bool SkProcCoeffXfermode::asMode(Mode* mode) const { 1341 if (mode) { 1342 *mode = fMode; 1343 } 1344 return true; 1345} 1346 1347bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const { 1348 if (CANNOT_USE_COEFF == fSrcCoeff) { 1349 return false; 1350 } 1351 1352 if (sc) { 1353 *sc = fSrcCoeff; 1354 } 1355 if (dc) { 1356 *dc = fDstCoeff; 1357 } 1358 return true; 1359} 1360 1361#if SK_SUPPORT_GPU 1362bool SkProcCoeffXfermode::asNewEffectOrCoeff(GrContext*, 1363 GrEffectRef** effect, 1364 Coeff* src, 1365 Coeff* dst, 1366 GrTexture* background) const { 1367 if (this->asCoeff(src, dst)) { 1368 return true; 1369 } 1370 if (XferEffect::IsSupportedMode(fMode)) { 1371 if (NULL != effect) { 1372 *effect = XferEffect::Create(fMode, background); 1373 SkASSERT(NULL != *effect); 1374 } 1375 return true; 1376 } 1377 return false; 1378} 1379#endif 1380 1381void SkProcCoeffXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { 1382 this->INHERITED::flatten(buffer); 1383 buffer.write32(fMode); 1384} 1385 1386const char* SkXfermode::ModeName(Mode mode) { 1387 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1388 const char* gModeStrings[] = { 1389 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1390 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1391 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1392 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1393 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1394 }; 1395 return gModeStrings[mode]; 1396 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1397} 1398 1399#ifdef SK_DEVELOPER 1400void SkProcCoeffXfermode::toString(SkString* str) const { 1401 str->append("SkProcCoeffXfermode: "); 1402 1403 str->append("mode: "); 1404 str->append(ModeName(fMode)); 1405 1406 static const char* gCoeffStrings[kCoeffCount] = { 1407 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1408 }; 1409 1410 str->append(" src: "); 1411 if (CANNOT_USE_COEFF == fSrcCoeff) { 1412 str->append("can't use"); 1413 } else { 1414 str->append(gCoeffStrings[fSrcCoeff]); 1415 } 1416 1417 str->append(" dst: "); 1418 if (CANNOT_USE_COEFF == fDstCoeff) { 1419 str->append("can't use"); 1420 } else { 1421 str->append(gCoeffStrings[fDstCoeff]); 1422 } 1423} 1424#endif 1425 1426/////////////////////////////////////////////////////////////////////////////// 1427 1428class SkClearXfermode : public SkProcCoeffXfermode { 1429public: 1430 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1431 1432 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1433 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1434 1435 SK_DEVELOPER_TO_STRING() 1436 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1437 1438private: 1439 SkClearXfermode(SkFlattenableReadBuffer& buffer) 1440 : SkProcCoeffXfermode(buffer) {} 1441 1442 typedef SkProcCoeffXfermode INHERITED; 1443}; 1444 1445void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1446 const SkPMColor* SK_RESTRICT, int count, 1447 const SkAlpha* SK_RESTRICT aa) const { 1448 SkASSERT(dst && count >= 0); 1449 1450 if (NULL == aa) { 1451 memset(dst, 0, count << 2); 1452 } else { 1453 for (int i = count - 1; i >= 0; --i) { 1454 unsigned a = aa[i]; 1455 if (0xFF == a) { 1456 dst[i] = 0; 1457 } else if (a != 0) { 1458 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1459 } 1460 } 1461 } 1462} 1463void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1464 const SkPMColor* SK_RESTRICT, int count, 1465 const SkAlpha* SK_RESTRICT aa) const { 1466 SkASSERT(dst && count >= 0); 1467 1468 if (NULL == aa) { 1469 memset(dst, 0, count); 1470 } else { 1471 for (int i = count - 1; i >= 0; --i) { 1472 unsigned a = aa[i]; 1473 if (0xFF == a) { 1474 dst[i] = 0; 1475 } else if (0 != a) { 1476 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1477 } 1478 } 1479 } 1480} 1481 1482#ifdef SK_DEVELOPER 1483void SkClearXfermode::toString(SkString* str) const { 1484 this->INHERITED::toString(str); 1485} 1486#endif 1487 1488/////////////////////////////////////////////////////////////////////////////// 1489 1490class SkSrcXfermode : public SkProcCoeffXfermode { 1491public: 1492 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1493 1494 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1495 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1496 1497 SK_DEVELOPER_TO_STRING() 1498 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1499 1500private: 1501 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 1502 : SkProcCoeffXfermode(buffer) {} 1503 1504 typedef SkProcCoeffXfermode INHERITED; 1505}; 1506 1507void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1508 const SkPMColor* SK_RESTRICT src, int count, 1509 const SkAlpha* SK_RESTRICT aa) const { 1510 SkASSERT(dst && src && count >= 0); 1511 1512 if (NULL == aa) { 1513 memcpy(dst, src, count << 2); 1514 } else { 1515 for (int i = count - 1; i >= 0; --i) { 1516 unsigned a = aa[i]; 1517 if (a == 0xFF) { 1518 dst[i] = src[i]; 1519 } else if (a != 0) { 1520 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1521 } 1522 } 1523 } 1524} 1525 1526void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1527 const SkPMColor* SK_RESTRICT src, int count, 1528 const SkAlpha* SK_RESTRICT aa) const { 1529 SkASSERT(dst && src && count >= 0); 1530 1531 if (NULL == aa) { 1532 for (int i = count - 1; i >= 0; --i) { 1533 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1534 } 1535 } else { 1536 for (int i = count - 1; i >= 0; --i) { 1537 unsigned a = aa[i]; 1538 if (0 != a) { 1539 unsigned srcA = SkGetPackedA32(src[i]); 1540 if (a == 0xFF) { 1541 dst[i] = SkToU8(srcA); 1542 } else { 1543 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1544 } 1545 } 1546 } 1547 } 1548} 1549#ifdef SK_DEVELOPER 1550void SkSrcXfermode::toString(SkString* str) const { 1551 this->INHERITED::toString(str); 1552} 1553#endif 1554 1555/////////////////////////////////////////////////////////////////////////////// 1556 1557class SkDstInXfermode : public SkProcCoeffXfermode { 1558public: 1559 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1560 1561 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1562 1563 SK_DEVELOPER_TO_STRING() 1564 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1565 1566private: 1567 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 1568 1569 typedef SkProcCoeffXfermode INHERITED; 1570}; 1571 1572void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1573 const SkPMColor* SK_RESTRICT src, int count, 1574 const SkAlpha* SK_RESTRICT aa) const { 1575 SkASSERT(dst && src); 1576 1577 if (count <= 0) { 1578 return; 1579 } 1580 if (NULL != aa) { 1581 return this->INHERITED::xfer32(dst, src, count, aa); 1582 } 1583 1584 do { 1585 unsigned a = SkGetPackedA32(*src); 1586 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1587 dst++; 1588 src++; 1589 } while (--count != 0); 1590} 1591 1592#ifdef SK_DEVELOPER 1593void SkDstInXfermode::toString(SkString* str) const { 1594 this->INHERITED::toString(str); 1595} 1596#endif 1597 1598/////////////////////////////////////////////////////////////////////////////// 1599 1600class SkDstOutXfermode : public SkProcCoeffXfermode { 1601public: 1602 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1603 1604 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1605 1606 SK_DEVELOPER_TO_STRING() 1607 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1608 1609private: 1610 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 1611 : INHERITED(buffer) {} 1612 1613 typedef SkProcCoeffXfermode INHERITED; 1614}; 1615 1616void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1617 const SkPMColor* SK_RESTRICT src, int count, 1618 const SkAlpha* SK_RESTRICT aa) const { 1619 SkASSERT(dst && src); 1620 1621 if (count <= 0) { 1622 return; 1623 } 1624 if (NULL != aa) { 1625 return this->INHERITED::xfer32(dst, src, count, aa); 1626 } 1627 1628 do { 1629 unsigned a = SkGetPackedA32(*src); 1630 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1631 dst++; 1632 src++; 1633 } while (--count != 0); 1634} 1635 1636#ifdef SK_DEVELOPER 1637void SkDstOutXfermode::toString(SkString* str) const { 1638 this->INHERITED::toString(str); 1639} 1640#endif 1641 1642/////////////////////////////////////////////////////////////////////////////// 1643 1644SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); 1645static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; 1646 1647void SkXfermode::Term() { 1648 SkAutoMutexAcquire ac(gCachedXfermodesMutex); 1649 1650 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) { 1651 SkSafeUnref(gCachedXfermodes[i]); 1652 gCachedXfermodes[i] = NULL; 1653 } 1654} 1655 1656extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, 1657 SkXfermode::Mode mode); 1658 1659SkXfermode* SkXfermode::Create(Mode mode) { 1660 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1661 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); 1662 1663 if ((unsigned)mode >= kModeCount) { 1664 // report error 1665 return NULL; 1666 } 1667 1668 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover 1669 // so we can just return NULL from the factory. 1670 if (kSrcOver_Mode == mode) { 1671 return NULL; 1672 } 1673 1674 // guard our access to gCachedXfermodes, since we may write into it 1675 SkAutoMutexAcquire ac(gCachedXfermodesMutex); 1676 1677 SkXfermode* xfer = gCachedXfermodes[mode]; 1678 if (NULL == xfer) { 1679 const ProcCoeff& rec = gProcCoeffs[mode]; 1680 1681 // check if we have a platform optim for that 1682 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); 1683 if (xfm != NULL) { 1684 xfer = xfm; 1685 } else { 1686 // All modes can in theory be represented by the ProcCoeff rec, since 1687 // it contains function ptrs. However, a few modes are both simple and 1688 // commonly used, so we call those out for their own subclasses here. 1689 switch (mode) { 1690 case kClear_Mode: 1691 xfer = SkNEW_ARGS(SkClearXfermode, (rec)); 1692 break; 1693 case kSrc_Mode: 1694 xfer = SkNEW_ARGS(SkSrcXfermode, (rec)); 1695 break; 1696 case kSrcOver_Mode: 1697 SkASSERT(false); // should not land here 1698 break; 1699 case kDstIn_Mode: 1700 xfer = SkNEW_ARGS(SkDstInXfermode, (rec)); 1701 break; 1702 case kDstOut_Mode: 1703 xfer = SkNEW_ARGS(SkDstOutXfermode, (rec)); 1704 break; 1705 default: 1706 // no special-case, just rely in the rec and its function-ptrs 1707 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 1708 break; 1709 } 1710 } 1711 gCachedXfermodes[mode] = xfer; 1712 } 1713 return SkSafeRef(xfer); 1714} 1715 1716SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1717 SkXfermodeProc proc = NULL; 1718 if ((unsigned)mode < kModeCount) { 1719 proc = gProcCoeffs[mode].fProc; 1720 } 1721 return proc; 1722} 1723 1724bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1725 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1726 1727 if ((unsigned)mode >= (unsigned)kModeCount) { 1728 // illegal mode parameter 1729 return false; 1730 } 1731 1732 const ProcCoeff& rec = gProcCoeffs[mode]; 1733 1734 if (CANNOT_USE_COEFF == rec.fSC) { 1735 return false; 1736 } 1737 1738 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1739 if (src) { 1740 *src = rec.fSC; 1741 } 1742 if (dst) { 1743 *dst = rec.fDC; 1744 } 1745 return true; 1746} 1747 1748bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1749 if (NULL == xfer) { 1750 if (mode) { 1751 *mode = kSrcOver_Mode; 1752 } 1753 return true; 1754 } 1755 return xfer->asMode(mode); 1756} 1757 1758bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1759 if (NULL == xfer) { 1760 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1761 } 1762 return xfer->asCoeff(src, dst); 1763} 1764 1765bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1766 // if xfer==null then the mode is srcover 1767 Mode m = kSrcOver_Mode; 1768 if (xfer && !xfer->asMode(&m)) { 1769 return false; 1770 } 1771 return mode == m; 1772} 1773 1774/////////////////////////////////////////////////////////////////////////////// 1775//////////// 16bit xfermode procs 1776 1777#ifdef SK_DEBUG 1778static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1779static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1780#endif 1781 1782static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1783 SkASSERT(require_255(src)); 1784 return SkPixel32ToPixel16(src); 1785} 1786 1787static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1788 return dst; 1789} 1790 1791static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1792 SkASSERT(require_0(src)); 1793 return dst; 1794} 1795 1796static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1797 SkASSERT(require_255(src)); 1798 return SkPixel32ToPixel16(src); 1799} 1800 1801static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1802 SkASSERT(require_0(src)); 1803 return dst; 1804} 1805 1806static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1807 SkASSERT(require_255(src)); 1808 return dst; 1809} 1810 1811static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1812 SkASSERT(require_255(src)); 1813 return SkPixel32ToPixel16(src); 1814} 1815 1816static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1817 SkASSERT(require_255(src)); 1818 return dst; 1819} 1820 1821static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1822 SkASSERT(require_0(src)); 1823 return dst; 1824} 1825 1826static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1827 unsigned isa = 255 - SkGetPackedA32(src); 1828 1829 return SkPackRGB16( 1830 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1831 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1832 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1833} 1834 1835static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1836 SkASSERT(require_0(src)); 1837 return dst; 1838} 1839 1840static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1841 SkASSERT(require_255(src)); 1842 return SkPixel32ToPixel16(src); 1843} 1844 1845static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1846 SkASSERT(require_255(src)); 1847 return dst; 1848} 1849 1850/********* 1851 darken and lighten boil down to this. 1852 1853 darken = (1 - Sa) * Dc + min(Sc, Dc) 1854 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1855 1856 if (Sa == 0) these become 1857 darken = Dc + min(0, Dc) = 0 1858 lighten = Dc + max(0, Dc) = Dc 1859 1860 if (Sa == 1) these become 1861 darken = min(Sc, Dc) 1862 lighten = max(Sc, Dc) 1863*/ 1864 1865static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1866 SkASSERT(require_0(src)); 1867 return 0; 1868} 1869 1870static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1871 SkASSERT(require_255(src)); 1872 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1873 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1874 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1875 return SkPackRGB16(r, g, b); 1876} 1877 1878static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1879 SkASSERT(require_0(src)); 1880 return dst; 1881} 1882 1883static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1884 SkASSERT(require_255(src)); 1885 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1886 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1887 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1888 return SkPackRGB16(r, g, b); 1889} 1890 1891struct Proc16Rec { 1892 SkXfermodeProc16 fProc16_0; 1893 SkXfermodeProc16 fProc16_255; 1894 SkXfermodeProc16 fProc16_General; 1895}; 1896 1897static const Proc16Rec gModeProcs16[] = { 1898 { NULL, NULL, NULL }, // CLEAR 1899 { NULL, src_modeproc16_255, NULL }, 1900 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1901 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1902 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1903 { NULL, srcin_modeproc16_255, NULL }, 1904 { NULL, dstin_modeproc16_255, NULL }, 1905 { NULL, NULL, NULL },// SRC_OUT 1906 { dstout_modeproc16_0, NULL, NULL }, 1907 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1908 { NULL, dstatop_modeproc16_255, NULL }, 1909 { NULL, NULL, NULL }, // XOR 1910 1911 { NULL, NULL, NULL }, // plus 1912 { NULL, NULL, NULL }, // modulate 1913 { NULL, NULL, NULL }, // screen 1914 { NULL, NULL, NULL }, // overlay 1915 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1916 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1917 { NULL, NULL, NULL }, // colordodge 1918 { NULL, NULL, NULL }, // colorburn 1919 { NULL, NULL, NULL }, // hardlight 1920 { NULL, NULL, NULL }, // softlight 1921 { NULL, NULL, NULL }, // difference 1922 { NULL, NULL, NULL }, // exclusion 1923 { NULL, NULL, NULL }, // multiply 1924 { NULL, NULL, NULL }, // hue 1925 { NULL, NULL, NULL }, // saturation 1926 { NULL, NULL, NULL }, // color 1927 { NULL, NULL, NULL }, // luminosity 1928}; 1929 1930SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1931 SkXfermodeProc16 proc16 = NULL; 1932 if ((unsigned)mode < kModeCount) { 1933 const Proc16Rec& rec = gModeProcs16[mode]; 1934 unsigned a = SkColorGetA(srcColor); 1935 1936 if (0 == a) { 1937 proc16 = rec.fProc16_0; 1938 } else if (255 == a) { 1939 proc16 = rec.fProc16_255; 1940 } else { 1941 proc16 = rec.fProc16_General; 1942 } 1943 } 1944 return proc16; 1945} 1946 1947SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1948 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1949 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1950 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1951 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1952 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1953SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1954