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