SkXfermode.cpp revision c3118739277beb7678973d47e3d71bb863929bce
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2006 The Android Open Source Project
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Use of this source code is governed by a BSD-style license that can be
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * found in the LICENSE file.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "SkXfermode.h"
110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "SkXfermode_proccoeff.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkColorPriv.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMathPriv.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkOnce.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkReadBuffer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkString.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkUtilsArm.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkWriteBuffer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkXfermode_opts_SSE2.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !SK_ARM_NEON_IS_NONE
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkXfermode_opts_arm_neon.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// idea for higher precision blends in xfer procs (and slightly faster)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// see DstATop as a probable caller
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(a <= 255);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(b <= 255);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(c <= 255);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(d <= 255);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned result = (prod + (prod >> 8)) >> 8;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(result <= 255);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned saturated_add(unsigned a, unsigned b) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(a <= 255);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(b <= 255);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned sum = a + b;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sum > 255) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sum = 255;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sum;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int clamp_signed_byte(int n) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (n < 0) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        n = 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (n > 255) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        n = 255;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return n;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int clamp_div255round(int prod) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prod <= 0) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (prod >= 255*255) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 255;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SkDiv255Round(prod);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kClear_Mode,    //!< [0, 0]
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return 0;
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kSrc_Mode,      //!< [Sa, Sc]
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return src;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kDst_Mode,      //!< [Da, Dc]
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return dst;
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if 0
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // this is the old, more-correct way, but it doesn't guarantee that dst==255
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // will always stay opaque
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this is slightly faster, but more importantly guarantees that dst==255
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will always stay opaque
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this is the reverse of srcover, just flipping src and dst
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // see srcover's comment about the 256 for opaqueness guarantees
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned sa = SkGetPackedA32(src);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned da = SkGetPackedA32(dst);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned isa = 255 - sa;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(da,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned sa = SkGetPackedA32(src);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned da = SkGetPackedA32(dst);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned ida = 255 - da;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(sa,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned sa = SkGetPackedA32(src);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned da = SkGetPackedA32(dst);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned isa = 255 - sa;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned ida = 255 - da;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kPlus_Mode
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// kModulate_Mode
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline int srcover_byte(int a, int b) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a + b - SkAlphaMulAlpha(a, b);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kMultiply_Mode
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// B(Cb, Cs) = Cb x Cs
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiply uses its own version of blendfunc_byte because sa and da are not needed
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sa = SkGetPackedA32(src);
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int da = SkGetPackedA32(dst);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int a = srcover_byte(sa, da);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return SkPackARGB32(a, r, g, b);
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kScreen_Mode
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kOverlay_Mode
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int overlay_byte(int sc, int dc, int sa, int da) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tmp = sc * (255 - da) + dc * (255 - sa);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (2 * dc <= da) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = 2 * sc * dc;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = sa * da - 2 * (da - dc) * (sa - sc);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return clamp_div255round(rc + tmp);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sa = SkGetPackedA32(src);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int da = SkGetPackedA32(dst);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int a = srcover_byte(sa, da);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDarken_Mode
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int darken_byte(int sc, int dc, int sa, int da) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sd = sc * da;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ds = dc * sa;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sd < ds) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // srcover
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return sc + dc - SkDiv255Round(ds);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // dstover
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return dc + sc - SkDiv255Round(sd);
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sa = SkGetPackedA32(src);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int da = SkGetPackedA32(dst);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int a = srcover_byte(sa, da);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kLighten_Mode
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int lighten_byte(int sc, int dc, int sa, int da) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sd = sc * da;
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int ds = dc * sa;
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (sd > ds) {
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        // srcover
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return sc + dc - SkDiv255Round(ds);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // dstover
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return dc + sc - SkDiv255Round(sd);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sa = SkGetPackedA32(src);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int da = SkGetPackedA32(dst);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int a = srcover_byte(sa, da);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkPackARGB32(a, r, g, b);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// kColorDodge_Mode
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int diff = sa - sc;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 == dc) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SkAlphaMulAlpha(sc, 255 - da);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (0 == diff) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        diff = dc * sa / diff;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return clamp_div255round(rc);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sa = SkGetPackedA32(src);
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int da = SkGetPackedA32(dst);
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int a = srcover_byte(sa, da);
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return SkPackARGB32(a, r, g, b);
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kColorBurn_Mode
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int rc;
319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (dc == da) {
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (0 == sc) {
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return SkAlphaMulAlpha(dc, 255 - sa);
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        int tmp = (da - dc) * sa / sc;
325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        rc = sa * (da - ((da < tmp) ? da : tmp))
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            + sc * (255 - da) + dc * (255 - sa);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return clamp_div255round(rc);
329}
330static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
331    int sa = SkGetPackedA32(src);
332    int da = SkGetPackedA32(dst);
333    int a = srcover_byte(sa, da);
334    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
335    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
336    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
337    return SkPackARGB32(a, r, g, b);
338}
339
340// kHardLight_Mode
341static inline int hardlight_byte(int sc, int dc, int sa, int da) {
342    int rc;
343    if (2 * sc <= sa) {
344        rc = 2 * sc * dc;
345    } else {
346        rc = sa * da - 2 * (da - dc) * (sa - sc);
347    }
348    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
349}
350static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
351    int sa = SkGetPackedA32(src);
352    int da = SkGetPackedA32(dst);
353    int a = srcover_byte(sa, da);
354    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
355    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
356    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
357    return SkPackARGB32(a, r, g, b);
358}
359
360// returns 255 * sqrt(n/255)
361static U8CPU sqrt_unit_byte(U8CPU n) {
362    return SkSqrtBits(n, 15+4);
363}
364
365// kSoftLight_Mode
366static inline int softlight_byte(int sc, int dc, int sa, int da) {
367    int m = da ? dc * 256 / da : 0;
368    int rc;
369    if (2 * sc <= sa) {
370        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
371    } else if (4 * dc <= da) {
372        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
373        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
374    } else {
375        int tmp = sqrt_unit_byte(m) - m;
376        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
377    }
378    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
379}
380static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
381    int sa = SkGetPackedA32(src);
382    int da = SkGetPackedA32(dst);
383    int a = srcover_byte(sa, da);
384    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
385    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
386    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
387    return SkPackARGB32(a, r, g, b);
388}
389
390// kDifference_Mode
391static inline int difference_byte(int sc, int dc, int sa, int da) {
392    int tmp = SkMin32(sc * da, dc * sa);
393    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
394}
395static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
396    int sa = SkGetPackedA32(src);
397    int da = SkGetPackedA32(dst);
398    int a = srcover_byte(sa, da);
399    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
400    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
401    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
402    return SkPackARGB32(a, r, g, b);
403}
404
405// kExclusion_Mode
406static inline int exclusion_byte(int sc, int dc, int, int) {
407    // this equations is wacky, wait for SVG to confirm it
408    //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
409
410    // The above equation can be simplified as follows
411    int r = 255*(sc + dc) - 2 * sc * dc;
412    return clamp_div255round(r);
413}
414static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
415    int sa = SkGetPackedA32(src);
416    int da = SkGetPackedA32(dst);
417    int a = srcover_byte(sa, da);
418    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
419    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
420    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
421    return SkPackARGB32(a, r, g, b);
422}
423
424// The CSS compositing spec introduces the following formulas:
425// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
426// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
427// while PDF and CG uses the one from Rec. Rec. 601
428// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
429static inline int Lum(int r, int g, int b)
430{
431    return SkDiv255Round(r * 77 + g * 150 + b * 28);
432}
433
434static inline int min2(int a, int b) { return a < b ? a : b; }
435static inline int max2(int a, int b) { return a > b ? a : b; }
436#define minimum(a, b, c) min2(min2(a, b), c)
437#define maximum(a, b, c) max2(max2(a, b), c)
438
439static inline int Sat(int r, int g, int b) {
440    return maximum(r, g, b) - minimum(r, g, b);
441}
442
443static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
444    if(*Cmax > *Cmin) {
445        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
446        *Cmax = s;
447    } else {
448        *Cmax = 0;
449        *Cmid = 0;
450    }
451
452    *Cmin = 0;
453}
454
455static inline void SetSat(int* r, int* g, int* b, int s) {
456    if(*r <= *g) {
457        if(*g <= *b) {
458            setSaturationComponents(r, g, b, s);
459        } else if(*r <= *b) {
460            setSaturationComponents(r, b, g, s);
461        } else {
462            setSaturationComponents(b, r, g, s);
463        }
464    } else if(*r <= *b) {
465        setSaturationComponents(g, r, b, s);
466    } else if(*g <= *b) {
467        setSaturationComponents(g, b, r, s);
468    } else {
469        setSaturationComponents(b, g, r, s);
470    }
471}
472
473static inline void clipColor(int* r, int* g, int* b, int a) {
474    int L = Lum(*r, *g, *b);
475    int n = minimum(*r, *g, *b);
476    int x = maximum(*r, *g, *b);
477    int denom;
478    if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
479       *r = L + SkMulDiv(*r - L, L, denom);
480       *g = L + SkMulDiv(*g - L, L, denom);
481       *b = L + SkMulDiv(*b - L, L, denom);
482    }
483
484    if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
485       int numer = a - L;
486       *r = L + SkMulDiv(*r - L, numer, denom);
487       *g = L + SkMulDiv(*g - L, numer, denom);
488       *b = L + SkMulDiv(*b - L, numer, denom);
489    }
490}
491
492static inline void SetLum(int* r, int* g, int* b, int a, int l) {
493  int d = l - Lum(*r, *g, *b);
494  *r +=  d;
495  *g +=  d;
496  *b +=  d;
497
498  clipColor(r, g, b, a);
499}
500
501// non-separable blend modes are done in non-premultiplied alpha
502#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
503  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
504
505// kHue_Mode
506// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
507// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
508static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
509    int sr = SkGetPackedR32(src);
510    int sg = SkGetPackedG32(src);
511    int sb = SkGetPackedB32(src);
512    int sa = SkGetPackedA32(src);
513
514    int dr = SkGetPackedR32(dst);
515    int dg = SkGetPackedG32(dst);
516    int db = SkGetPackedB32(dst);
517    int da = SkGetPackedA32(dst);
518    int Sr, Sg, Sb;
519
520    if(sa && da) {
521        Sr = sr * sa;
522        Sg = sg * sa;
523        Sb = sb * sa;
524        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
525        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
526    } else {
527        Sr = 0;
528        Sg = 0;
529        Sb = 0;
530    }
531
532    int a = srcover_byte(sa, da);
533    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
534    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
535    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
536    return SkPackARGB32(a, r, g, b);
537}
538
539// kSaturation_Mode
540// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
541// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
542static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
543    int sr = SkGetPackedR32(src);
544    int sg = SkGetPackedG32(src);
545    int sb = SkGetPackedB32(src);
546    int sa = SkGetPackedA32(src);
547
548    int dr = SkGetPackedR32(dst);
549    int dg = SkGetPackedG32(dst);
550    int db = SkGetPackedB32(dst);
551    int da = SkGetPackedA32(dst);
552    int Dr, Dg, Db;
553
554    if(sa && da) {
555        Dr = dr * sa;
556        Dg = dg * sa;
557        Db = db * sa;
558        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
559        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
560    } else {
561        Dr = 0;
562        Dg = 0;
563        Db = 0;
564    }
565
566    int a = srcover_byte(sa, da);
567    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
568    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
569    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
570    return SkPackARGB32(a, r, g, b);
571}
572
573// kColor_Mode
574// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
575// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
576static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
577    int sr = SkGetPackedR32(src);
578    int sg = SkGetPackedG32(src);
579    int sb = SkGetPackedB32(src);
580    int sa = SkGetPackedA32(src);
581
582    int dr = SkGetPackedR32(dst);
583    int dg = SkGetPackedG32(dst);
584    int db = SkGetPackedB32(dst);
585    int da = SkGetPackedA32(dst);
586    int Sr, Sg, Sb;
587
588    if(sa && da) {
589        Sr = sr * da;
590        Sg = sg * da;
591        Sb = sb * da;
592        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
593    } else {
594        Sr = 0;
595        Sg = 0;
596        Sb = 0;
597    }
598
599    int a = srcover_byte(sa, da);
600    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
601    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
602    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
603    return SkPackARGB32(a, r, g, b);
604}
605
606// kLuminosity_Mode
607// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
608// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
609static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
610    int sr = SkGetPackedR32(src);
611    int sg = SkGetPackedG32(src);
612    int sb = SkGetPackedB32(src);
613    int sa = SkGetPackedA32(src);
614
615    int dr = SkGetPackedR32(dst);
616    int dg = SkGetPackedG32(dst);
617    int db = SkGetPackedB32(dst);
618    int da = SkGetPackedA32(dst);
619    int Dr, Dg, Db;
620
621    if(sa && da) {
622        Dr = dr * sa;
623        Dg = dg * sa;
624        Db = db * sa;
625        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
626    } else {
627        Dr = 0;
628        Dg = 0;
629        Db = 0;
630    }
631
632    int a = srcover_byte(sa, da);
633    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
634    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
635    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
636    return SkPackARGB32(a, r, g, b);
637}
638
639const ProcCoeff gProcCoeffs[] = {
640    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
641    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
642    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
643    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
644    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
645    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
646    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
647    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
648    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
649    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
650    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
651    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
652
653    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
654    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
655    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
656    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
657    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
662    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
663    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
664    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
665    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
666    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
667    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
668    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
669    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
670};
671
672///////////////////////////////////////////////////////////////////////////////
673
674bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
675    return false;
676}
677
678bool SkXfermode::asMode(Mode* mode) const {
679    return false;
680}
681
682bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
683    return false;
684}
685
686bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
687                                    GrEffectRef** effect,
688                                    Coeff* src,
689                                    Coeff* dst,
690                                    GrTexture* background) {
691    if (NULL == xfermode) {
692        return ModeAsCoeff(kSrcOver_Mode, src, dst);
693    } else if (xfermode->asCoeff(src, dst)) {
694        return true;
695    } else {
696        return xfermode->asNewEffect(effect, background);
697    }
698}
699
700SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
701    // no-op. subclasses should override this
702    return dst;
703}
704
705void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
706                        const SkPMColor* SK_RESTRICT src, int count,
707                        const SkAlpha* SK_RESTRICT aa) const {
708    SkASSERT(dst && src && count >= 0);
709
710    if (NULL == aa) {
711        for (int i = count - 1; i >= 0; --i) {
712            dst[i] = this->xferColor(src[i], dst[i]);
713        }
714    } else {
715        for (int i = count - 1; i >= 0; --i) {
716            unsigned a = aa[i];
717            if (0 != a) {
718                SkPMColor dstC = dst[i];
719                SkPMColor C = this->xferColor(src[i], dstC);
720                if (0xFF != a) {
721                    C = SkFourByteInterp(C, dstC, a);
722                }
723                dst[i] = C;
724            }
725        }
726    }
727}
728
729void SkXfermode::xfer16(uint16_t* dst,
730                        const SkPMColor* SK_RESTRICT src, int count,
731                        const SkAlpha* SK_RESTRICT aa) const {
732    SkASSERT(dst && src && count >= 0);
733
734    if (NULL == aa) {
735        for (int i = count - 1; i >= 0; --i) {
736            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
737            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
738        }
739    } else {
740        for (int i = count - 1; i >= 0; --i) {
741            unsigned a = aa[i];
742            if (0 != a) {
743                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
744                SkPMColor C = this->xferColor(src[i], dstC);
745                if (0xFF != a) {
746                    C = SkFourByteInterp(C, dstC, a);
747                }
748                dst[i] = SkPixel32ToPixel16_ToU16(C);
749            }
750        }
751    }
752}
753
754void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
755                        const SkPMColor src[], int count,
756                        const SkAlpha* SK_RESTRICT aa) const {
757    SkASSERT(dst && src && count >= 0);
758
759    if (NULL == aa) {
760        for (int i = count - 1; i >= 0; --i) {
761            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
762            dst[i] = SkToU8(SkGetPackedA32(res));
763        }
764    } else {
765        for (int i = count - 1; i >= 0; --i) {
766            unsigned a = aa[i];
767            if (0 != a) {
768                SkAlpha dstA = dst[i];
769                unsigned A = SkGetPackedA32(this->xferColor(src[i],
770                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
771                if (0xFF != a) {
772                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
773                }
774                dst[i] = SkToU8(A);
775            }
776        }
777    }
778}
779
780///////////////////////////////////////////////////////////////////////////////
781
782void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
783                            const SkPMColor* SK_RESTRICT src, int count,
784                            const SkAlpha* SK_RESTRICT aa) const {
785    SkASSERT(dst && src && count >= 0);
786
787    SkXfermodeProc proc = fProc;
788
789    if (NULL != proc) {
790        if (NULL == aa) {
791            for (int i = count - 1; i >= 0; --i) {
792                dst[i] = proc(src[i], dst[i]);
793            }
794        } else {
795            for (int i = count - 1; i >= 0; --i) {
796                unsigned a = aa[i];
797                if (0 != a) {
798                    SkPMColor dstC = dst[i];
799                    SkPMColor C = proc(src[i], dstC);
800                    if (a != 0xFF) {
801                        C = SkFourByteInterp(C, dstC, a);
802                    }
803                    dst[i] = C;
804                }
805            }
806        }
807    }
808}
809
810void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
811                            const SkPMColor* SK_RESTRICT src, int count,
812                            const SkAlpha* SK_RESTRICT aa) const {
813    SkASSERT(dst && src && count >= 0);
814
815    SkXfermodeProc proc = fProc;
816
817    if (NULL != proc) {
818        if (NULL == aa) {
819            for (int i = count - 1; i >= 0; --i) {
820                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
821                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
822            }
823        } else {
824            for (int i = count - 1; i >= 0; --i) {
825                unsigned a = aa[i];
826                if (0 != a) {
827                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
828                    SkPMColor C = proc(src[i], dstC);
829                    if (0xFF != a) {
830                        C = SkFourByteInterp(C, dstC, a);
831                    }
832                    dst[i] = SkPixel32ToPixel16_ToU16(C);
833                }
834            }
835        }
836    }
837}
838
839void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
840                            const SkPMColor* SK_RESTRICT src, int count,
841                            const SkAlpha* SK_RESTRICT aa) const {
842    SkASSERT(dst && src && count >= 0);
843
844    SkXfermodeProc proc = fProc;
845
846    if (NULL != proc) {
847        if (NULL == aa) {
848            for (int i = count - 1; i >= 0; --i) {
849                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
850                dst[i] = SkToU8(SkGetPackedA32(res));
851            }
852        } else {
853            for (int i = count - 1; i >= 0; --i) {
854                unsigned a = aa[i];
855                if (0 != a) {
856                    SkAlpha dstA = dst[i];
857                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
858                    unsigned A = SkGetPackedA32(res);
859                    if (0xFF != a) {
860                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
861                    }
862                    dst[i] = SkToU8(A);
863                }
864            }
865        }
866    }
867}
868
869SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer)
870        : SkXfermode(buffer) {
871    fProc = NULL;
872    if (!buffer.isCrossProcess()) {
873        fProc = (SkXfermodeProc)buffer.readFunctionPtr();
874    }
875}
876
877void SkProcXfermode::flatten(SkWriteBuffer& buffer) const {
878    this->INHERITED::flatten(buffer);
879    if (!buffer.isCrossProcess()) {
880        buffer.writeFunctionPtr((void*)fProc);
881    }
882}
883
884#ifndef SK_IGNORE_TO_STRING
885void SkProcXfermode::toString(SkString* str) const {
886    str->appendf("SkProcXfermode: %p", fProc);
887}
888#endif
889
890//////////////////////////////////////////////////////////////////////////////
891
892#if SK_SUPPORT_GPU
893
894#include "GrEffect.h"
895#include "GrCoordTransform.h"
896#include "GrEffectUnitTest.h"
897#include "GrTBackendEffectFactory.h"
898#include "gl/GrGLEffect.h"
899
900/**
901 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
902 */
903class XferEffect : public GrEffect {
904public:
905    static bool IsSupportedMode(SkXfermode::Mode mode) {
906        return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
907    }
908
909    static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
910        if (!IsSupportedMode(mode)) {
911            return NULL;
912        } else {
913            AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
914            return CreateEffectRef(effect);
915        }
916    }
917
918    virtual void getConstantColorComponents(GrColor* color,
919                                            uint32_t* validFlags) const SK_OVERRIDE {
920        *validFlags = 0;
921    }
922
923    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
924        return GrTBackendEffectFactory<XferEffect>::getInstance();
925    }
926
927    static const char* Name() { return "XferEffect"; }
928
929    SkXfermode::Mode mode() const { return fMode; }
930    const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
931
932    class GLEffect : public GrGLEffect {
933    public:
934        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
935            : GrGLEffect(factory) {
936        }
937        virtual void emitCode(GrGLShaderBuilder* builder,
938                              const GrDrawEffect& drawEffect,
939                              EffectKey key,
940                              const char* outputColor,
941                              const char* inputColor,
942                              const TransformedCoordsArray& coords,
943                              const TextureSamplerArray& samplers) SK_OVERRIDE {
944            SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
945            const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
946            const char* dstColor;
947            if (backgroundTex) {
948                dstColor = "bgColor";
949                builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
950                builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
951                builder->fsCodeAppendf(";\n");
952            } else {
953                dstColor = builder->dstColor();
954            }
955            SkASSERT(NULL != dstColor);
956
957            // We don't try to optimize for this case at all
958            if (NULL == inputColor) {
959                builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
960                inputColor = "ones";
961            }
962            builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
963
964            // These all perform src-over on the alpha channel.
965            builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
966                                    outputColor, inputColor, inputColor, dstColor);
967
968            switch (mode) {
969                case SkXfermode::kOverlay_Mode:
970                    // Overlay is Hard-Light with the src and dst reversed
971                    HardLight(builder, outputColor, dstColor, inputColor);
972                    break;
973                case SkXfermode::kDarken_Mode:
974                    builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
975                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
976                                            outputColor,
977                                            inputColor, dstColor, inputColor,
978                                            dstColor, inputColor, dstColor);
979                    break;
980                case SkXfermode::kLighten_Mode:
981                    builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
982                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
983                                            outputColor,
984                                            inputColor, dstColor, inputColor,
985                                            dstColor, inputColor, dstColor);
986                    break;
987                case SkXfermode::kColorDodge_Mode:
988                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
989                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
990                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
991                    break;
992                case SkXfermode::kColorBurn_Mode:
993                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
994                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
995                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
996                    break;
997                case SkXfermode::kHardLight_Mode:
998                    HardLight(builder, outputColor, inputColor, dstColor);
999                    break;
1000                case SkXfermode::kSoftLight_Mode:
1001                    builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
1002                    builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
1003                    builder->fsCodeAppendf("\t\t} else {\n");
1004                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
1005                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1006                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1007                    builder->fsCodeAppendf("\t\t}\n");
1008                    break;
1009                case SkXfermode::kDifference_Mode:
1010                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1011                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1012                                           outputColor, inputColor, dstColor, inputColor, dstColor,
1013                                           dstColor, inputColor);
1014                    break;
1015                case SkXfermode::kExclusion_Mode:
1016                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1017                                                        "2.0 * %s.rgb * %s.rgb;\n",
1018                                           outputColor, dstColor, inputColor, dstColor, inputColor);
1019                    break;
1020                case SkXfermode::kMultiply_Mode:
1021                    builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1022                                                        "(1.0 - %s.a) * %s.rgb + "
1023                                                         "%s.rgb * %s.rgb;\n",
1024                                           outputColor, inputColor, dstColor, dstColor, inputColor,
1025                                           inputColor, dstColor);
1026                    break;
1027                case SkXfermode::kHue_Mode: {
1028                    //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1029                    SkString setSat, setLum;
1030                    AddSatFunction(builder, &setSat);
1031                    AddLumFunction(builder, &setLum);
1032                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1033                                           dstColor, inputColor);
1034                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1035                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1036                                           dstColor);
1037                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1038                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1039                    break;
1040                }
1041                case SkXfermode::kSaturation_Mode: {
1042                    // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1043                    SkString setSat, setLum;
1044                    AddSatFunction(builder, &setSat);
1045                    AddLumFunction(builder, &setLum);
1046                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1047                                           dstColor, inputColor);
1048                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1049                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1050                                           dstColor);
1051                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1052                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1053                    break;
1054                }
1055                case SkXfermode::kColor_Mode: {
1056                    //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1057                    SkString setLum;
1058                    AddLumFunction(builder, &setLum);
1059                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1060                                           inputColor, dstColor);
1061                    builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
1062                                           outputColor, setLum.c_str(), dstColor, inputColor);
1063                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1064                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1065                    break;
1066                }
1067                case SkXfermode::kLuminosity_Mode: {
1068                    //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1069                    SkString setLum;
1070                    AddLumFunction(builder, &setLum);
1071                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1072                                           inputColor, dstColor);
1073                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
1074                                           outputColor, setLum.c_str(), dstColor, inputColor);
1075                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1076                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1077                    break;
1078                }
1079                default:
1080                    GrCrash("Unknown XferEffect mode.");
1081                    break;
1082            }
1083        }
1084
1085        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1086            return drawEffect.castEffect<XferEffect>().mode();
1087        }
1088
1089    private:
1090        static void HardLight(GrGLShaderBuilder* builder,
1091                              const char* final,
1092                              const char* src,
1093                              const char* dst) {
1094            static const char kComponents[] = {'r', 'g', 'b'};
1095            for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
1096                char component = kComponents[i];
1097                builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1098                builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
1099                builder->fsCodeAppend("\t\t} else {\n");
1100                builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
1101                                       final, component, src, dst, dst, dst, component, src, src, component);
1102                builder->fsCodeAppend("\t\t}\n");
1103            }
1104            builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1105                                   final, src, dst, dst, src);
1106        }
1107
1108        // Does one component of color-dodge
1109        static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1110                                        const char* final,
1111                                        const char* src,
1112                                        const char* dst,
1113                                        const char component) {
1114            builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1115            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1116                                   final, component, src, component, dst);
1117            builder->fsCodeAppend("\t\t} else {\n");
1118            builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1119            builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1120            builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1121                                   final, component, src, dst, src, component, dst, dst, component,
1122                                   src);
1123            builder->fsCodeAppend("\t\t\t} else {\n");
1124            builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1125                                   dst, dst, component, src);
1126            builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1127                                   final, component, src, src, component, dst, dst, component, src);
1128            builder->fsCodeAppend("\t\t\t}\n");
1129            builder->fsCodeAppend("\t\t}\n");
1130        }
1131
1132        // Does one component of color-burn
1133        static void ColorBurnComponent(GrGLShaderBuilder* builder,
1134                                       const char* final,
1135                                       const char* src,
1136                                       const char* dst,
1137                                       const char component) {
1138            builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1139            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1140                                   final, component, src, dst, src, component, dst, dst, component,
1141                                   src);
1142            builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1143            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1144                                   final, component, dst, component, src);
1145            builder->fsCodeAppend("\t\t} else {\n");
1146            builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1147                                   dst, dst, dst, component, src, src, component);
1148            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1149                                   final, component, src, src, component, dst, dst, component, src);
1150            builder->fsCodeAppend("\t\t}\n");
1151        }
1152
1153        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1154        static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1155                                                  const char* final,
1156                                                  const char* src,
1157                                                  const char* dst,
1158                                                  const char component) {
1159            // if (2S < Sa)
1160            builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1161            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1162            builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
1163                                   final, component, dst, component, dst, component, src, src,
1164                                   component, dst, dst, src, component, dst, component, src, src,
1165                                   component);
1166            // else if (4D < Da)
1167            builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1168                                   dst, component, dst);
1169            builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1170                                   dst, component, dst, component);
1171            builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1172            builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1173            builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1174            // (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
1175            builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
1176                                   final, component, src, component, src, component, dst, component,
1177                                   src, src, component, dst, src, src, component, src, src,
1178                                   component);
1179            builder->fsCodeAppendf("\t\t\t} else {\n");
1180            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1181            builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
1182                                    final, component, dst, dst, component, src, src, component, dst,
1183                                    src, component, dst, component, src, src, component, src,
1184                                    component);
1185            builder->fsCodeAppendf("\t\t\t}\n");
1186        }
1187
1188        // Adds a function that takes two colors and an alpha as input. It produces a color with the
1189        // hue and saturation of the first color, the luminosity of the second color, and the input
1190        // alpha. It has this signature:
1191        //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1192        static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1193            // Emit a helper that gets the luminance of a color.
1194            SkString getFunction;
1195            GrGLShaderVar getLumArgs[] = {
1196                GrGLShaderVar("color", kVec3f_GrSLType),
1197            };
1198            SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1199            builder->fsEmitFunction(kFloat_GrSLType,
1200                                    "luminance",
1201                                    SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1202                                    getLumBody.c_str(),
1203                                    &getFunction);
1204
1205            // Emit the set luminance function.
1206            GrGLShaderVar setLumArgs[] = {
1207                GrGLShaderVar("hueSat", kVec3f_GrSLType),
1208                GrGLShaderVar("alpha", kFloat_GrSLType),
1209                GrGLShaderVar("lumColor", kVec3f_GrSLType),
1210            };
1211            SkString setLumBody;
1212            setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1213            setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1214            setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1215            setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1216                              "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1217                              "\tif (minComp < 0.0) {\n"
1218                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1219                              "\t}\n"
1220                              "\tif (maxComp > alpha) {\n"
1221                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1222                              "\t}\n"
1223                              "\treturn outColor;\n");
1224            builder->fsEmitFunction(kVec3f_GrSLType,
1225                                    "set_luminance",
1226                                    SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1227                                    setLumBody.c_str(),
1228                                    setLumFunction);
1229        }
1230
1231        // Adds a function that creates a color with the hue and luminosity of one input color and
1232        // the saturation of another color. It will have this signature:
1233        //      float set_saturation(vec3 hueLumColor, vec3 satColor)
1234        static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1235            // Emit a helper that gets the saturation of a color
1236            SkString getFunction;
1237            GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1238            SkString getSatBody;
1239            getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1240                              "min(min(color.r, color.g), color.b);\n");
1241            builder->fsEmitFunction(kFloat_GrSLType,
1242                                    "saturation",
1243                                    SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1244                                    getSatBody.c_str(),
1245                                    &getFunction);
1246
1247            // Emit a helper that sets the saturation given sorted input channels. This used
1248            // to use inout params for min, mid, and max components but that seems to cause
1249            // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1250            // adjusted min, mid, and max inputs, respectively.
1251            SkString helperFunction;
1252            GrGLShaderVar helperArgs[] = {
1253                GrGLShaderVar("minComp", kFloat_GrSLType),
1254                GrGLShaderVar("midComp", kFloat_GrSLType),
1255                GrGLShaderVar("maxComp", kFloat_GrSLType),
1256                GrGLShaderVar("sat", kFloat_GrSLType),
1257            };
1258            static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1259                                              "\t\tvec3 result;\n"
1260                                              "\t\tresult.r = 0.0;\n"
1261                                              "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1262                                              "\t\tresult.b = sat;\n"
1263                                              "\t\treturn result;\n"
1264                                              "\t} else {\n"
1265                                              "\t\treturn vec3(0, 0, 0);\n"
1266                                              "\t}\n";
1267            builder->fsEmitFunction(kVec3f_GrSLType,
1268                                    "set_saturation_helper",
1269                                    SK_ARRAY_COUNT(helperArgs), helperArgs,
1270                                    kHelperBody,
1271                                    &helperFunction);
1272
1273            GrGLShaderVar setSatArgs[] = {
1274                GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1275                GrGLShaderVar("satColor", kVec3f_GrSLType),
1276            };
1277            const char* helpFunc = helperFunction.c_str();
1278            SkString setSatBody;
1279            setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1280                               "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1281                               "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1282                               "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1283                               "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1284                               "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1285                               "\t\t} else {\n"
1286                               "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1287                               "\t\t}\n"
1288                               "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1289                               "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1290                               "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1291                               "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1292                               "\t} else {\n"
1293                               "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1294                               "\t}\n"
1295                               "\treturn hueLumColor;\n",
1296                               getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1297                               helpFunc, helpFunc);
1298            builder->fsEmitFunction(kVec3f_GrSLType,
1299                                    "set_saturation",
1300                                    SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1301                                    setSatBody.c_str(),
1302                                    setSatFunction);
1303
1304        }
1305
1306        typedef GrGLEffect INHERITED;
1307    };
1308
1309    GR_DECLARE_EFFECT_TEST;
1310
1311private:
1312    XferEffect(SkXfermode::Mode mode, GrTexture* background)
1313        : fMode(mode) {
1314        if (background) {
1315            fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1316            this->addCoordTransform(&fBackgroundTransform);
1317            fBackgroundAccess.reset(background);
1318            this->addTextureAccess(&fBackgroundAccess);
1319        } else {
1320            this->setWillReadDstColor();
1321        }
1322    }
1323    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1324        const XferEffect& s = CastEffect<XferEffect>(other);
1325        return fMode == s.fMode &&
1326               fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1327    }
1328
1329    SkXfermode::Mode fMode;
1330    GrCoordTransform fBackgroundTransform;
1331    GrTextureAccess  fBackgroundAccess;
1332
1333    typedef GrEffect INHERITED;
1334};
1335
1336GR_DEFINE_EFFECT_TEST(XferEffect);
1337GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
1338                                    GrContext*,
1339                                    const GrDrawTargetCaps&,
1340                                    GrTexture*[]) {
1341    int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1342
1343    AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
1344    return CreateEffectRef(gEffect);
1345}
1346
1347#endif
1348
1349///////////////////////////////////////////////////////////////////////////////
1350///////////////////////////////////////////////////////////////////////////////
1351
1352SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1353    uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1354    if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1355        // out of range, just set to something harmless
1356        mode32 = SkXfermode::kSrcOut_Mode;
1357    }
1358    fMode = (SkXfermode::Mode)mode32;
1359
1360    const ProcCoeff& rec = gProcCoeffs[fMode];
1361    // these may be valid, or may be CANNOT_USE_COEFF
1362    fSrcCoeff = rec.fSC;
1363    fDstCoeff = rec.fDC;
1364    // now update our function-ptr in the super class
1365    this->INHERITED::setProc(rec.fProc);
1366}
1367
1368bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1369    if (mode) {
1370        *mode = fMode;
1371    }
1372    return true;
1373}
1374
1375bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1376    if (CANNOT_USE_COEFF == fSrcCoeff) {
1377        return false;
1378    }
1379
1380    if (sc) {
1381        *sc = fSrcCoeff;
1382    }
1383    if (dc) {
1384        *dc = fDstCoeff;
1385    }
1386    return true;
1387}
1388
1389#if SK_SUPPORT_GPU
1390bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
1391                                      GrTexture* background) const {
1392    if (XferEffect::IsSupportedMode(fMode)) {
1393        if (NULL != effect) {
1394            *effect = XferEffect::Create(fMode, background);
1395            SkASSERT(NULL != *effect);
1396        }
1397        return true;
1398    }
1399    return false;
1400}
1401#endif
1402
1403void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1404    this->INHERITED::flatten(buffer);
1405    buffer.write32(fMode);
1406}
1407
1408const char* SkXfermode::ModeName(Mode mode) {
1409    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1410    const char* gModeStrings[] = {
1411        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1412        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1413        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1414        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1415        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1416    };
1417    return gModeStrings[mode];
1418    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1419}
1420
1421#ifndef SK_IGNORE_TO_STRING
1422void SkProcCoeffXfermode::toString(SkString* str) const {
1423    str->append("SkProcCoeffXfermode: ");
1424
1425    str->append("mode: ");
1426    str->append(ModeName(fMode));
1427
1428    static const char* gCoeffStrings[kCoeffCount] = {
1429        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1430    };
1431
1432    str->append(" src: ");
1433    if (CANNOT_USE_COEFF == fSrcCoeff) {
1434        str->append("can't use");
1435    } else {
1436        str->append(gCoeffStrings[fSrcCoeff]);
1437    }
1438
1439    str->append(" dst: ");
1440    if (CANNOT_USE_COEFF == fDstCoeff) {
1441        str->append("can't use");
1442    } else {
1443        str->append(gCoeffStrings[fDstCoeff]);
1444    }
1445}
1446#endif
1447
1448///////////////////////////////////////////////////////////////////////////////
1449
1450class SkClearXfermode : public SkProcCoeffXfermode {
1451public:
1452    static SkClearXfermode* Create(const ProcCoeff& rec) {
1453        return SkNEW_ARGS(SkClearXfermode, (rec));
1454    }
1455
1456    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1457    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1458
1459    SK_TO_STRING_OVERRIDE()
1460    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1461
1462private:
1463    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1464    SkClearXfermode(SkReadBuffer& buffer)
1465        : SkProcCoeffXfermode(buffer) {}
1466
1467    typedef SkProcCoeffXfermode INHERITED;
1468};
1469
1470void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1471                             const SkPMColor* SK_RESTRICT, int count,
1472                             const SkAlpha* SK_RESTRICT aa) const {
1473    SkASSERT(dst && count >= 0);
1474
1475    if (NULL == aa) {
1476        memset(dst, 0, count << 2);
1477    } else {
1478        for (int i = count - 1; i >= 0; --i) {
1479            unsigned a = aa[i];
1480            if (0xFF == a) {
1481                dst[i] = 0;
1482            } else if (a != 0) {
1483                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1484            }
1485        }
1486    }
1487}
1488void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1489                             const SkPMColor* SK_RESTRICT, int count,
1490                             const SkAlpha* SK_RESTRICT aa) const {
1491    SkASSERT(dst && count >= 0);
1492
1493    if (NULL == aa) {
1494        memset(dst, 0, count);
1495    } else {
1496        for (int i = count - 1; i >= 0; --i) {
1497            unsigned a = aa[i];
1498            if (0xFF == a) {
1499                dst[i] = 0;
1500            } else if (0 != a) {
1501                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1502            }
1503        }
1504    }
1505}
1506
1507#ifndef SK_IGNORE_TO_STRING
1508void SkClearXfermode::toString(SkString* str) const {
1509    this->INHERITED::toString(str);
1510}
1511#endif
1512
1513///////////////////////////////////////////////////////////////////////////////
1514
1515class SkSrcXfermode : public SkProcCoeffXfermode {
1516public:
1517    static SkSrcXfermode* Create(const ProcCoeff& rec) {
1518        return SkNEW_ARGS(SkSrcXfermode, (rec));
1519    }
1520
1521    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1522    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1523
1524    SK_TO_STRING_OVERRIDE()
1525    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1526
1527private:
1528    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1529    SkSrcXfermode(SkReadBuffer& buffer)
1530        : SkProcCoeffXfermode(buffer) {}
1531
1532    typedef SkProcCoeffXfermode INHERITED;
1533};
1534
1535void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1536                           const SkPMColor* SK_RESTRICT src, int count,
1537                           const SkAlpha* SK_RESTRICT aa) const {
1538    SkASSERT(dst && src && count >= 0);
1539
1540    if (NULL == aa) {
1541        memcpy(dst, src, count << 2);
1542    } else {
1543        for (int i = count - 1; i >= 0; --i) {
1544            unsigned a = aa[i];
1545            if (a == 0xFF) {
1546                dst[i] = src[i];
1547            } else if (a != 0) {
1548                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1549            }
1550        }
1551    }
1552}
1553
1554void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1555                           const SkPMColor* SK_RESTRICT src, int count,
1556                           const SkAlpha* SK_RESTRICT aa) const {
1557    SkASSERT(dst && src && count >= 0);
1558
1559    if (NULL == aa) {
1560        for (int i = count - 1; i >= 0; --i) {
1561            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1562        }
1563    } else {
1564        for (int i = count - 1; i >= 0; --i) {
1565            unsigned a = aa[i];
1566            if (0 != a) {
1567                unsigned srcA = SkGetPackedA32(src[i]);
1568                if (a == 0xFF) {
1569                    dst[i] = SkToU8(srcA);
1570                } else {
1571                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1572                }
1573            }
1574        }
1575    }
1576}
1577#ifndef SK_IGNORE_TO_STRING
1578void SkSrcXfermode::toString(SkString* str) const {
1579    this->INHERITED::toString(str);
1580}
1581#endif
1582
1583///////////////////////////////////////////////////////////////////////////////
1584
1585class SkDstInXfermode : public SkProcCoeffXfermode {
1586public:
1587    static SkDstInXfermode* Create(const ProcCoeff& rec) {
1588        return SkNEW_ARGS(SkDstInXfermode, (rec));
1589    }
1590
1591    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1592
1593    SK_TO_STRING_OVERRIDE()
1594    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1595
1596private:
1597    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1598    SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1599
1600    typedef SkProcCoeffXfermode INHERITED;
1601};
1602
1603void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1604                             const SkPMColor* SK_RESTRICT src, int count,
1605                             const SkAlpha* SK_RESTRICT aa) const {
1606    SkASSERT(dst && src);
1607
1608    if (count <= 0) {
1609        return;
1610    }
1611    if (NULL != aa) {
1612        return this->INHERITED::xfer32(dst, src, count, aa);
1613    }
1614
1615    do {
1616        unsigned a = SkGetPackedA32(*src);
1617        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1618        dst++;
1619        src++;
1620    } while (--count != 0);
1621}
1622
1623#ifndef SK_IGNORE_TO_STRING
1624void SkDstInXfermode::toString(SkString* str) const {
1625    this->INHERITED::toString(str);
1626}
1627#endif
1628
1629///////////////////////////////////////////////////////////////////////////////
1630
1631class SkDstOutXfermode : public SkProcCoeffXfermode {
1632public:
1633    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1634        return SkNEW_ARGS(SkDstOutXfermode, (rec));
1635    }
1636
1637    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1638
1639    SK_TO_STRING_OVERRIDE()
1640    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1641
1642private:
1643    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1644    SkDstOutXfermode(SkReadBuffer& buffer)
1645        : INHERITED(buffer) {}
1646
1647    typedef SkProcCoeffXfermode INHERITED;
1648};
1649
1650void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1651                              const SkPMColor* SK_RESTRICT src, int count,
1652                              const SkAlpha* SK_RESTRICT aa) const {
1653    SkASSERT(dst && src);
1654
1655    if (count <= 0) {
1656        return;
1657    }
1658    if (NULL != aa) {
1659        return this->INHERITED::xfer32(dst, src, count, aa);
1660    }
1661
1662    do {
1663        unsigned a = SkGetPackedA32(*src);
1664        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1665        dst++;
1666        src++;
1667    } while (--count != 0);
1668}
1669
1670#ifndef SK_IGNORE_TO_STRING
1671void SkDstOutXfermode::toString(SkString* str) const {
1672    this->INHERITED::toString(str);
1673}
1674#endif
1675
1676///////////////////////////////////////////////////////////////////////////////
1677
1678SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex);
1679static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1];  // All NULL to start.
1680static bool gXfermodeCached[SK_ARRAY_COUNT(gCachedXfermodes)];  // All false to start.
1681
1682void SkXfermode::Term() {
1683    SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1684
1685    for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) {
1686        SkSafeUnref(gCachedXfermodes[i]);
1687        gCachedXfermodes[i] = NULL;
1688    }
1689}
1690
1691extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
1692                                                      SkXfermode::Mode mode);
1693extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1694
1695
1696static void create_mode(SkXfermode::Mode mode) {
1697    SkASSERT(NULL == gCachedXfermodes[mode]);
1698
1699    ProcCoeff rec = gProcCoeffs[mode];
1700    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1701    if (pp != NULL) {
1702        rec.fProc = pp;
1703    }
1704
1705    SkXfermode* xfer = NULL;
1706    // check if we have a platform optim for that
1707    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1708    if (xfm != NULL) {
1709        xfer = xfm;
1710    } else {
1711        // All modes can in theory be represented by the ProcCoeff rec, since
1712        // it contains function ptrs. However, a few modes are both simple and
1713        // commonly used, so we call those out for their own subclasses here.
1714        switch (mode) {
1715            case SkXfermode::kClear_Mode:
1716                xfer = SkClearXfermode::Create(rec);
1717                break;
1718            case SkXfermode::kSrc_Mode:
1719                xfer = SkSrcXfermode::Create(rec);
1720                break;
1721            case SkXfermode::kSrcOver_Mode:
1722                SkASSERT(false);    // should not land here
1723                break;
1724            case SkXfermode::kDstIn_Mode:
1725                xfer = SkDstInXfermode::Create(rec);
1726                break;
1727            case SkXfermode::kDstOut_Mode:
1728                xfer = SkDstOutXfermode::Create(rec);
1729                break;
1730            default:
1731                // no special-case, just rely in the rec and its function-ptrs
1732                xfer = SkProcCoeffXfermode::Create(rec, mode);
1733                break;
1734        }
1735    }
1736    gCachedXfermodes[mode] = xfer;
1737}
1738
1739SkXfermode* SkXfermode::Create(Mode mode) {
1740    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1741    SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount);
1742
1743    if ((unsigned)mode >= kModeCount) {
1744        // report error
1745        return NULL;
1746    }
1747
1748    // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover
1749    // so we can just return NULL from the factory.
1750    if (kSrcOver_Mode == mode) {
1751        return NULL;
1752    }
1753
1754    SkOnce(&gXfermodeCached[mode], &gCachedXfermodesMutex, create_mode, mode);
1755    SkXfermode* xfer = gCachedXfermodes[mode];
1756    SkASSERT(xfer != NULL);
1757    return SkSafeRef(xfer);
1758}
1759
1760SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1761    SkXfermodeProc  proc = NULL;
1762    if ((unsigned)mode < kModeCount) {
1763        proc = gProcCoeffs[mode].fProc;
1764    }
1765    return proc;
1766}
1767
1768bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1769    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1770
1771    if ((unsigned)mode >= (unsigned)kModeCount) {
1772        // illegal mode parameter
1773        return false;
1774    }
1775
1776    const ProcCoeff& rec = gProcCoeffs[mode];
1777
1778    if (CANNOT_USE_COEFF == rec.fSC) {
1779        return false;
1780    }
1781
1782    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1783    if (src) {
1784        *src = rec.fSC;
1785    }
1786    if (dst) {
1787        *dst = rec.fDC;
1788    }
1789    return true;
1790}
1791
1792bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1793    if (NULL == xfer) {
1794        if (mode) {
1795            *mode = kSrcOver_Mode;
1796        }
1797        return true;
1798    }
1799    return xfer->asMode(mode);
1800}
1801
1802bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1803    if (NULL == xfer) {
1804        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1805    }
1806    return xfer->asCoeff(src, dst);
1807}
1808
1809bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1810    // if xfer==null then the mode is srcover
1811    Mode m = kSrcOver_Mode;
1812    if (xfer && !xfer->asMode(&m)) {
1813        return false;
1814    }
1815    return mode == m;
1816}
1817
1818///////////////////////////////////////////////////////////////////////////////
1819//////////// 16bit xfermode procs
1820
1821#ifdef SK_DEBUG
1822static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1823static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1824#endif
1825
1826static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1827    SkASSERT(require_255(src));
1828    return SkPixel32ToPixel16(src);
1829}
1830
1831static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1832    return dst;
1833}
1834
1835static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1836    SkASSERT(require_0(src));
1837    return dst;
1838}
1839
1840static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1841    SkASSERT(require_255(src));
1842    return SkPixel32ToPixel16(src);
1843}
1844
1845static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1846    SkASSERT(require_0(src));
1847    return dst;
1848}
1849
1850static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1851    SkASSERT(require_255(src));
1852    return dst;
1853}
1854
1855static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1856    SkASSERT(require_255(src));
1857    return SkPixel32ToPixel16(src);
1858}
1859
1860static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1861    SkASSERT(require_255(src));
1862    return dst;
1863}
1864
1865static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1866    SkASSERT(require_0(src));
1867    return dst;
1868}
1869
1870static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1871    unsigned isa = 255 - SkGetPackedA32(src);
1872
1873    return SkPackRGB16(
1874           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1875           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1876           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1877}
1878
1879static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1880    SkASSERT(require_0(src));
1881    return dst;
1882}
1883
1884static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1885    SkASSERT(require_255(src));
1886    return SkPixel32ToPixel16(src);
1887}
1888
1889static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1890    SkASSERT(require_255(src));
1891    return dst;
1892}
1893
1894/*********
1895    darken and lighten boil down to this.
1896
1897    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1898    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1899
1900    if (Sa == 0) these become
1901        darken  = Dc + min(0, Dc) = 0
1902        lighten = Dc + max(0, Dc) = Dc
1903
1904    if (Sa == 1) these become
1905        darken  = min(Sc, Dc)
1906        lighten = max(Sc, Dc)
1907*/
1908
1909static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1910    SkASSERT(require_0(src));
1911    return 0;
1912}
1913
1914static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1915    SkASSERT(require_255(src));
1916    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1917    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1918    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1919    return SkPackRGB16(r, g, b);
1920}
1921
1922static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1923    SkASSERT(require_0(src));
1924    return dst;
1925}
1926
1927static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1928    SkASSERT(require_255(src));
1929    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1930    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1931    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1932    return SkPackRGB16(r, g, b);
1933}
1934
1935struct Proc16Rec {
1936    SkXfermodeProc16    fProc16_0;
1937    SkXfermodeProc16    fProc16_255;
1938    SkXfermodeProc16    fProc16_General;
1939};
1940
1941static const Proc16Rec gModeProcs16[] = {
1942    { NULL,                 NULL,                   NULL            }, // CLEAR
1943    { NULL,                 src_modeproc16_255,     NULL            },
1944    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1945    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1946    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1947    { NULL,                 srcin_modeproc16_255,   NULL            },
1948    { NULL,                 dstin_modeproc16_255,   NULL            },
1949    { NULL,                 NULL,                   NULL            },// SRC_OUT
1950    { dstout_modeproc16_0,  NULL,                   NULL            },
1951    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1952    { NULL,                 dstatop_modeproc16_255, NULL            },
1953    { NULL,                 NULL,                   NULL            }, // XOR
1954
1955    { NULL,                 NULL,                   NULL            }, // plus
1956    { NULL,                 NULL,                   NULL            }, // modulate
1957    { NULL,                 NULL,                   NULL            }, // screen
1958    { NULL,                 NULL,                   NULL            }, // overlay
1959    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1960    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1961    { NULL,                 NULL,                   NULL            }, // colordodge
1962    { NULL,                 NULL,                   NULL            }, // colorburn
1963    { NULL,                 NULL,                   NULL            }, // hardlight
1964    { NULL,                 NULL,                   NULL            }, // softlight
1965    { NULL,                 NULL,                   NULL            }, // difference
1966    { NULL,                 NULL,                   NULL            }, // exclusion
1967    { NULL,                 NULL,                   NULL            }, // multiply
1968    { NULL,                 NULL,                   NULL            }, // hue
1969    { NULL,                 NULL,                   NULL            }, // saturation
1970    { NULL,                 NULL,                   NULL            }, // color
1971    { NULL,                 NULL,                   NULL            }, // luminosity
1972};
1973
1974SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1975    SkXfermodeProc16  proc16 = NULL;
1976    if ((unsigned)mode < kModeCount) {
1977        const Proc16Rec& rec = gModeProcs16[mode];
1978        unsigned a = SkColorGetA(srcColor);
1979
1980        if (0 == a) {
1981            proc16 = rec.fProc16_0;
1982        } else if (255 == a) {
1983            proc16 = rec.fProc16_255;
1984        } else {
1985            proc16 = rec.fProc16_General;
1986        }
1987    }
1988    return proc16;
1989}
1990
1991SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1992    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1993    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1994    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1995    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1996    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1997#if !SK_ARM_NEON_IS_NONE
1998    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
1999#endif
2000#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
2001    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode)
2002#endif
2003SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
2004