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