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