SkXfermode.cpp revision 372a9c3f443bdcc60b0e0c17f028461eaaed5fd1
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 "SkMathPriv.h" 14#include "SkOnce.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::asNewEffect(GrEffectRef** effect, GrTexture* background) const { 679 return false; 680} 681 682bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode, 683 GrEffectRef** effect, 684 Coeff* src, 685 Coeff* dst, 686 GrTexture* background) { 687 if (NULL == xfermode) { 688 return ModeAsCoeff(kSrcOver_Mode, src, dst); 689 } else if (xfermode->asCoeff(src, dst)) { 690 return true; 691 } else { 692 return xfermode->asNewEffect(effect, background); 693 } 694} 695 696SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ 697 // no-op. subclasses should override this 698 return dst; 699} 700 701void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 702 const SkPMColor* SK_RESTRICT src, int count, 703 const SkAlpha* SK_RESTRICT aa) const { 704 SkASSERT(dst && src && count >= 0); 705 706 if (NULL == aa) { 707 for (int i = count - 1; i >= 0; --i) { 708 dst[i] = this->xferColor(src[i], dst[i]); 709 } 710 } else { 711 for (int i = count - 1; i >= 0; --i) { 712 unsigned a = aa[i]; 713 if (0 != a) { 714 SkPMColor dstC = dst[i]; 715 SkPMColor C = this->xferColor(src[i], dstC); 716 if (0xFF != a) { 717 C = SkFourByteInterp(C, dstC, a); 718 } 719 dst[i] = C; 720 } 721 } 722 } 723} 724 725void SkXfermode::xfer16(uint16_t* dst, 726 const SkPMColor* SK_RESTRICT src, int count, 727 const SkAlpha* SK_RESTRICT aa) const { 728 SkASSERT(dst && src && count >= 0); 729 730 if (NULL == aa) { 731 for (int i = count - 1; i >= 0; --i) { 732 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 733 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 734 } 735 } else { 736 for (int i = count - 1; i >= 0; --i) { 737 unsigned a = aa[i]; 738 if (0 != a) { 739 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 740 SkPMColor C = this->xferColor(src[i], dstC); 741 if (0xFF != a) { 742 C = SkFourByteInterp(C, dstC, a); 743 } 744 dst[i] = SkPixel32ToPixel16_ToU16(C); 745 } 746 } 747 } 748} 749 750void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 751 const SkPMColor src[], int count, 752 const SkAlpha* SK_RESTRICT aa) const { 753 SkASSERT(dst && src && count >= 0); 754 755 if (NULL == aa) { 756 for (int i = count - 1; i >= 0; --i) { 757 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 758 dst[i] = SkToU8(SkGetPackedA32(res)); 759 } 760 } else { 761 for (int i = count - 1; i >= 0; --i) { 762 unsigned a = aa[i]; 763 if (0 != a) { 764 SkAlpha dstA = dst[i]; 765 unsigned A = SkGetPackedA32(this->xferColor(src[i], 766 (SkPMColor)(dstA << SK_A32_SHIFT))); 767 if (0xFF != a) { 768 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 769 } 770 dst[i] = SkToU8(A); 771 } 772 } 773 } 774} 775 776/////////////////////////////////////////////////////////////////////////////// 777 778void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 779 const SkPMColor* SK_RESTRICT src, int count, 780 const SkAlpha* SK_RESTRICT aa) const { 781 SkASSERT(dst && src && count >= 0); 782 783 SkXfermodeProc proc = fProc; 784 785 if (NULL != proc) { 786 if (NULL == aa) { 787 for (int i = count - 1; i >= 0; --i) { 788 dst[i] = proc(src[i], dst[i]); 789 } 790 } else { 791 for (int i = count - 1; i >= 0; --i) { 792 unsigned a = aa[i]; 793 if (0 != a) { 794 SkPMColor dstC = dst[i]; 795 SkPMColor C = proc(src[i], dstC); 796 if (a != 0xFF) { 797 C = SkFourByteInterp(C, dstC, a); 798 } 799 dst[i] = C; 800 } 801 } 802 } 803 } 804} 805 806void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, 807 const SkPMColor* SK_RESTRICT src, int count, 808 const SkAlpha* SK_RESTRICT aa) const { 809 SkASSERT(dst && src && count >= 0); 810 811 SkXfermodeProc proc = fProc; 812 813 if (NULL != proc) { 814 if (NULL == aa) { 815 for (int i = count - 1; i >= 0; --i) { 816 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 817 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 818 } 819 } else { 820 for (int i = count - 1; i >= 0; --i) { 821 unsigned a = aa[i]; 822 if (0 != a) { 823 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 824 SkPMColor C = proc(src[i], dstC); 825 if (0xFF != a) { 826 C = SkFourByteInterp(C, dstC, a); 827 } 828 dst[i] = SkPixel32ToPixel16_ToU16(C); 829 } 830 } 831 } 832 } 833} 834 835void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 836 const SkPMColor* SK_RESTRICT src, int count, 837 const SkAlpha* SK_RESTRICT aa) const { 838 SkASSERT(dst && src && count >= 0); 839 840 SkXfermodeProc proc = fProc; 841 842 if (NULL != proc) { 843 if (NULL == aa) { 844 for (int i = count - 1; i >= 0; --i) { 845 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 846 dst[i] = SkToU8(SkGetPackedA32(res)); 847 } 848 } else { 849 for (int i = count - 1; i >= 0; --i) { 850 unsigned a = aa[i]; 851 if (0 != a) { 852 SkAlpha dstA = dst[i]; 853 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 854 unsigned A = SkGetPackedA32(res); 855 if (0xFF != a) { 856 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 857 } 858 dst[i] = SkToU8(A); 859 } 860 } 861 } 862 } 863} 864 865SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer) 866 : SkXfermode(buffer) { 867 fProc = NULL; 868 if (!buffer.isCrossProcess()) { 869 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 870 } 871} 872 873void SkProcXfermode::flatten(SkWriteBuffer& buffer) const { 874 this->INHERITED::flatten(buffer); 875 if (!buffer.isCrossProcess()) { 876 buffer.writeFunctionPtr((void*)fProc); 877 } 878} 879 880#ifndef SK_IGNORE_TO_STRING 881void SkProcXfermode::toString(SkString* str) const { 882 str->appendf("SkProcXfermode: %p", fProc); 883} 884#endif 885 886////////////////////////////////////////////////////////////////////////////// 887 888#if SK_SUPPORT_GPU 889 890#include "GrEffect.h" 891#include "GrCoordTransform.h" 892#include "GrEffectUnitTest.h" 893#include "GrTBackendEffectFactory.h" 894#include "gl/GrGLEffect.h" 895 896/** 897 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. 898 */ 899class XferEffect : public GrEffect { 900public: 901 static bool IsSupportedMode(SkXfermode::Mode mode) { 902 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; 903 } 904 905 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) { 906 if (!IsSupportedMode(mode)) { 907 return NULL; 908 } else { 909 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background))); 910 return CreateEffectRef(effect); 911 } 912 } 913 914 virtual void getConstantColorComponents(GrColor* color, 915 uint32_t* validFlags) const SK_OVERRIDE { 916 *validFlags = 0; 917 } 918 919 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 920 return GrTBackendEffectFactory<XferEffect>::getInstance(); 921 } 922 923 static const char* Name() { return "XferEffect"; } 924 925 SkXfermode::Mode mode() const { return fMode; } 926 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; } 927 928 class GLEffect : public GrGLEffect { 929 public: 930 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 931 : GrGLEffect(factory) { 932 } 933 virtual void emitCode(GrGLShaderBuilder* builder, 934 const GrDrawEffect& drawEffect, 935 EffectKey key, 936 const char* outputColor, 937 const char* inputColor, 938 const TransformedCoordsArray& coords, 939 const TextureSamplerArray& samplers) SK_OVERRIDE { 940 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode(); 941 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture(); 942 const char* dstColor; 943 if (backgroundTex) { 944 dstColor = "bgColor"; 945 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor); 946 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); 947 builder->fsCodeAppendf(";\n"); 948 } else { 949 dstColor = builder->dstColor(); 950 } 951 SkASSERT(NULL != dstColor); 952 953 // We don't try to optimize for this case at all 954 if (NULL == inputColor) { 955 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n"); 956 inputColor = "ones"; 957 } 958 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); 959 960 // These all perform src-over on the alpha channel. 961 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 962 outputColor, inputColor, inputColor, dstColor); 963 964 switch (mode) { 965 case SkXfermode::kOverlay_Mode: 966 // Overlay is Hard-Light with the src and dst reversed 967 HardLight(builder, outputColor, dstColor, inputColor); 968 break; 969 case SkXfermode::kDarken_Mode: 970 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " 971 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 972 outputColor, 973 inputColor, dstColor, inputColor, 974 dstColor, inputColor, dstColor); 975 break; 976 case SkXfermode::kLighten_Mode: 977 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " 978 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 979 outputColor, 980 inputColor, dstColor, inputColor, 981 dstColor, inputColor, dstColor); 982 break; 983 case SkXfermode::kColorDodge_Mode: 984 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); 985 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); 986 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); 987 break; 988 case SkXfermode::kColorBurn_Mode: 989 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); 990 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); 991 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); 992 break; 993 case SkXfermode::kHardLight_Mode: 994 HardLight(builder, outputColor, inputColor, dstColor); 995 break; 996 case SkXfermode::kSoftLight_Mode: 997 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); 998 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); 999 builder->fsCodeAppendf("\t\t} else {\n"); 1000 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); 1001 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); 1002 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); 1003 builder->fsCodeAppendf("\t\t}\n"); 1004 break; 1005 case SkXfermode::kDifference_Mode: 1006 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" 1007 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", 1008 outputColor, inputColor, dstColor, inputColor, dstColor, 1009 dstColor, inputColor); 1010 break; 1011 case SkXfermode::kExclusion_Mode: 1012 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " 1013 "2.0 * %s.rgb * %s.rgb;\n", 1014 outputColor, dstColor, inputColor, dstColor, inputColor); 1015 break; 1016 case SkXfermode::kMultiply_Mode: 1017 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1018 "(1.0 - %s.a) * %s.rgb + " 1019 "%s.rgb * %s.rgb;\n", 1020 outputColor, inputColor, dstColor, dstColor, inputColor, 1021 inputColor, dstColor); 1022 break; 1023 case SkXfermode::kHue_Mode: { 1024 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S 1025 SkString setSat, setLum; 1026 AddSatFunction(builder, &setSat); 1027 AddLumFunction(builder, &setLum); 1028 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1029 dstColor, inputColor); 1030 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1031 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1032 dstColor); 1033 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1034 outputColor, inputColor, dstColor, dstColor, inputColor); 1035 break; 1036 } 1037 case SkXfermode::kSaturation_Mode: { 1038 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S 1039 SkString setSat, setLum; 1040 AddSatFunction(builder, &setSat); 1041 AddLumFunction(builder, &setLum); 1042 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1043 dstColor, inputColor); 1044 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1045 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1046 dstColor); 1047 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1048 outputColor, inputColor, dstColor, dstColor, inputColor); 1049 break; 1050 } 1051 case SkXfermode::kColor_Mode: { 1052 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S 1053 SkString setLum; 1054 AddLumFunction(builder, &setLum); 1055 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1056 inputColor, dstColor); 1057 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", 1058 outputColor, setLum.c_str(), dstColor, inputColor); 1059 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1060 outputColor, inputColor, dstColor, dstColor, inputColor); 1061 break; 1062 } 1063 case SkXfermode::kLuminosity_Mode: { 1064 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S 1065 SkString setLum; 1066 AddLumFunction(builder, &setLum); 1067 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1068 inputColor, dstColor); 1069 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", 1070 outputColor, setLum.c_str(), dstColor, inputColor); 1071 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1072 outputColor, inputColor, dstColor, dstColor, inputColor); 1073 break; 1074 } 1075 default: 1076 GrCrash("Unknown XferEffect mode."); 1077 break; 1078 } 1079 } 1080 1081 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1082 // The background may come from the dst or from a texture. 1083 int numTextures = (*drawEffect.effect())->numTextures(); 1084 SkASSERT(numTextures <= 1); 1085 return (drawEffect.castEffect<XferEffect>().mode() << 1) | numTextures; 1086 } 1087 1088 private: 1089 static void HardLight(GrGLShaderBuilder* builder, 1090 const char* final, 1091 const char* src, 1092 const char* dst) { 1093 static const char kComponents[] = {'r', 'g', 'b'}; 1094 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { 1095 char component = kComponents[i]; 1096 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1097 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); 1098 builder->fsCodeAppend("\t\t} else {\n"); 1099 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", 1100 final, component, src, dst, dst, dst, component, src, src, component); 1101 builder->fsCodeAppend("\t\t}\n"); 1102 } 1103 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", 1104 final, src, dst, dst, src); 1105 } 1106 1107 // Does one component of color-dodge 1108 static void ColorDodgeComponent(GrGLShaderBuilder* builder, 1109 const char* final, 1110 const char* src, 1111 const char* dst, 1112 const char component) { 1113 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); 1114 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1115 final, component, src, component, dst); 1116 builder->fsCodeAppend("\t\t} else {\n"); 1117 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); 1118 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); 1119 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", 1120 final, component, src, dst, src, component, dst, dst, component, 1121 src); 1122 builder->fsCodeAppend("\t\t\t} else {\n"); 1123 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", 1124 dst, dst, component, src); 1125 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1126 final, component, src, src, component, dst, dst, component, src); 1127 builder->fsCodeAppend("\t\t\t}\n"); 1128 builder->fsCodeAppend("\t\t}\n"); 1129 } 1130 1131 // Does one component of color-burn 1132 static void ColorBurnComponent(GrGLShaderBuilder* builder, 1133 const char* final, 1134 const char* src, 1135 const char* dst, 1136 const char component) { 1137 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); 1138 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1139 final, component, src, dst, src, component, dst, dst, component, 1140 src); 1141 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); 1142 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1143 final, component, dst, component, src); 1144 builder->fsCodeAppend("\t\t} else {\n"); 1145 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", 1146 dst, dst, dst, component, src, src, component); 1147 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1148 final, component, src, src, component, dst, dst, component, src); 1149 builder->fsCodeAppend("\t\t}\n"); 1150 } 1151 1152 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. 1153 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, 1154 const char* final, 1155 const char* src, 1156 const char* dst, 1157 const char component) { 1158 // if (2S < Sa) 1159 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1160 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) 1161 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", 1162 final, component, dst, component, dst, component, src, src, 1163 component, dst, dst, src, component, dst, component, src, src, 1164 component); 1165 // else if (4D < Da) 1166 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", 1167 dst, component, dst); 1168 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", 1169 dst, component, dst, component); 1170 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); 1171 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); 1172 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); 1173 // (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 1174 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", 1175 final, component, src, component, src, component, dst, component, 1176 src, src, component, dst, src, src, component, src, src, 1177 component); 1178 builder->fsCodeAppendf("\t\t\t} else {\n"); 1179 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1180 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", 1181 final, component, dst, dst, component, src, src, component, dst, 1182 src, component, dst, component, src, src, component, src, 1183 component); 1184 builder->fsCodeAppendf("\t\t\t}\n"); 1185 } 1186 1187 // Adds a function that takes two colors and an alpha as input. It produces a color with the 1188 // hue and saturation of the first color, the luminosity of the second color, and the input 1189 // alpha. It has this signature: 1190 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). 1191 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { 1192 // Emit a helper that gets the luminance of a color. 1193 SkString getFunction; 1194 GrGLShaderVar getLumArgs[] = { 1195 GrGLShaderVar("color", kVec3f_GrSLType), 1196 }; 1197 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); 1198 builder->fsEmitFunction(kFloat_GrSLType, 1199 "luminance", 1200 SK_ARRAY_COUNT(getLumArgs), getLumArgs, 1201 getLumBody.c_str(), 1202 &getFunction); 1203 1204 // Emit the set luminance function. 1205 GrGLShaderVar setLumArgs[] = { 1206 GrGLShaderVar("hueSat", kVec3f_GrSLType), 1207 GrGLShaderVar("alpha", kFloat_GrSLType), 1208 GrGLShaderVar("lumColor", kVec3f_GrSLType), 1209 }; 1210 SkString setLumBody; 1211 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str()); 1212 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); 1213 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str()); 1214 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n" 1215 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n" 1216 "\tif (minComp < 0.0) {\n" 1217 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n" 1218 "\t}\n" 1219 "\tif (maxComp > alpha) {\n" 1220 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" 1221 "\t}\n" 1222 "\treturn outColor;\n"); 1223 builder->fsEmitFunction(kVec3f_GrSLType, 1224 "set_luminance", 1225 SK_ARRAY_COUNT(setLumArgs), setLumArgs, 1226 setLumBody.c_str(), 1227 setLumFunction); 1228 } 1229 1230 // Adds a function that creates a color with the hue and luminosity of one input color and 1231 // the saturation of another color. It will have this signature: 1232 // float set_saturation(vec3 hueLumColor, vec3 satColor) 1233 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { 1234 // Emit a helper that gets the saturation of a color 1235 SkString getFunction; 1236 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; 1237 SkString getSatBody; 1238 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " 1239 "min(min(color.r, color.g), color.b);\n"); 1240 builder->fsEmitFunction(kFloat_GrSLType, 1241 "saturation", 1242 SK_ARRAY_COUNT(getSatArgs), getSatArgs, 1243 getSatBody.c_str(), 1244 &getFunction); 1245 1246 // Emit a helper that sets the saturation given sorted input channels. This used 1247 // to use inout params for min, mid, and max components but that seems to cause 1248 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the 1249 // adjusted min, mid, and max inputs, respectively. 1250 SkString helperFunction; 1251 GrGLShaderVar helperArgs[] = { 1252 GrGLShaderVar("minComp", kFloat_GrSLType), 1253 GrGLShaderVar("midComp", kFloat_GrSLType), 1254 GrGLShaderVar("maxComp", kFloat_GrSLType), 1255 GrGLShaderVar("sat", kFloat_GrSLType), 1256 }; 1257 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n" 1258 "\t\tvec3 result;\n" 1259 "\t\tresult.r = 0.0;\n" 1260 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n" 1261 "\t\tresult.b = sat;\n" 1262 "\t\treturn result;\n" 1263 "\t} else {\n" 1264 "\t\treturn vec3(0, 0, 0);\n" 1265 "\t}\n"; 1266 builder->fsEmitFunction(kVec3f_GrSLType, 1267 "set_saturation_helper", 1268 SK_ARRAY_COUNT(helperArgs), helperArgs, 1269 kHelperBody, 1270 &helperFunction); 1271 1272 GrGLShaderVar setSatArgs[] = { 1273 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), 1274 GrGLShaderVar("satColor", kVec3f_GrSLType), 1275 }; 1276 const char* helpFunc = helperFunction.c_str(); 1277 SkString setSatBody; 1278 setSatBody.appendf("\tfloat sat = %s(satColor);\n" 1279 "\tif (hueLumColor.r <= hueLumColor.g) {\n" 1280 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" 1281 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n" 1282 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1283 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n" 1284 "\t\t} else {\n" 1285 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n" 1286 "\t\t}\n" 1287 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1288 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n" 1289 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n" 1290 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n" 1291 "\t} else {\n" 1292 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n" 1293 "\t}\n" 1294 "\treturn hueLumColor;\n", 1295 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, 1296 helpFunc, helpFunc); 1297 builder->fsEmitFunction(kVec3f_GrSLType, 1298 "set_saturation", 1299 SK_ARRAY_COUNT(setSatArgs), setSatArgs, 1300 setSatBody.c_str(), 1301 setSatFunction); 1302 1303 } 1304 1305 typedef GrGLEffect INHERITED; 1306 }; 1307 1308 GR_DECLARE_EFFECT_TEST; 1309 1310private: 1311 XferEffect(SkXfermode::Mode mode, GrTexture* background) 1312 : fMode(mode) { 1313 if (background) { 1314 fBackgroundTransform.reset(kLocal_GrCoordSet, background); 1315 this->addCoordTransform(&fBackgroundTransform); 1316 fBackgroundAccess.reset(background); 1317 this->addTextureAccess(&fBackgroundAccess); 1318 } else { 1319 this->setWillReadDstColor(); 1320 } 1321 } 1322 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 1323 const XferEffect& s = CastEffect<XferEffect>(other); 1324 return fMode == s.fMode && 1325 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture(); 1326 } 1327 1328 SkXfermode::Mode fMode; 1329 GrCoordTransform fBackgroundTransform; 1330 GrTextureAccess fBackgroundAccess; 1331 1332 typedef GrEffect INHERITED; 1333}; 1334 1335GR_DEFINE_EFFECT_TEST(XferEffect); 1336GrEffectRef* XferEffect::TestCreate(SkRandom* rand, 1337 GrContext*, 1338 const GrDrawTargetCaps&, 1339 GrTexture*[]) { 1340 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); 1341 1342 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL))); 1343 return CreateEffectRef(gEffect); 1344} 1345 1346#endif 1347 1348/////////////////////////////////////////////////////////////////////////////// 1349/////////////////////////////////////////////////////////////////////////////// 1350 1351SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) { 1352 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs); 1353 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) { 1354 // out of range, just set to something harmless 1355 mode32 = SkXfermode::kSrcOut_Mode; 1356 } 1357 fMode = (SkXfermode::Mode)mode32; 1358 1359 const ProcCoeff& rec = gProcCoeffs[fMode]; 1360 // these may be valid, or may be CANNOT_USE_COEFF 1361 fSrcCoeff = rec.fSC; 1362 fDstCoeff = rec.fDC; 1363 // now update our function-ptr in the super class 1364 this->INHERITED::setProc(rec.fProc); 1365} 1366 1367bool SkProcCoeffXfermode::asMode(Mode* mode) const { 1368 if (mode) { 1369 *mode = fMode; 1370 } 1371 return true; 1372} 1373 1374bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const { 1375 if (CANNOT_USE_COEFF == fSrcCoeff) { 1376 return false; 1377 } 1378 1379 if (sc) { 1380 *sc = fSrcCoeff; 1381 } 1382 if (dc) { 1383 *dc = fDstCoeff; 1384 } 1385 return true; 1386} 1387 1388#if SK_SUPPORT_GPU 1389bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect, 1390 GrTexture* background) const { 1391 if (XferEffect::IsSupportedMode(fMode)) { 1392 if (NULL != effect) { 1393 *effect = XferEffect::Create(fMode, background); 1394 SkASSERT(NULL != *effect); 1395 } 1396 return true; 1397 } 1398 return false; 1399} 1400#endif 1401 1402void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const { 1403 this->INHERITED::flatten(buffer); 1404 buffer.write32(fMode); 1405} 1406 1407const char* SkXfermode::ModeName(Mode mode) { 1408 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1409 const char* gModeStrings[] = { 1410 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1411 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1412 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1413 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1414 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1415 }; 1416 return gModeStrings[mode]; 1417 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1418} 1419 1420#ifndef SK_IGNORE_TO_STRING 1421void SkProcCoeffXfermode::toString(SkString* str) const { 1422 str->append("SkProcCoeffXfermode: "); 1423 1424 str->append("mode: "); 1425 str->append(ModeName(fMode)); 1426 1427 static const char* gCoeffStrings[kCoeffCount] = { 1428 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1429 }; 1430 1431 str->append(" src: "); 1432 if (CANNOT_USE_COEFF == fSrcCoeff) { 1433 str->append("can't use"); 1434 } else { 1435 str->append(gCoeffStrings[fSrcCoeff]); 1436 } 1437 1438 str->append(" dst: "); 1439 if (CANNOT_USE_COEFF == fDstCoeff) { 1440 str->append("can't use"); 1441 } else { 1442 str->append(gCoeffStrings[fDstCoeff]); 1443 } 1444} 1445#endif 1446 1447/////////////////////////////////////////////////////////////////////////////// 1448 1449class SkClearXfermode : public SkProcCoeffXfermode { 1450public: 1451 static SkClearXfermode* Create(const ProcCoeff& rec) { 1452 return SkNEW_ARGS(SkClearXfermode, (rec)); 1453 } 1454 1455 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1456 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1457 1458 SK_TO_STRING_OVERRIDE() 1459 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1460 1461private: 1462 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1463 SkClearXfermode(SkReadBuffer& buffer) 1464 : SkProcCoeffXfermode(buffer) {} 1465 1466 typedef SkProcCoeffXfermode INHERITED; 1467}; 1468 1469void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1470 const SkPMColor* SK_RESTRICT, int count, 1471 const SkAlpha* SK_RESTRICT aa) const { 1472 SkASSERT(dst && count >= 0); 1473 1474 if (NULL == aa) { 1475 memset(dst, 0, count << 2); 1476 } else { 1477 for (int i = count - 1; i >= 0; --i) { 1478 unsigned a = aa[i]; 1479 if (0xFF == a) { 1480 dst[i] = 0; 1481 } else if (a != 0) { 1482 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1483 } 1484 } 1485 } 1486} 1487void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1488 const SkPMColor* SK_RESTRICT, int count, 1489 const SkAlpha* SK_RESTRICT aa) const { 1490 SkASSERT(dst && count >= 0); 1491 1492 if (NULL == aa) { 1493 memset(dst, 0, count); 1494 } else { 1495 for (int i = count - 1; i >= 0; --i) { 1496 unsigned a = aa[i]; 1497 if (0xFF == a) { 1498 dst[i] = 0; 1499 } else if (0 != a) { 1500 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1501 } 1502 } 1503 } 1504} 1505 1506#ifndef SK_IGNORE_TO_STRING 1507void SkClearXfermode::toString(SkString* str) const { 1508 this->INHERITED::toString(str); 1509} 1510#endif 1511 1512/////////////////////////////////////////////////////////////////////////////// 1513 1514class SkSrcXfermode : public SkProcCoeffXfermode { 1515public: 1516 static SkSrcXfermode* Create(const ProcCoeff& rec) { 1517 return SkNEW_ARGS(SkSrcXfermode, (rec)); 1518 } 1519 1520 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1521 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1522 1523 SK_TO_STRING_OVERRIDE() 1524 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1525 1526private: 1527 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1528 SkSrcXfermode(SkReadBuffer& buffer) 1529 : SkProcCoeffXfermode(buffer) {} 1530 1531 typedef SkProcCoeffXfermode INHERITED; 1532}; 1533 1534void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1535 const SkPMColor* SK_RESTRICT src, int count, 1536 const SkAlpha* SK_RESTRICT aa) const { 1537 SkASSERT(dst && src && count >= 0); 1538 1539 if (NULL == aa) { 1540 memcpy(dst, src, count << 2); 1541 } else { 1542 for (int i = count - 1; i >= 0; --i) { 1543 unsigned a = aa[i]; 1544 if (a == 0xFF) { 1545 dst[i] = src[i]; 1546 } else if (a != 0) { 1547 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1548 } 1549 } 1550 } 1551} 1552 1553void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1554 const SkPMColor* SK_RESTRICT src, int count, 1555 const SkAlpha* SK_RESTRICT aa) const { 1556 SkASSERT(dst && src && count >= 0); 1557 1558 if (NULL == aa) { 1559 for (int i = count - 1; i >= 0; --i) { 1560 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1561 } 1562 } else { 1563 for (int i = count - 1; i >= 0; --i) { 1564 unsigned a = aa[i]; 1565 if (0 != a) { 1566 unsigned srcA = SkGetPackedA32(src[i]); 1567 if (a == 0xFF) { 1568 dst[i] = SkToU8(srcA); 1569 } else { 1570 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1571 } 1572 } 1573 } 1574 } 1575} 1576#ifndef SK_IGNORE_TO_STRING 1577void SkSrcXfermode::toString(SkString* str) const { 1578 this->INHERITED::toString(str); 1579} 1580#endif 1581 1582/////////////////////////////////////////////////////////////////////////////// 1583 1584class SkDstInXfermode : public SkProcCoeffXfermode { 1585public: 1586 static SkDstInXfermode* Create(const ProcCoeff& rec) { 1587 return SkNEW_ARGS(SkDstInXfermode, (rec)); 1588 } 1589 1590 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1591 1592 SK_TO_STRING_OVERRIDE() 1593 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1594 1595private: 1596 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1597 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {} 1598 1599 typedef SkProcCoeffXfermode INHERITED; 1600}; 1601 1602void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1603 const SkPMColor* SK_RESTRICT src, int count, 1604 const SkAlpha* SK_RESTRICT aa) const { 1605 SkASSERT(dst && src); 1606 1607 if (count <= 0) { 1608 return; 1609 } 1610 if (NULL != aa) { 1611 return this->INHERITED::xfer32(dst, src, count, aa); 1612 } 1613 1614 do { 1615 unsigned a = SkGetPackedA32(*src); 1616 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1617 dst++; 1618 src++; 1619 } while (--count != 0); 1620} 1621 1622#ifndef SK_IGNORE_TO_STRING 1623void SkDstInXfermode::toString(SkString* str) const { 1624 this->INHERITED::toString(str); 1625} 1626#endif 1627 1628/////////////////////////////////////////////////////////////////////////////// 1629 1630class SkDstOutXfermode : public SkProcCoeffXfermode { 1631public: 1632 static SkDstOutXfermode* Create(const ProcCoeff& rec) { 1633 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 1634 } 1635 1636 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1637 1638 SK_TO_STRING_OVERRIDE() 1639 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1640 1641private: 1642 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1643 SkDstOutXfermode(SkReadBuffer& buffer) 1644 : INHERITED(buffer) {} 1645 1646 typedef SkProcCoeffXfermode INHERITED; 1647}; 1648 1649void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1650 const SkPMColor* SK_RESTRICT src, int count, 1651 const SkAlpha* SK_RESTRICT aa) const { 1652 SkASSERT(dst && src); 1653 1654 if (count <= 0) { 1655 return; 1656 } 1657 if (NULL != aa) { 1658 return this->INHERITED::xfer32(dst, src, count, aa); 1659 } 1660 1661 do { 1662 unsigned a = SkGetPackedA32(*src); 1663 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1664 dst++; 1665 src++; 1666 } while (--count != 0); 1667} 1668 1669#ifndef SK_IGNORE_TO_STRING 1670void SkDstOutXfermode::toString(SkString* str) const { 1671 this->INHERITED::toString(str); 1672} 1673#endif 1674 1675/////////////////////////////////////////////////////////////////////////////// 1676 1677SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); 1678static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; // All NULL to start. 1679static bool gXfermodeCached[SK_ARRAY_COUNT(gCachedXfermodes)]; // All false to start. 1680 1681void SkXfermode::Term() { 1682 SkAutoMutexAcquire ac(gCachedXfermodesMutex); 1683 1684 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) { 1685 SkSafeUnref(gCachedXfermodes[i]); 1686 gCachedXfermodes[i] = NULL; 1687 } 1688} 1689 1690extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, 1691 SkXfermode::Mode mode); 1692extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); 1693 1694 1695static void create_mode(SkXfermode::Mode mode) { 1696 SkASSERT(NULL == gCachedXfermodes[mode]); 1697 1698 ProcCoeff rec = gProcCoeffs[mode]; 1699 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); 1700 if (pp != NULL) { 1701 rec.fProc = pp; 1702 } 1703 1704 SkXfermode* xfer = NULL; 1705 // check if we have a platform optim for that 1706 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); 1707 if (xfm != NULL) { 1708 xfer = xfm; 1709 } else { 1710 // All modes can in theory be represented by the ProcCoeff rec, since 1711 // it contains function ptrs. However, a few modes are both simple and 1712 // commonly used, so we call those out for their own subclasses here. 1713 switch (mode) { 1714 case SkXfermode::kClear_Mode: 1715 xfer = SkClearXfermode::Create(rec); 1716 break; 1717 case SkXfermode::kSrc_Mode: 1718 xfer = SkSrcXfermode::Create(rec); 1719 break; 1720 case SkXfermode::kSrcOver_Mode: 1721 SkASSERT(false); // should not land here 1722 break; 1723 case SkXfermode::kDstIn_Mode: 1724 xfer = SkDstInXfermode::Create(rec); 1725 break; 1726 case SkXfermode::kDstOut_Mode: 1727 xfer = SkDstOutXfermode::Create(rec); 1728 break; 1729 default: 1730 // no special-case, just rely in the rec and its function-ptrs 1731 xfer = SkProcCoeffXfermode::Create(rec, mode); 1732 break; 1733 } 1734 } 1735 gCachedXfermodes[mode] = xfer; 1736} 1737 1738SkXfermode* SkXfermode::Create(Mode mode) { 1739 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1740 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); 1741 1742 if ((unsigned)mode >= kModeCount) { 1743 // report error 1744 return NULL; 1745 } 1746 1747 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover 1748 // so we can just return NULL from the factory. 1749 if (kSrcOver_Mode == mode) { 1750 return NULL; 1751 } 1752 1753 SkOnce(&gXfermodeCached[mode], &gCachedXfermodesMutex, create_mode, mode); 1754 SkXfermode* xfer = gCachedXfermodes[mode]; 1755 SkASSERT(xfer != NULL); 1756 return SkSafeRef(xfer); 1757} 1758 1759SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1760 SkXfermodeProc proc = NULL; 1761 if ((unsigned)mode < kModeCount) { 1762 proc = gProcCoeffs[mode].fProc; 1763 } 1764 return proc; 1765} 1766 1767bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1768 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1769 1770 if ((unsigned)mode >= (unsigned)kModeCount) { 1771 // illegal mode parameter 1772 return false; 1773 } 1774 1775 const ProcCoeff& rec = gProcCoeffs[mode]; 1776 1777 if (CANNOT_USE_COEFF == rec.fSC) { 1778 return false; 1779 } 1780 1781 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1782 if (src) { 1783 *src = rec.fSC; 1784 } 1785 if (dst) { 1786 *dst = rec.fDC; 1787 } 1788 return true; 1789} 1790 1791bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1792 if (NULL == xfer) { 1793 if (mode) { 1794 *mode = kSrcOver_Mode; 1795 } 1796 return true; 1797 } 1798 return xfer->asMode(mode); 1799} 1800 1801bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1802 if (NULL == xfer) { 1803 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1804 } 1805 return xfer->asCoeff(src, dst); 1806} 1807 1808bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1809 // if xfer==null then the mode is srcover 1810 Mode m = kSrcOver_Mode; 1811 if (xfer && !xfer->asMode(&m)) { 1812 return false; 1813 } 1814 return mode == m; 1815} 1816 1817/////////////////////////////////////////////////////////////////////////////// 1818//////////// 16bit xfermode procs 1819 1820#ifdef SK_DEBUG 1821static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1822static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1823#endif 1824 1825static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1826 SkASSERT(require_255(src)); 1827 return SkPixel32ToPixel16(src); 1828} 1829 1830static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1831 return dst; 1832} 1833 1834static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1835 SkASSERT(require_0(src)); 1836 return dst; 1837} 1838 1839static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1840 SkASSERT(require_255(src)); 1841 return SkPixel32ToPixel16(src); 1842} 1843 1844static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1845 SkASSERT(require_0(src)); 1846 return dst; 1847} 1848 1849static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1850 SkASSERT(require_255(src)); 1851 return dst; 1852} 1853 1854static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1855 SkASSERT(require_255(src)); 1856 return SkPixel32ToPixel16(src); 1857} 1858 1859static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1860 SkASSERT(require_255(src)); 1861 return dst; 1862} 1863 1864static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1865 SkASSERT(require_0(src)); 1866 return dst; 1867} 1868 1869static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1870 unsigned isa = 255 - SkGetPackedA32(src); 1871 1872 return SkPackRGB16( 1873 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1874 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1875 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1876} 1877 1878static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1879 SkASSERT(require_0(src)); 1880 return dst; 1881} 1882 1883static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1884 SkASSERT(require_255(src)); 1885 return SkPixel32ToPixel16(src); 1886} 1887 1888static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1889 SkASSERT(require_255(src)); 1890 return dst; 1891} 1892 1893/********* 1894 darken and lighten boil down to this. 1895 1896 darken = (1 - Sa) * Dc + min(Sc, Dc) 1897 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1898 1899 if (Sa == 0) these become 1900 darken = Dc + min(0, Dc) = 0 1901 lighten = Dc + max(0, Dc) = Dc 1902 1903 if (Sa == 1) these become 1904 darken = min(Sc, Dc) 1905 lighten = max(Sc, Dc) 1906*/ 1907 1908static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1909 SkASSERT(require_0(src)); 1910 return 0; 1911} 1912 1913static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1914 SkASSERT(require_255(src)); 1915 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1916 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1917 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1918 return SkPackRGB16(r, g, b); 1919} 1920 1921static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1922 SkASSERT(require_0(src)); 1923 return dst; 1924} 1925 1926static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1927 SkASSERT(require_255(src)); 1928 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1929 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1930 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1931 return SkPackRGB16(r, g, b); 1932} 1933 1934struct Proc16Rec { 1935 SkXfermodeProc16 fProc16_0; 1936 SkXfermodeProc16 fProc16_255; 1937 SkXfermodeProc16 fProc16_General; 1938}; 1939 1940static const Proc16Rec gModeProcs16[] = { 1941 { NULL, NULL, NULL }, // CLEAR 1942 { NULL, src_modeproc16_255, NULL }, 1943 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1944 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1945 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1946 { NULL, srcin_modeproc16_255, NULL }, 1947 { NULL, dstin_modeproc16_255, NULL }, 1948 { NULL, NULL, NULL },// SRC_OUT 1949 { dstout_modeproc16_0, NULL, NULL }, 1950 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1951 { NULL, dstatop_modeproc16_255, NULL }, 1952 { NULL, NULL, NULL }, // XOR 1953 1954 { NULL, NULL, NULL }, // plus 1955 { NULL, NULL, NULL }, // modulate 1956 { NULL, NULL, NULL }, // screen 1957 { NULL, NULL, NULL }, // overlay 1958 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1959 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1960 { NULL, NULL, NULL }, // colordodge 1961 { NULL, NULL, NULL }, // colorburn 1962 { NULL, NULL, NULL }, // hardlight 1963 { NULL, NULL, NULL }, // softlight 1964 { NULL, NULL, NULL }, // difference 1965 { NULL, NULL, NULL }, // exclusion 1966 { NULL, NULL, NULL }, // multiply 1967 { NULL, NULL, NULL }, // hue 1968 { NULL, NULL, NULL }, // saturation 1969 { NULL, NULL, NULL }, // color 1970 { NULL, NULL, NULL }, // luminosity 1971}; 1972 1973SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1974 SkXfermodeProc16 proc16 = NULL; 1975 if ((unsigned)mode < kModeCount) { 1976 const Proc16Rec& rec = gModeProcs16[mode]; 1977 unsigned a = SkColorGetA(srcColor); 1978 1979 if (0 == a) { 1980 proc16 = rec.fProc16_0; 1981 } else if (255 == a) { 1982 proc16 = rec.fProc16_255; 1983 } else { 1984 proc16 = rec.fProc16_General; 1985 } 1986 } 1987 return proc16; 1988} 1989 1990SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1991 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1992 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1993 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1994 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1995 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1996#if !SK_ARM_NEON_IS_NONE 1997 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode) 1998#endif 1999SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 2000