| |
| /* |
| * 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; |
| } |
| } |