diff options
author | bungeman <bungeman@google.com> | 2015-05-22 17:55:26 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-22 17:55:26 -0700 |
commit | c33db93d1b285923b5deef97ecb04d4d01e05dd5 (patch) | |
tree | 1dbb22f4cea24efb7c97c72041695d73b5ac14bf /src/gpu/GrBlend.cpp | |
parent | c319c80d09c6e9c681041f9e9db7b6bcbae542cc (diff) |
Revert of Implement Porter Duff XP with a blend table (patchset #12 id:220001 of https://codereview.chromium.org/1124373002/)
Reason for revert:
Blocking DEPS roll into Chromium. Crashing virtual/gpu/fast/canvas/canvas-composite-*.html tests with the assert
../../third_party/skia/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp:281: failed assertion "k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()"
Original issue's description:
> Implement Porter Duff XP with a blend table
>
> Removes the runtime logic used by PorterDuffXferProcessor to decide
> blend coeffs and shader outputs, and instead uses a compile-time
> constant table of pre-selected blend formulas.
>
> Introduces a new blend strategy for srcCoeff=0 that can apply coverage
> with a reverse subtract blend equation instead of dual source
> blending.
>
> Adds new macros in GrBlend.h to analyze blend formulas both runtime.
>
> Removes kSetCoverageDrawing_OptFlag and GrSimplifyBlend as they are no
> longer used.
>
> Adds a GM that verifies all xfermodes, including arithmetic, with the
> color/coverage invariants used by Porter Duff.
>
> Adds a unit test that verifies each Porter Duff formula with every
> color/coverage invariant.
>
> Major changes:
>
> * Uses a reverse subtract blend equation for coverage when srcCoeff=0
> (clear, dst-out [Sa=1], dst-in, modulate). Platforms that don't
> support dual source blending no longer require a dst copy for
> dst-in and modulate.
>
> * Sets BlendInfo::fWriteColor to false when the blend does not modify
> the dst. GrGLGpu will now use glColorMask instead of blending for
> these modes (dst, dst-in [Sa=1], modulate ignored for [Sc=1]).
>
> * Converts all SA blend coeffs to One for opaque inputs, and ISA to
> Zero if there is also no coverage. (We keep ISA around when there
> is coverage because we use it to tweak alpha for coverage.)
>
> * Abandons solid white optimizations for the sake of simplicity
> (screen was the only mode that previous had solid white opts).
>
> Minor differences:
>
> * Inconsequential differences in opt flags (e.g. we now return
> kCanTweakAlphaForCoverage_OptFlag even when there is no coverage).
>
> * Src coeffs when the shader outputs 0.
>
> * IS2C vs IS2A when the secondary output is scalar.
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/9a70920db22b6309c671f8e5d519bb95570e4414
TBR=egdaniel@google.com,bsalomon@google.com,cdalton@nvidia.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Review URL: https://codereview.chromium.org/1153993002
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..52e335e9b0 --- /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) { + + SkASSERT(!GrBlendCoeffRefsSrc(*srcCoeff)); + SkASSERT(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. + SkDEBUGCODE(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; + } +} |