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