diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-06 15:07:23 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-06 15:07:23 +0000 |
commit | c1cdf21ab88b63c07990e6bbce559397bf207b47 (patch) | |
tree | 9015cb2d6736d628a5a08a34d291cb53acc882d3 /src/gpu/GrBlend.cpp | |
parent | 0b82fbcb464fa480c3fb59bed7524518ed9b32ce (diff) |
Add blend optimization helpers and use to convert rect draws to clears.
Committed: http://code.google.com/p/skia/source/detail?r=10537
R=robertphillips@google.com, jvanverth@google.com, reed@google.com
Author: bsalomon@google.com
Review URL: https://chromiumcodereview.appspot.com/21877006
git-svn-id: http://skia.googlecode.com/svn/trunk@10562 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/GrBlend.cpp')
-rw-r--r-- | src/gpu/GrBlend.cpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/gpu/GrBlend.cpp b/src/gpu/GrBlend.cpp new file mode 100644 index 0000000000..c0621a9b3f --- /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; + } +} |