Chromium Code Reviews| 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); |
|
jvanverth1
2013/08/02 21:30:28
This is kinda ugly, but I don't have a better sugg
|
| + 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; |
| + } |
| +} |