| Index: src/gpu/GrBlend.cpp
 | 
| diff --git a/src/gpu/GrBlend.cpp b/src/gpu/GrBlend.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..c0621a9b3f81f8f05223430b200ea8710792e02d
 | 
| --- /dev/null
 | 
| +++ b/src/gpu/GrBlend.cpp
 | 
| @@ -0,0 +1,154 @@
 | 
| +
 | 
| +/*
 | 
| + * Copyright 2013 Google Inc.
 | 
| + *
 | 
| + * Use of this source code is governed by a BSD-style license that can be
 | 
| + * found in the LICENSE file.
 | 
| + */
 | 
| +
 | 
| +#include "GrBlend.h"
 | 
| +
 | 
| +static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) {
 | 
| +    switch (coeff) {
 | 
| +        case kDC_GrBlendCoeff:
 | 
| +            return kSC_GrBlendCoeff;
 | 
| +        case kIDC_GrBlendCoeff:
 | 
| +            return kISC_GrBlendCoeff;
 | 
| +        case kDA_GrBlendCoeff:
 | 
| +            return kSA_GrBlendCoeff;
 | 
| +        case kIDA_GrBlendCoeff:
 | 
| +            return kISA_GrBlendCoeff;
 | 
| +        case kSC_GrBlendCoeff:
 | 
| +            return kDC_GrBlendCoeff;
 | 
| +        case kISC_GrBlendCoeff:
 | 
| +            return kIDC_GrBlendCoeff;
 | 
| +        case kSA_GrBlendCoeff:
 | 
| +            return kDA_GrBlendCoeff;
 | 
| +        case kISA_GrBlendCoeff:
 | 
| +            return kIDA_GrBlendCoeff;
 | 
| +        default:
 | 
| +            return coeff;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +static inline unsigned saturated_add(unsigned a, unsigned b) {
 | 
| +    SkASSERT(a <= 255);
 | 
| +    SkASSERT(b <= 255);
 | 
| +    unsigned sum = a + b;
 | 
| +    if (sum > 255) {
 | 
| +        sum = 255;
 | 
| +    }
 | 
| +    return sum;
 | 
| +}
 | 
| +
 | 
| +static GrColor add_colors(GrColor src, GrColor dst) {
 | 
| +    unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst));
 | 
| +    unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst));
 | 
| +    unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst));
 | 
| +    unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst));
 | 
| +    return GrColorPackRGBA(r, g, b, a);
 | 
| +}
 | 
| +
 | 
| +static inline bool valid_color(uint32_t compFlags) {
 | 
| +     return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags;
 | 
| +}
 | 
| +
 | 
| +static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff,
 | 
| +                                   GrColor srcColor, uint32_t srcCompFlags,
 | 
| +                                   GrColor dstColor, uint32_t dstCompFlags,
 | 
| +                                   GrColor constantColor) {
 | 
| +
 | 
| +    GrAssert(!GrBlendCoeffRefsSrc(*srcCoeff));
 | 
| +    GrAssert(NULL != srcCoeff);
 | 
| +
 | 
| +    // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs.
 | 
| +    // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color,
 | 
| +    // if possible, below but that is not implemented now.
 | 
| +    switch (*srcCoeff) {
 | 
| +        case kIDC_GrBlendCoeff:
 | 
| +            dstColor = ~dstColor; // fallthrough
 | 
| +        case kDC_GrBlendCoeff:
 | 
| +            if (valid_color(dstCompFlags)) {
 | 
| +                if (0xffffffff == dstColor) {
 | 
| +                    *srcCoeff = kOne_GrBlendCoeff;
 | 
| +                } else if (0 == dstColor) {
 | 
| +                    *srcCoeff = kZero_GrBlendCoeff;
 | 
| +                }
 | 
| +            }
 | 
| +            break;
 | 
| +
 | 
| +        case kIDA_GrBlendCoeff:
 | 
| +            dstColor = ~dstColor; // fallthrough
 | 
| +        case kDA_GrBlendCoeff:
 | 
| +            if (kA_GrColorComponentFlag & dstCompFlags) {
 | 
| +                if (0xff == GrColorUnpackA(dstColor)) {
 | 
| +                    *srcCoeff = kOne_GrBlendCoeff;
 | 
| +                } else if (0 == GrColorUnpackA(dstColor)) {
 | 
| +                    *srcCoeff = kZero_GrBlendCoeff;
 | 
| +                }
 | 
| +            }
 | 
| +            break;
 | 
| +
 | 
| +        case kIConstC_GrBlendCoeff:
 | 
| +            constantColor = ~constantColor; // fallthrough
 | 
| +        case kConstC_GrBlendCoeff:
 | 
| +            if (0xffffffff == constantColor) {
 | 
| +                *srcCoeff = kOne_GrBlendCoeff;
 | 
| +            } else if (0 == constantColor) {
 | 
| +                *srcCoeff = kZero_GrBlendCoeff;
 | 
| +            }
 | 
| +            break;
 | 
| +
 | 
| +        case kIConstA_GrBlendCoeff:
 | 
| +            constantColor = ~constantColor; // fallthrough
 | 
| +        case kConstA_GrBlendCoeff:
 | 
| +            if (0xff == GrColorUnpackA(constantColor)) {
 | 
| +                *srcCoeff = kOne_GrBlendCoeff;
 | 
| +            } else if (0 == GrColorUnpackA(constantColor)) {
 | 
| +                *srcCoeff = kZero_GrBlendCoeff;
 | 
| +            }
 | 
| +            break;
 | 
| +            
 | 
| +        default:
 | 
| +            break;
 | 
| +    }
 | 
| +    // We may have invalidated these above and shouldn't read them again.
 | 
| +    GR_DEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;)
 | 
| +
 | 
| +    if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) {
 | 
| +        *srcCoeff = kZero_GrBlendCoeff;
 | 
| +        return 0;
 | 
| +    }
 | 
| +
 | 
| +    if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) {
 | 
| +        return srcColor;
 | 
| +    } else {
 | 
| +        return GrColor_ILLEGAL;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff,
 | 
| +                        GrBlendCoeff* dstCoeff,
 | 
| +                        GrColor srcColor, uint32_t srcCompFlags,
 | 
| +                        GrColor dstColor, uint32_t dstCompFlags,
 | 
| +                        GrColor constantColor) {
 | 
| +    GrColor srcTermColor = simplify_blend_term(srcCoeff,
 | 
| +                                               srcColor, srcCompFlags,
 | 
| +                                               dstColor, dstCompFlags,
 | 
| +                                               constantColor);
 | 
| +
 | 
| +    // We call the same function to simplify the dst blend coeff. We trick it out by swapping the
 | 
| +    // src and dst.
 | 
| +    GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff);
 | 
| +    GrColor dstTermColor = simplify_blend_term(&spoofedCoeff,
 | 
| +                                               dstColor, dstCompFlags,
 | 
| +                                               srcColor, srcCompFlags,
 | 
| +                                               constantColor);
 | 
| +    *dstCoeff = swap_coeff_src_dst(spoofedCoeff);
 | 
| +
 | 
| +    if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) {
 | 
| +        return add_colors(srcTermColor, dstTermColor);
 | 
| +    } else {
 | 
| +        return GrColor_ILLEGAL;
 | 
| +    }
 | 
| +}
 | 
| 
 |