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