diff options
author | 2015-05-22 17:55:26 -0700 | |
---|---|---|
committer | 2015-05-22 17:55:26 -0700 | |
commit | c33db93d1b285923b5deef97ecb04d4d01e05dd5 (patch) | |
tree | 1dbb22f4cea24efb7c97c72041695d73b5ac14bf | |
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
-rw-r--r-- | gm/aaxfermodes.cpp | 191 | ||||
-rw-r--r-- | gyp/gpu.gypi | 1 | ||||
-rw-r--r-- | include/gpu/GrColor.h | 4 | ||||
-rw-r--r-- | include/gpu/GrXferProcessor.h | 8 | ||||
-rw-r--r-- | include/gpu/effects/GrPorterDuffXferProcessor.h | 9 | ||||
-rw-r--r-- | src/gpu/GrBlend.cpp | 154 | ||||
-rw-r--r-- | src/gpu/GrBlend.h | 113 | ||||
-rw-r--r-- | src/gpu/effects/GrPorterDuffXferProcessor.cpp | 905 | ||||
-rw-r--r-- | tests/GrPorterDuffTest.cpp | 1280 |
9 files changed, 628 insertions, 2037 deletions
diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp deleted file mode 100644 index 30b34a4d53..0000000000 --- a/gm/aaxfermodes.cpp +++ /dev/null @@ -1,191 +0,0 @@ - -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gm.h" -#include "SkArithmeticMode.h" -#include "SkShader.h" -#include "SkXfermode.h" - -enum { - kXfermodeCount = SkXfermode::kLastMode + 2, // All xfermodes plus arithmetic mode. - kShapeSize = 22, - kShapeSpacing = 36, - kShapeTypeSpacing = 4 * kShapeSpacing/3, - kPaintSpacing = 2 * kShapeSpacing, - kPadding = (kPaintSpacing - kShapeSpacing) / 2, - - kPaintWidth = 3*kShapeSpacing + 2*kShapeTypeSpacing + kShapeSize, - kPaintPadding = kPaintSpacing - kShapeSize, -}; - -static const SkColor kBGColor = SkColorSetARGB(200, 210, 184, 135); - -static const SkColor kShapeColors[3] = { - SkColorSetARGB(130, 255, 0, 128), // input color unknown - SkColorSetARGB(255, 0, 255, 255), // input color opaque - SkColorSetARGB(255, 255, 255, 255) // input solid white -}; - -enum Shape { - kSquare_Shape, - kDiamond_Shape, - kOval_Shape, - - kLast_Shape = kOval_Shape -}; - -namespace skiagm { - -static void draw_shape(SkCanvas* canvas, Shape shape, const SkColor color, size_t xfermodeIdx); - -/** - * Verifies AA works properly on all Xfermodes, including arithmetic, with various color invariants. - */ -class AAXfermodesGM : public GM { -public: - AAXfermodesGM() {} - -protected: - SkString onShortName() override { - return SkString("aaxfermodes"); - } - - SkISize onISize() override { - return SkISize::Make(3*kPaintWidth + 2*kPaintPadding + 2*kPadding, - (2 + SkXfermode::kLastCoeffMode) * kShapeSpacing + 2*kPadding); - } - - void onDraw(SkCanvas* canvas) override { - sk_tool_utils::draw_checkerboard(canvas, 0xffffffff, 0xffc0c0c0, 10); - - canvas->saveLayer(NULL, NULL); - canvas->drawColor(kBGColor, SkXfermode::kSrc_Mode); - - canvas->translate(kPadding + kShapeSize/2, kPadding + kShapeSpacing + kShapeSize/2); - - for (size_t colorIdx = 0; colorIdx < SK_ARRAY_COUNT(kShapeColors); colorIdx++) { - SkColor color = kShapeColors[colorIdx]; - - for (size_t shapeIdx = 0; shapeIdx <= kLast_Shape; shapeIdx++) { - Shape shape = static_cast<Shape>(shapeIdx); - canvas->save(); - - for (size_t xfermodeIdx = 0; xfermodeIdx < kXfermodeCount; xfermodeIdx++) { - draw_shape(canvas, shape, color, xfermodeIdx); - - if (xfermodeIdx == SkXfermode::kLastCoeffMode) { - // New column. - canvas->restore(); - canvas->translate(kShapeSpacing, 0); - canvas->save(); - } else { - canvas->translate(0, kShapeSpacing); - } - } - - canvas->restore(); - - if (shape != kLast_Shape) { - canvas->translate(kShapeTypeSpacing, 0); - } else { - canvas->translate(kPaintSpacing, 0); - } - } - } - - canvas->restore(); - - SkPaint textPaint; - textPaint.setAntiAlias(true); - sk_tool_utils::set_portable_typeface(&textPaint); - textPaint.setTextAlign(SkPaint::kCenter_Align); - textPaint.setFakeBoldText(true); - textPaint.setTextSize(21 * kShapeSize/32); - - canvas->translate(kPadding + kPaintWidth/2, - kPadding + kShapeSize/2 + textPaint.getTextSize()/4); - canvas->drawText("input color unknown", sizeof("input color unknown") - 1, 0, 0, textPaint); - - canvas->translate(kPaintWidth + kPaintPadding, 0); - canvas->drawText("input color opaque", sizeof("input color opaque") - 1, 0, 0, textPaint); - - canvas->translate(kPaintWidth + kPaintPadding, 0); - canvas->drawText("input solid white", sizeof("input solid white") - 1, 0, 0, textPaint); - } - -private: - typedef GM INHERITED; -}; - -static void draw_shape(SkCanvas* canvas, Shape shape, const SkColor color, size_t xfermodeIdx) { - SkPaint shapePaint; - shapePaint.setAntiAlias(kSquare_Shape != shape); - shapePaint.setColor(color); - - SkAutoTUnref<SkXfermode> xfermode; - if (xfermodeIdx <= SkXfermode::kLastMode) { - SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeIdx); - xfermode.reset(SkXfermode::Create(mode)); - } else { - xfermode.reset(SkArithmeticMode::Create(+1.0f, +0.25f, -0.5f, +0.1f)); - } - shapePaint.setXfermode(xfermode); - - if (xfermodeIdx == SkXfermode::kPlus_Mode) { - // Check for overflow and dim the src and dst colors if we need to, otherwise we might get - // confusing AA artifacts. - int maxSum = SkTMax(SkTMax(SkColorGetA(kBGColor) + SkColorGetA(color), - SkColorGetR(kBGColor) + SkColorGetR(color)), - SkTMax(SkColorGetG(kBGColor) + SkColorGetG(color), - SkColorGetB(kBGColor) + SkColorGetB(color))); - - if (maxSum > 255) { - SkPaint dimPaint; - dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0); - dimPaint.setAntiAlias(false); - dimPaint.setXfermode(SkXfermode::Create(SkXfermode::kDstIn_Mode)); - canvas->drawRectCoords(-kShapeSpacing/2, -kShapeSpacing/2, - kShapeSpacing/2, kShapeSpacing/2, dimPaint); - - shapePaint.setAlpha(255 * shapePaint.getAlpha() / maxSum); - } - } - - switch (shape) { - case kSquare_Shape: - canvas->drawRectCoords(-kShapeSize/2, -kShapeSize/2, kShapeSize/2, kShapeSize/2, - shapePaint); - break; - - case kDiamond_Shape: - canvas->save(); - canvas->rotate(45); - canvas->drawRectCoords(-kShapeSize/2, -kShapeSize/2, kShapeSize/2, kShapeSize/2, - shapePaint); - canvas->restore(); - break; - - case kOval_Shape: - canvas->save(); - canvas->rotate(static_cast<SkScalar>((511 * xfermodeIdx + 257) % 360)); - canvas->drawArc(SkRect::MakeLTRB(-kShapeSize/2, -1.4f * kShapeSize/2, - kShapeSize/2, 1.4f * kShapeSize/2), - 0, 360, true, shapePaint); - canvas->restore(); - break; - - default: - SkFAIL("Invalid shape."); - } -} - -////////////////////////////////////////////////////////////////////////////// - -static GM* MyFactory(void*) { return new AAXfermodesGM; } -static GMRegistry reg(MyFactory); - -} diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index e56175b58e..01f70f119a 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -80,6 +80,7 @@ '<(skia_src_path)/gpu/GrBatchTarget.h', '<(skia_src_path)/gpu/GrBatchTest.cpp', '<(skia_src_path)/gpu/GrBatchTest.h', + '<(skia_src_path)/gpu/GrBlend.cpp', '<(skia_src_path)/gpu/GrBlend.h', '<(skia_src_path)/gpu/GrBufferAllocPool.cpp', '<(skia_src_path)/gpu/GrBufferAllocPool.h', diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h index 9ccc638fc9..f5757b93f5 100644 --- a/include/gpu/GrColor.h +++ b/include/gpu/GrColor.h @@ -142,8 +142,6 @@ enum GrColorComponentFlags { kB_GrColorComponentFlag = 1 << (GrColor_SHIFT_B / 8), kA_GrColorComponentFlag = 1 << (GrColor_SHIFT_A / 8), - kNone_GrColorComponentFlags = 0, - kRGB_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag | kB_GrColorComponentFlag), @@ -151,8 +149,6 @@ enum GrColorComponentFlags { kB_GrColorComponentFlag | kA_GrColorComponentFlag) }; -GR_MAKE_BITFIELD_OPS(GrColorComponentFlags) - static inline char GrColorComponentFlagToChar(GrColorComponentFlags component) { SkASSERT(SkIsPow2(component)); switch (component) { diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h index 85e5aa04ed..8458a620fe 100644 --- a/include/gpu/GrXferProcessor.h +++ b/include/gpu/GrXferProcessor.h @@ -51,6 +51,10 @@ enum GrBlendEquation { static const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1; +inline bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { + return equation >= kFirstAdvancedGrBlendEquation; +} + /** * Coeffecients for alpha-blending. */ @@ -139,6 +143,10 @@ public: */ kOverrideColor_OptFlag = 0x8, /** + * Set CoverageDrawing_StateBit + */ + kSetCoverageDrawing_OptFlag = 0x10, + /** * Can tweak alpha for coverage. Currently this flag should only be used by a batch */ kCanTweakAlphaForCoverage_OptFlag = 0x20, diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h index 56ddb372b4..481b373c10 100644 --- a/include/gpu/effects/GrPorterDuffXferProcessor.h +++ b/include/gpu/effects/GrPorterDuffXferProcessor.h @@ -24,7 +24,7 @@ public: GrXPFactory::InvariantOutput*) const override; private: - GrPorterDuffXPFactory(SkXfermode::Mode); + GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst); GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrProcOptInfo& colorPOI, @@ -37,15 +37,14 @@ private: bool onIsEqual(const GrXPFactory& xpfBase) const override { const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>(); - return fXfermode == xpf.fXfermode; + return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff); } GR_DECLARE_XP_FACTORY_TEST; - static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary); - SkXfermode::Mode fXfermode; + GrBlendCoeff fSrcCoeff; + GrBlendCoeff fDstCoeff; - friend class GrPorterDuffTest; // for TestGetXPOutputTypes() typedef GrXPFactory INHERITED; }; 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; + } +} diff --git a/src/gpu/GrBlend.h b/src/gpu/GrBlend.h index 05d7ebcfdc..e5b8993377 100644 --- a/src/gpu/GrBlend.h +++ b/src/gpu/GrBlend.h @@ -7,22 +7,13 @@ */ #include "GrTypes.h" -#include "SkTLogic.h" +#include "GrColor.h" #include "GrXferProcessor.h" #ifndef GrBlend_DEFINED #define GrBlend_DEFINED -template<GrBlendCoeff Coeff> -struct GrTBlendCoeffRefsSrc : SkTBool<kSC_GrBlendCoeff == Coeff || - kISC_GrBlendCoeff == Coeff || - kSA_GrBlendCoeff == Coeff || - kISA_GrBlendCoeff == Coeff> {}; - -#define GR_BLEND_COEFF_REFS_SRC(COEFF) \ - GrTBlendCoeffRefsSrc<COEFF>::value - -inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) { +static inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) { switch (coeff) { case kSC_GrBlendCoeff: case kISC_GrBlendCoeff: @@ -34,17 +25,7 @@ inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) { } } - -template<GrBlendCoeff Coeff> -struct GrTBlendCoeffRefsDst : SkTBool<kDC_GrBlendCoeff == Coeff || - kIDC_GrBlendCoeff == Coeff || - kDA_GrBlendCoeff == Coeff || - kIDA_GrBlendCoeff == Coeff> {}; - -#define GR_BLEND_COEFF_REFS_DST(COEFF) \ - GrTBlendCoeffRefsDst<COEFF>::value - -inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) { +static inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) { switch (coeff) { case kDC_GrBlendCoeff: case kIDC_GrBlendCoeff: @@ -56,88 +37,10 @@ inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) { } } - -template<GrBlendCoeff Coeff> -struct GrTBlendCoeffRefsSrc2 : SkTBool<kS2C_GrBlendCoeff == Coeff || - kIS2C_GrBlendCoeff == Coeff || - kS2A_GrBlendCoeff == Coeff || - kIS2A_GrBlendCoeff == Coeff> {}; - -#define GR_BLEND_COEFF_REFS_SRC2(COEFF) \ - GrTBlendCoeffRefsSrc2<COEFF>::value - - -template<GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> -struct GrTBlendCoeffsUseSrcColor : SkTBool<kZero_GrBlendCoeff != SrcCoeff || - GR_BLEND_COEFF_REFS_SRC(DstCoeff)> {}; - -#define GR_BLEND_COEFFS_USE_SRC_COLOR(SRC_COEFF, DST_COEFF) \ - GrTBlendCoeffsUseSrcColor<SRC_COEFF, DST_COEFF>::value - - -template<GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> -struct GrTBlendCoeffsUseDstColor : SkTBool<GR_BLEND_COEFF_REFS_DST(SrcCoeff) || - kZero_GrBlendCoeff != DstCoeff> {}; - -#define GR_BLEND_COEFFS_USE_DST_COLOR(SRC_COEFF, DST_COEFF) \ - GrTBlendCoeffsUseDstColor<SRC_COEFF, DST_COEFF>::value - - -template<GrBlendEquation Equation> -struct GrTBlendEquationIsAdvanced : SkTBool<Equation >= kFirstAdvancedGrBlendEquation> {}; - -#define GR_BLEND_EQUATION_IS_ADVANCED(EQUATION) \ - GrTBlendEquationIsAdvanced<EQUATION>::value - -inline bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { - return equation >= kFirstAdvancedGrBlendEquation; -} - - -template<GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> -struct GrTBlendModifiesDst : SkTBool<(kAdd_GrBlendEquation != BlendEquation && - kReverseSubtract_GrBlendEquation != BlendEquation) || - kZero_GrBlendCoeff != SrcCoeff || - kOne_GrBlendCoeff != DstCoeff> {}; - -#define GR_BLEND_MODIFIES_DST(EQUATION, SRC_COEFF, DST_COEFF) \ - GrTBlendModifiesDst<EQUATION, SRC_COEFF, DST_COEFF>::value - - -/** - * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) - * - * For "add" and "reverse subtract" the blend equation with f=coverage is: - * - * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D - * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) - * - * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the - * following relationship holds: - * - * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) - * - * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) - * - * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff - * does not reference S). For the dst term, this will work as long as the following is true: - *| - * dstCoeff' == f * dstCoeff + (1 - f) - * dstCoeff' == 1 - f * (1 - dstCoeff) - * - * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in - * dstCoeff references S. - */ -template<GrBlendEquation Equation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> -struct GrTBlendCanTweakAlphaForCoverage : SkTBool<GR_BLEND_EQUATION_IS_ADVANCED(Equation) || - ((kAdd_GrBlendEquation == Equation || - kReverseSubtract_GrBlendEquation == Equation) && - !GR_BLEND_COEFF_REFS_SRC(SrcCoeff) && - (kOne_GrBlendCoeff == DstCoeff || - kISC_GrBlendCoeff == DstCoeff || - kISA_GrBlendCoeff == DstCoeff))> {}; - -#define GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(EQUATION, SRC_COEFF, DST_COEFF) \ - GrTBlendCanTweakAlphaForCoverage<EQUATION, SRC_COEFF, DST_COEFF>::value +GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff, + GrBlendCoeff* dstCoeff, + GrColor srcColor, uint32_t srcCompFlags, + GrColor dstColor, uint32_t dstCompFlags, + GrColor constantColor); #endif diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp index de0143acea..43cdc400cc 100644 --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp @@ -17,299 +17,28 @@ #include "gl/builders/GrGLFragmentShaderBuilder.h" #include "gl/builders/GrGLProgramBuilder.h" -/** - * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. - */ -struct BlendFormula { -public: - /** - * Values the shader can write to primary and secondary outputs. These must all be modulated by - * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage. +static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff) { + /* + The fractional coverage is f. + The src and dst coeffs are Cs and Cd. + The dst and src colors are S and D. + We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha + we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second + term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we + find that only 1, ISA, and ISC produce the correct destination when applied to S' and D. */ - enum OutputType { - kNone_OutputType, //<! 0 - kCoverage_OutputType, //<! inputCoverage - kModulate_OutputType, //<! inputColor * inputCoverage - kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage - kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage - - kLast_OutputType = kISCModulate_OutputType - }; - - enum Properties { - kModifiesDst_Property = 1, - kUsesDstColor_Property = 1 << 1, - kUsesInputColor_Property = 1 << 2, - kCanTweakAlphaForCoverage_Property = 1 << 3, - - kLast_Property = kCanTweakAlphaForCoverage_Property - }; - - BlendFormula& operator =(const BlendFormula& other) { - fData = other.fData; - return *this; - } - - bool operator ==(const BlendFormula& other) const { - return fData == other.fData; - } - - bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; } - bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); } - bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); } - bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); } - bool canTweakAlphaForCoverage() const { - return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); - } - - /** - * Deduce the properties of a compile-time constant BlendFormula. - */ - template<OutputType PrimaryOut, OutputType SecondaryOut, - GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> - struct get_properties : SkTIntegralConstant<Properties, static_cast<Properties>( - - (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ? - kModifiesDst_Property : 0) | - - (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ? - kUsesDstColor_Property : 0) | - - ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff,DstCoeff)) || - (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ? - kUsesInputColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2. - - (kModulate_OutputType == PrimaryOut && - kNone_OutputType == SecondaryOut && - GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ? - kCanTweakAlphaForCoverage_Property : 0))> { - - // The provided formula should already be optimized. - GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) == - !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff)); - GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff)); - GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) == - !GR_BLEND_COEFF_REFS_SRC2(DstCoeff)); - GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut); - GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut); - }; - - union { - struct { - // We allot the enums one more bit than they require because MSVC seems to sign-extend - // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) - OutputType fPrimaryOutputType : 4; - OutputType fSecondaryOutputType : 4; - GrBlendEquation fBlendEquation : 6; - GrBlendCoeff fSrcCoeff : 6; - GrBlendCoeff fDstCoeff : 6; - Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); - }; - uint32_t fData; - }; - - GR_STATIC_ASSERT(kLast_OutputType < (1 << 3)); - GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5)); - GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5)); - GR_STATIC_ASSERT(kLast_Property < (1 << 6)); -}; - -GR_STATIC_ASSERT(4 == sizeof(BlendFormula)); - -GR_MAKE_BITFIELD_OPS(BlendFormula::Properties); - -/** - * Initialize a compile-time constant BlendFormula and automatically deduce fProps. - */ -#define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF, DST_COEFF) \ - {{{PRIMARY_OUT, \ - SECONDARY_OUT, \ - BLEND_EQUATION, SRC_COEFF, DST_COEFF, \ - BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \ - BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}}} - -/** - * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard - * Porter Duff formula. - */ -#define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \ - INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ - BlendFormula::kNone_OutputType, \ - kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF) - -/** - * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set - * the primary output type to none. - */ -#define DST_CLEAR_FORMULA \ - INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \ - BlendFormula::kNone_OutputType, \ - kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCoeff) - -/** - * When the coeffs are (Zero, One), we don't write to the dst at all. This formula has its own macro - * so we can set the primary output type to none. - */ -#define NO_DST_WRITE_FORMULA \ - INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \ - BlendFormula::kNone_OutputType, \ - kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoeff) - -/** - * When there is coverage, the equation with f=coverage is: - * - * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D - * - * This can be rewritten as: - * - * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) - * - * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the - * HW dst coeff with IS2C. - * - * Xfer modes: dst-atop (Sa!=1) - */ -#define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \ - INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ - ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \ - kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff) - -/** - * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: - * - * D' = f * D * dstCoeff + (1-f) * D - * - * This can be rewritten as: - * - * D' = D - D * [f * (1 - dstCoeff)] - * - * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse - * subtract HW blend equation with coeffs of (DC, One). - * - * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) - */ -#define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \ - INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \ - BlendFormula::kNone_OutputType, \ - kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff) - -/** - * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: - * - * D' = f * S * srcCoeff + (1-f) * D - * - * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff - * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) - * - * Xfer modes (Sa!=1): src, src-in, src-out - */ -#define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \ - INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ - BlendFormula::kCoverage_OutputType, \ - kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff) - -/** - * This table outlines the blend formulas we will use with each xfermode, with and without coverage, - * with and without an opaque input color. Optimization properties are deduced at compile time so we - * can make runtime decisions quickly. RGB coverage is not supported. - */ -static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = { - - /*>> Has coverage, input color unknown <<*/ {{ - - /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), - /* src */ COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff), - /* dst */ NO_DST_WRITE_FORMULA, - /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* src-in */ COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff), - /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType), - /* src-out */ COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff), - /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff), - /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), - /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), - /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType), - /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), - - }, /*>> No coverage, input color unknown <<*/ { - - /* clear */ DST_CLEAR_FORMULA, - /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst */ NO_DST_WRITE_FORMULA, - /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-in */ COEFF_FORMULA( kZero_GrBlendCoeff, kSA_GrBlendCoeff), - /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff), - /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kSA_GrBlendCoeff), - /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), - /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff), - /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), - - }}, /*>> Has coverage, input color opaque <<*/ {{ - - /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), - /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst */ NO_DST_WRITE_FORMULA, - /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-in */ NO_DST_WRITE_FORMULA, - /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), - /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), - /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), - /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType), - /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), - - }, /*>> No coverage, input color opaque <<*/ { - - /* clear */ DST_CLEAR_FORMULA, - /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst */ NO_DST_WRITE_FORMULA, - /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-in */ NO_DST_WRITE_FORMULA, - /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-out */ DST_CLEAR_FORMULA, - /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), - /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), - /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), - /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff), - /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), -}}}; - -static BlendFormula get_blend_formula(SkXfermode::Mode xfermode, - const GrProcOptInfo& colorPOI, - const GrProcOptInfo& coveragePOI) { - SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); - SkASSERT(!coveragePOI.isFourChannelOutput()); - - return gBlendTable[colorPOI.isOpaque()][coveragePOI.isSolidWhite()][xfermode]; -} - -static BlendFormula get_unoptimized_blend_formula(SkXfermode::Mode xfermode) { - SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); - - return gBlendTable[0][0][xfermode]; + return kOne_GrBlendCoeff == dstCoeff || + kISA_GrBlendCoeff == dstCoeff || + kISC_GrBlendCoeff == dstCoeff; } -/////////////////////////////////////////////////////////////////////////////// - class PorterDuffXferProcessor : public GrXferProcessor { public: - static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrDeviceCoordTexture* dstCopy, + static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, + GrColor constant, const GrDeviceCoordTexture* dstCopy, bool willReadDstColor) { - return SkNEW_ARGS(PorterDuffXferProcessor, (xfermode, dstCopy, willReadDstColor)); + return SkNEW_ARGS(PorterDuffXferProcessor, (srcBlend, dstBlend, constant, dstCopy, + willReadDstColor)); } ~PorterDuffXferProcessor() override; @@ -318,16 +47,49 @@ public: GrGLXferProcessor* createGLInstance() const override; - bool hasSecondaryOutput() const override { - return fBlendFormula.hasSecondaryOutput(); - } + bool hasSecondaryOutput() const override; + + /////////////////////////////////////////////////////////////////////////// + /// @name Stage Output Types + //// + + enum PrimaryOutputType { + kNone_PrimaryOutputType, + kColor_PrimaryOutputType, + kCoverage_PrimaryOutputType, + // Modulate color and coverage, write result as the color output. + kModulate_PrimaryOutputType, + // Custom Porter-Duff output, used for when we explictly are reading the dst and blending + // in the shader. Secondary Output must be none if you use this. The custom blend uses the + // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D + kCustom_PrimaryOutputType + }; + + enum SecondaryOutputType { + // There is no secondary output + kNone_SecondaryOutputType, + // Writes coverage as the secondary output. Only set if dual source blending is supported + // and primary output is kModulate. + kCoverage_SecondaryOutputType, + // Writes coverage * (1 - colorA) as the secondary output. Only set if dual source blending + // is supported and primary output is kModulate. + kCoverageISA_SecondaryOutputType, + // Writes coverage * (1 - colorRGBA) as the secondary output. Only set if dual source + // blending is supported and primary output is kModulate. + kCoverageISC_SecondaryOutputType, + + kSecondaryOutputTypeCnt, + }; - SkXfermode::Mode getXfermode() const { return fXfermode; } - BlendFormula getBlendFormula() const { return fBlendFormula; } + PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } + SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputType; } + + GrBlendCoeff getSrcBlend() const { return fSrcBlend; } + GrBlendCoeff getDstBlend() const { return fDstBlend; } private: - PorterDuffXferProcessor(SkXfermode::Mode, const GrDeviceCoordTexture* dstCopy, - bool willReadDstColor); + PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant, + const GrDeviceCoordTexture* dstCopy, bool willReadDstColor); GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, @@ -339,69 +101,49 @@ private: void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { if (!this->willReadDstColor()) { - blendInfo->fEquation = fBlendFormula.fBlendEquation; - blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; - blendInfo->fDstBlend = fBlendFormula.fDstCoeff; - blendInfo->fWriteColor = fBlendFormula.modifiesDst(); + blendInfo->fSrcBlend = fSrcBlend; + blendInfo->fDstBlend = fDstBlend; + } else { + blendInfo->fSrcBlend = kOne_GrBlendCoeff; + blendInfo->fDstBlend = kZero_GrBlendCoeff; } + blendInfo->fBlendConstant = fBlendConstant; } bool onIsEqual(const GrXferProcessor& xpBase) const override { const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); - return fXfermode == xp.fXfermode && - fBlendFormula == xp.fBlendFormula; + if (fSrcBlend != xp.fSrcBlend || + fDstBlend != xp.fDstBlend || + fBlendConstant != xp.fBlendConstant || + fPrimaryOutputType != xp.fPrimaryOutputType || + fSecondaryOutputType != xp.fSecondaryOutputType) { + return false; + } + return true; } - SkXfermode::Mode fXfermode; - BlendFormula fBlendFormula; + GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, + bool doesStencilWrite); + + void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrCaps& caps, + bool hasSolidCoverage); + + GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrColor fBlendConstant; + PrimaryOutputType fPrimaryOutputType; + SecondaryOutputType fSecondaryOutputType; typedef GrXferProcessor INHERITED; }; /////////////////////////////////////////////////////////////////////////////// -void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmentBuilder* fsBuilder, - BlendFormula::OutputType outputType, const char* output, - const char* inColor, const char* inCoverage) { - switch (outputType) { - case BlendFormula::kNone_OutputType: - fsBuilder->codeAppendf("%s = vec4(0.0);", output); - break; - case BlendFormula::kCoverage_OutputType: - fsBuilder->codeAppendf("%s = %s;", - output, xp.readsCoverage() ? inCoverage : "vec4(1.0)"); - break; - case BlendFormula::kModulate_OutputType: - if (xp.readsCoverage()) { - fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); - } else { - fsBuilder->codeAppendf("%s = %s;", output, inColor); - } - break; - case BlendFormula::kISAModulate_OutputType: - if (xp.readsCoverage()) { - fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); - } else { - fsBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor); - } - break; - case BlendFormula::kISCModulate_OutputType: - if (xp.readsCoverage()) { - fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage); - } else { - fsBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor); - } - break; - default: - SkFAIL("Unsupported output type."); - break; - } -} - -bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, SkXfermode::Coeff coeff, +bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, GrBlendCoeff coeff, const char* colorName, const char* srcColorName, const char* dstColorName, bool hasPrevious) { - if (SkXfermode::kZero_Coeff == coeff) { + if (kZero_GrBlendCoeff == coeff) { return hasPrevious; } else { if (hasPrevious) { @@ -409,30 +151,30 @@ bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, SkXfermode::Coeff } fsBuilder->codeAppendf("%s", colorName); switch (coeff) { - case SkXfermode::kOne_Coeff: + case kOne_GrBlendCoeff: break; - case SkXfermode::kSC_Coeff: + case kSC_GrBlendCoeff: fsBuilder->codeAppendf(" * %s", srcColorName); break; - case SkXfermode::kISC_Coeff: + case kISC_GrBlendCoeff: fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); break; - case SkXfermode::kDC_Coeff: + case kDC_GrBlendCoeff: fsBuilder->codeAppendf(" * %s", dstColorName); break; - case SkXfermode::kIDC_Coeff: + case kIDC_GrBlendCoeff: fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); break; - case SkXfermode::kSA_Coeff: + case kSA_GrBlendCoeff: fsBuilder->codeAppendf(" * %s.a", srcColorName); break; - case SkXfermode::kISA_Coeff: + case kISA_GrBlendCoeff: fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); break; - case SkXfermode::kDA_Coeff: + case kDA_GrBlendCoeff: fsBuilder->codeAppendf(" * %s.a", dstColorName); break; - case SkXfermode::kIDA_Coeff: + case kIDA_GrBlendCoeff: fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); break; default: @@ -451,13 +193,11 @@ public: static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) { const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); + b->add32(xp.primaryOutputType()); + b->add32(xp.secondaryOutputType()); if (xp.willReadDstColor()) { - b->add32(xp.getXfermode()); // Parent class includes willReadDstColor() in key. - } else { - b->add32(SkToInt(xp.readsCoverage()) | - (xp.getBlendFormula().fPrimaryOutputType << 1) | - (xp.getBlendFormula().fSecondaryOutputType << 4)); - GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); + b->add32(xp.getSrcBlend()); + b->add32(xp.getDstBlend()); } }; @@ -465,29 +205,58 @@ private: void onEmitCode(const EmitArgs& args) override { const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); - if (!xp.willReadDstColor()) { - BlendFormula blendFormula = xp.getBlendFormula(); - if (blendFormula.hasSecondaryOutput()) { - append_color_output(xp, fsBuilder, blendFormula.fSecondaryOutputType, - args.fOutputSecondary, args.fInputColor, args.fInputCoverage); + if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutputType()) { + SkASSERT(!xp.willReadDstColor()); + switch(xp.secondaryOutputType()) { + case PorterDuffXferProcessor::kNone_SecondaryOutputType: + break; + case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: + fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, + args.fInputCoverage); + break; + case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: + fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", + args.fOutputSecondary, args.fInputColor, + args.fInputCoverage); + break; + case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputType: + fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", + args.fOutputSecondary, args.fInputColor, + args.fInputCoverage); + break; + default: + SkFAIL("Unexpected Secondary Output"); + } + + switch (xp.primaryOutputType()) { + case PorterDuffXferProcessor::kNone_PrimaryOutputType: + fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); + break; + case PorterDuffXferProcessor::kColor_PrimaryOutputType: + fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputColor); + break; + case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: + fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); + break; + case PorterDuffXferProcessor::kModulate_PrimaryOutputType: + fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, + args.fInputCoverage); + break; + default: + SkFAIL("Unexpected Primary Output"); } - append_color_output(xp, fsBuilder, blendFormula.fPrimaryOutputType, - args.fOutputPrimary, args.fInputColor, args.fInputCoverage); } else { SkASSERT(xp.willReadDstColor()); - SkXfermode::Coeff srcCoeff, dstCoeff; - SkXfermode::ModeAsCoeff(xp.getXfermode(), &srcCoeff, &dstCoeff); - const char* dstColor = fsBuilder->dstColor(); fsBuilder->codeAppend("vec4 colorBlend ="); // append src blend - bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, + bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), args.fInputColor, args.fInputColor, dstColor, false); // append dst blend - SkAssertResult(append_porterduff_term(fsBuilder, dstCoeff, + SkAssertResult(append_porterduff_term(fsBuilder, xp.getDstBlend(), dstColor, args.fInputColor, dstColor, didAppend)); fsBuilder->codeAppend(";"); @@ -505,12 +274,17 @@ private: /////////////////////////////////////////////////////////////////////////////// -PorterDuffXferProcessor::PorterDuffXferProcessor(SkXfermode::Mode xfermode, +PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, + GrBlendCoeff dstBlend, + GrColor constant, const GrDeviceCoordTexture* dstCopy, bool willReadDstColor) : INHERITED(dstCopy, willReadDstColor) - , fXfermode(xfermode) - , fBlendFormula(get_unoptimized_blend_formula(xfermode)) { + , fSrcBlend(srcBlend) + , fDstBlend(dstBlend) + , fBlendConstant(constant) + , fPrimaryOutputType(kModulate_PrimaryOutputType) + , fSecondaryOutputType(kNone_SecondaryOutputType) { this->initClassID<PorterDuffXferProcessor>(); } @@ -532,40 +306,168 @@ PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, bool doesStencilWrite, GrColor* overrideColor, const GrCaps& caps) { + GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI, + coveragePOI, + doesStencilWrite); + this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); + return optFlags; +} + +void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags, + const GrCaps& caps, + bool hasSolidCoverage) { + if (this->willReadDstColor()) { + fPrimaryOutputType = kCustom_PrimaryOutputType; + return; + } + + if (optFlags & kIgnoreColor_OptFlag) { + if (optFlags & kIgnoreCoverage_OptFlag) { + fPrimaryOutputType = kNone_PrimaryOutputType; + return; + } else { + fPrimaryOutputType = kCoverage_PrimaryOutputType; + return; + } + } else if (optFlags & kIgnoreCoverage_OptFlag) { + fPrimaryOutputType = kColor_PrimaryOutputType; + return; + } + + // If we do have coverage determine whether it matters. Dual source blending is expensive so + // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source + // blending if we have any effective coverage stages OR the geometry processor doesn't emits + // solid coverage. + if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { + if (caps.shaderCaps()->dualSourceBlendingSupport()) { + if (kZero_GrBlendCoeff == fDstBlend) { + // write the coverage value to second color + fSecondaryOutputType = kCoverage_SecondaryOutputType; + fDstBlend = kIS2C_GrBlendCoeff; + } else if (kSA_GrBlendCoeff == fDstBlend) { + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. + fSecondaryOutputType = kCoverageISA_SecondaryOutputType; + fDstBlend = kIS2C_GrBlendCoeff; + } else if (kSC_GrBlendCoeff == fDstBlend) { + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. + fSecondaryOutputType = kCoverageISC_SecondaryOutputType; + fDstBlend = kIS2C_GrBlendCoeff; + } + } + } +} + +GrXferProcessor::OptFlags +PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, + bool doesStencilWrite) { if (this->willReadDstColor()) { return GrXferProcessor::kNone_Opt; } - fBlendFormula = get_blend_formula(fXfermode, colorPOI, coveragePOI); + bool srcAIsOne = colorPOI.isOpaque(); + bool hasCoverage = !coveragePOI.isSolidWhite(); + + bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || + (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); + bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || + (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); + + // When coeffs are (0,1) there is no reason to draw at all, unless + // stenciling is enabled. Having color writes disabled is effectively + // (0,1). + if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { + if (doesStencilWrite) { + return GrXferProcessor::kIgnoreColor_OptFlag | + GrXferProcessor::kSetCoverageDrawing_OptFlag; + } else { + fDstBlend = kOne_GrBlendCoeff; + return GrXferProcessor::kSkipDraw_OptFlag; + } + } - GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_Opt; - if (!fBlendFormula.modifiesDst()) { - if (!doesStencilWrite) { - optFlags |= GrXferProcessor::kSkipDraw_OptFlag; + // if we don't have coverage we can check whether the dst + // has to read at all. If not, we'll disable blending. + if (!hasCoverage) { + if (dstCoeffIsZero) { + if (kOne_GrBlendCoeff == fSrcBlend) { + // if there is no coverage and coeffs are (1,0) then we + // won't need to read the dst at all, it gets replaced by src + fDstBlend = kZero_GrBlendCoeff; + return GrXferProcessor::kNone_Opt | + GrXferProcessor::kIgnoreCoverage_OptFlag; + } else if (kZero_GrBlendCoeff == fSrcBlend) { + // if the op is "clear" then we don't need to emit a color + // or blend, just write transparent black into the dst. + fSrcBlend = kOne_GrBlendCoeff; + fDstBlend = kZero_GrBlendCoeff; + return GrXferProcessor::kIgnoreColor_OptFlag | + GrXferProcessor::kIgnoreCoverage_OptFlag; + } } - optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag | - GrXferProcessor::kIgnoreCoverage_OptFlag | - GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); - } else { - if (!fBlendFormula.usesInputColor()) { - optFlags |= GrXferProcessor::kIgnoreColor_OptFlag; + return GrXferProcessor::kIgnoreCoverage_OptFlag; + } + + // check whether coverage can be safely rolled into alpha + // of if we can skip color computation and just emit coverage + if (can_tweak_alpha_for_coverage(fDstBlend)) { + if (colorPOI.allStagesMultiplyInput()) { + return GrXferProcessor::kSetCoverageDrawing_OptFlag | + GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; + } else { + return GrXferProcessor::kSetCoverageDrawing_OptFlag; + } - if (coveragePOI.isSolidWhite()) { - optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag; + } + if (dstCoeffIsZero) { + if (kZero_GrBlendCoeff == fSrcBlend) { + // the source color is not included in the blend + // the dst coeff is effectively zero so blend works out to: + // (c)(0)D + (1-c)D = (1-c)D. + fDstBlend = kISA_GrBlendCoeff; + return GrXferProcessor::kIgnoreColor_OptFlag | + GrXferProcessor::kSetCoverageDrawing_OptFlag; + } else if (srcAIsOne) { + // the dst coeff is effectively zero so blend works out to: + // cS + (c)(0)D + (1-c)D = cS + (1-c)D. + // If Sa is 1 then we can replace Sa with c + // and set dst coeff to 1-Sa. + fDstBlend = kISA_GrBlendCoeff; + if (colorPOI.allStagesMultiplyInput()) { + return GrXferProcessor::kSetCoverageDrawing_OptFlag | + GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; + } else { + return GrXferProcessor::kSetCoverageDrawing_OptFlag; + + } } - if (colorPOI.allStagesMultiplyInput() && fBlendFormula.canTweakAlphaForCoverage()) { - optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; + } else if (dstCoeffIsOne) { + // the dst coeff is effectively one so blend works out to: + // cS + (c)(1)D + (1-c)D = cS + D. + fDstBlend = kOne_GrBlendCoeff; + if (colorPOI.allStagesMultiplyInput()) { + return GrXferProcessor::kSetCoverageDrawing_OptFlag | + GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; + } else { + return GrXferProcessor::kSetCoverageDrawing_OptFlag; + } + return GrXferProcessor::kSetCoverageDrawing_OptFlag; } - return optFlags; + return GrXferProcessor::kNone_Opt; +} + +bool PorterDuffXferProcessor::hasSecondaryOutput() const { + return kNone_SecondaryOutputType != fSecondaryOutputType; } /////////////////////////////////////////////////////////////////////////////// class PDLCDXferProcessor : public GrXferProcessor { public: - static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI); + static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, + const GrProcOptInfo& colorPOI); ~PDLCDXferProcessor() override; @@ -639,9 +541,9 @@ PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) this->initClassID<PDLCDXferProcessor>(); } -GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode, +GrXferProcessor* PDLCDXferProcessor::Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, const GrProcOptInfo& colorPOI) { - if (SkXfermode::kSrcOver_Mode != xfermode) { + if (kOne_GrBlendCoeff != srcBlend || kISA_GrBlendCoeff != dstBlend) { return NULL; } @@ -683,40 +585,91 @@ PDLCDXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, } /////////////////////////////////////////////////////////////////////////////// - -GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode) - : fXfermode(xfermode) { +GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) + : fSrcCoeff(src), fDstCoeff(dst) { this->initClassID<GrPorterDuffXPFactory>(); } -GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) { - static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode); - static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); - static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode); - static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); - static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); - static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); - static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); - static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); - static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); - static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); - static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); - static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode); - static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); - static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); - static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); - - static GrPorterDuffXPFactory* gFactories[] = { - &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF, - &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF, - &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF - }; - GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1); - - if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { - return NULL; +GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { + switch (mode) { + case SkXfermode::kClear_Mode: { + static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_GrBlendCoeff); + return SkRef(&gClearPDXPF); + break; + } + case SkXfermode::kSrc_Mode: { + static GrPorterDuffXPFactory gSrcPDXPF(kOne_GrBlendCoeff, kZero_GrBlendCoeff); + return SkRef(&gSrcPDXPF); + break; + } + case SkXfermode::kDst_Mode: { + static GrPorterDuffXPFactory gDstPDXPF(kZero_GrBlendCoeff, kOne_GrBlendCoeff); + return SkRef(&gDstPDXPF); + break; + } + case SkXfermode::kSrcOver_Mode: { + static GrPorterDuffXPFactory gSrcOverPDXPF(kOne_GrBlendCoeff, kISA_GrBlendCoeff); + return SkRef(&gSrcOverPDXPF); + break; + } + case SkXfermode::kDstOver_Mode: { + static GrPorterDuffXPFactory gDstOverPDXPF(kIDA_GrBlendCoeff, kOne_GrBlendCoeff); + return SkRef(&gDstOverPDXPF); + break; + } + case SkXfermode::kSrcIn_Mode: { + static GrPorterDuffXPFactory gSrcInPDXPF(kDA_GrBlendCoeff, kZero_GrBlendCoeff); + return SkRef(&gSrcInPDXPF); + break; + } + case SkXfermode::kDstIn_Mode: { + static GrPorterDuffXPFactory gDstInPDXPF(kZero_GrBlendCoeff, kSA_GrBlendCoeff); + return SkRef(&gDstInPDXPF); + break; + } + case SkXfermode::kSrcOut_Mode: { + static GrPorterDuffXPFactory gSrcOutPDXPF(kIDA_GrBlendCoeff, kZero_GrBlendCoeff); + return SkRef(&gSrcOutPDXPF); + break; + } + case SkXfermode::kDstOut_Mode: { + static GrPorterDuffXPFactory gDstOutPDXPF(kZero_GrBlendCoeff, kISA_GrBlendCoeff); + return SkRef(&gDstOutPDXPF); + break; + } + case SkXfermode::kSrcATop_Mode: { + static GrPorterDuffXPFactory gSrcATopPDXPF(kDA_GrBlendCoeff, kISA_GrBlendCoeff); + return SkRef(&gSrcATopPDXPF); + break; + } + case SkXfermode::kDstATop_Mode: { + static GrPorterDuffXPFactory gDstATopPDXPF(kIDA_GrBlendCoeff, kSA_GrBlendCoeff); + return SkRef(&gDstATopPDXPF); + break; + } + case SkXfermode::kXor_Mode: { + static GrPorterDuffXPFactory gXorPDXPF(kIDA_GrBlendCoeff, kISA_GrBlendCoeff); + return SkRef(&gXorPDXPF); + break; + } + case SkXfermode::kPlus_Mode: { + static GrPorterDuffXPFactory gPlusPDXPF(kOne_GrBlendCoeff, kOne_GrBlendCoeff); + return SkRef(&gPlusPDXPF); + break; + } + case SkXfermode::kModulate_Mode: { + static GrPorterDuffXPFactory gModulatePDXPF(kZero_GrBlendCoeff, kSC_GrBlendCoeff); + return SkRef(&gModulatePDXPF); + break; + } + case SkXfermode::kScreen_Mode: { + static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_GrBlendCoeff); + return SkRef(&gScreenPDXPF); + break; + } + default: + return NULL; } - return SkRef(gFactories[xfermode]); } GrXferProcessor* @@ -725,16 +678,16 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, const GrProcOptInfo& covPOI, const GrDeviceCoordTexture* dstCopy) const { if (covPOI.isFourChannelOutput()) { - return PDLCDXferProcessor::Create(fXfermode, colorPOI); + return PDLCDXferProcessor::Create(fSrcCoeff, fDstCoeff, colorPOI); } else { - return PorterDuffXferProcessor::Create(fXfermode, dstCopy, + return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, this->willReadDstColor(caps, colorPOI, covPOI)); } } bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, uint32_t knownColorFlags) const { - if (SkXfermode::kSrcOver_Mode == fXfermode && + if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && kRGBA_GrColorComponentFlags == knownColorFlags) { return true; } @@ -744,43 +697,103 @@ bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, GrXPFactory::InvariantOutput* output) const { - const BlendFormula& blendFormula = get_blend_formula(fXfermode, colorPOI, coveragePOI); - - if (blendFormula.usesDstColor()) { + if (!coveragePOI.isSolidWhite()) { output->fWillBlendWithDst = true; - output->fBlendedColorFlags = kNone_GrColorComponentFlags; + output->fBlendedColorFlags = 0; return; } - SkASSERT(coveragePOI.isSolidWhite()); - SkASSERT(kAdd_GrBlendEquation == blendFormula.fBlendEquation); + GrBlendCoeff srcCoeff = fSrcCoeff; + GrBlendCoeff dstCoeff = fDstCoeff; - output->fWillBlendWithDst = false; + // TODO: figure out to merge this simplify with other current optimization code paths and + // eventually remove from GrBlend + GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags(), + 0, 0, 0); + + if (GrBlendCoeffRefsDst(srcCoeff)) { + output->fWillBlendWithDst = true; + output->fBlendedColorFlags = 0; + return; + } + + if (kZero_GrBlendCoeff != dstCoeff) { + bool srcAIsOne = colorPOI.isOpaque(); + if (kISA_GrBlendCoeff != dstCoeff || !srcAIsOne) { + output->fWillBlendWithDst = true; + } + output->fBlendedColorFlags = 0; + return; + } - switch (blendFormula.fSrcCoeff) { + switch (srcCoeff) { case kZero_GrBlendCoeff: output->fBlendedColor = 0; output->fBlendedColorFlags = kRGBA_GrColorComponentFlags; - return; + break; case kOne_GrBlendCoeff: output->fBlendedColor = colorPOI.color(); output->fBlendedColorFlags = colorPOI.validFlags(); - return; + break; - // TODO: update if we ever use const color. + // The src coeff should never refer to the src and if it refers to dst then opaque + // should have been false. + case kSC_GrBlendCoeff: + case kISC_GrBlendCoeff: + case kDC_GrBlendCoeff: + case kIDC_GrBlendCoeff: + case kSA_GrBlendCoeff: + case kISA_GrBlendCoeff: + case kDA_GrBlendCoeff: + case kIDA_GrBlendCoeff: default: - output->fBlendedColorFlags = kNone_GrColorComponentFlags; - return; + SkFAIL("srcCoeff should not refer to src or dst."); + break; + + // TODO: update this once GrPaint actually has a const color. + case kConstC_GrBlendCoeff: + case kIConstC_GrBlendCoeff: + case kConstA_GrBlendCoeff: + case kIConstA_GrBlendCoeff: + output->fBlendedColorFlags = 0; + break; } + + output->fWillBlendWithDst = false; } bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI) const { - // Some formulas use dual source blending, so we fall back if it is required but not supported. - return !caps.shaderCaps()->dualSourceBlendingSupport() && - get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutput(); + // We can always blend correctly if we have dual source blending. + if (caps.shaderCaps()->dualSourceBlendingSupport()) { + return false; + } + + if (can_tweak_alpha_for_coverage(fDstCoeff)) { + return false; + } + + bool srcAIsOne = colorPOI.isOpaque(); + + if (kZero_GrBlendCoeff == fDstCoeff) { + if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { + return false; + } + } + + // Reduces to: coeffS * (Cov*S) + D + if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { + return false; + } + + // We can always blend correctly if we have solid coverage. + if (coveragePOI.isSolidWhite()) { + return false; + } + + return true; } GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); @@ -793,15 +806,3 @@ GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, return GrPorterDuffXPFactory::Create(mode); } -void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, - int* outPrimary, - int* outSecondary) { - if (!!strcmp(xp->name(), "Porter Duff")) { - *outPrimary = *outSecondary = -1; - return; - } - BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); - *outPrimary = blendFormula.fPrimaryOutputType; - *outSecondary = blendFormula.fSecondaryOutputType; -} - diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp deleted file mode 100644 index 79cee71333..0000000000 --- a/tests/GrPorterDuffTest.cpp +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkXfermode.h" -#include "Test.h" - -#if SK_SUPPORT_GPU - -#include "GrContextFactory.h" -#include "GrGpu.h" -#include "GrXferProcessor.h" -#include "effects/GrPorterDuffXferProcessor.h" - -//////////////////////////////////////////////////////////////////////////////// - -static void test_alpha_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps); -static void test_alpha_unknown_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps); -static void test_alpha_opaque_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps); -static void test_alpha_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps); -static void test_color_white_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps); -static void test_color_white_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps); - -DEF_GPUTEST(GrPorterDuff, reporter, factory) { - GrContext* ctx = factory->get(GrContextFactory::kNull_GLContextType); - if (!ctx) { - SkFAIL("Failed to create null context."); - return; - } - - const GrCaps& caps = *ctx->getGpu()->caps(); - if (!caps.shaderCaps()->dualSourceBlendingSupport()) { - SkFAIL("Null context does not support dual source blending."); - return; - } - - test_alpha_unknown_with_coverage(reporter, caps); - test_alpha_unknown_no_coverage(reporter, caps); - test_alpha_opaque_with_coverage(reporter, caps); - test_alpha_opaque_no_coverage(reporter, caps); - test_color_white_with_coverage(reporter, caps); - test_color_white_with_coverage(reporter, caps); - test_color_white_no_coverage(reporter, caps); -} - -//////////////////////////////////////////////////////////////////////////////// - -#define TEST_ASSERT(...) REPORTER_ASSERT(reporter, __VA_ARGS__) - -enum { - kNone_OutputType, - kCoverage_OutputType, - kModulate_OutputType, - kISAModulate_OutputType, - kISCModulate_OutputType -}; - -enum { - kNone_Opt = GrXferProcessor::kNone_Opt, - kSkipDraw_OptFlag = GrXferProcessor::kSkipDraw_OptFlag, - kIgnoreColor_OptFlag = GrXferProcessor::kIgnoreColor_OptFlag, - kIgnoreCoverage_OptFlag = GrXferProcessor::kIgnoreCoverage_OptFlag, - kCanTweakAlphaForCoverage_OptFlag = GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag -}; - -class GrPorterDuffTest { -public: - struct XPInfo { - XPInfo(skiatest::Reporter* reporter, SkXfermode::Mode xfermode, const GrCaps& caps, - const GrProcOptInfo& colorPOI, const GrProcOptInfo& covPOI) { - SkAutoTUnref<GrXPFactory> xpf(GrPorterDuffXPFactory::Create(xfermode)); - SkAutoTUnref<GrXferProcessor> xp(xpf->createXferProcessor(colorPOI, covPOI, 0, caps)); - TEST_ASSERT(!xpf->willNeedDstCopy(caps, colorPOI, covPOI)); - xpf->getInvariantOutput(colorPOI, covPOI, &fInvariantOutput); - fOptFlags = xp->getOptimizations(colorPOI, covPOI, false, 0, caps); - GetXPOutputTypes(xp, &fPrimaryOutputType, &fSecondaryOutputType); - xp->getBlendInfo(&fBlendInfo); - } - - GrXPFactory::InvariantOutput fInvariantOutput; - int fOptFlags; - int fPrimaryOutputType; - int fSecondaryOutputType; - GrXferProcessor::BlendInfo fBlendInfo; - }; - - static void GetXPOutputTypes(const GrXferProcessor* xp, int* outPrimary, int* outSecondary) { - GrPorterDuffXPFactory::TestGetXPOutputTypes(xp, outPrimary, outSecondary); - } -}; - -static void test_alpha_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, false); - covPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, true); - - SkASSERT(!colorPOI.isOpaque()); - SkASSERT(!colorPOI.isSolidWhite()); - SkASSERT(!covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2A_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2A_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2A_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -static void test_alpha_unknown_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, GrColorPackRGBA(229, 0, 154, 0), - kR_GrColorComponentFlag | kB_GrColorComponentFlag, false); - covPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kRGBA_GrColorComponentFlags, true); - - SkASSERT(!colorPOI.isOpaque()); - SkASSERT(!colorPOI.isSolidWhite()); - SkASSERT(covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(0 == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(229 == GrColorUnpackR(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT(154 == GrColorUnpackB(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT((kR_GrColorComponentFlag | - kB_GrColorComponentFlag) == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kSA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kSA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kSC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -static void test_alpha_opaque_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kA_GrColorComponentFlag, false); - covPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, true); - - SkASSERT(colorPOI.isOpaque()); - SkASSERT(!colorPOI.isSolidWhite()); - SkASSERT(!covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -static void test_alpha_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, GrColorPackRGBA(0, 82, 0, 255), - kG_GrColorComponentFlag | kA_GrColorComponentFlag, false); - covPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kRGBA_GrColorComponentFlags, true); - - SkASSERT(colorPOI.isOpaque()); - SkASSERT(!colorPOI.isSolidWhite()); - SkASSERT(covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(0 == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(82 == GrColorUnpackG(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT(255 == GrColorUnpackA(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT((kG_GrColorComponentFlag | - kA_GrColorComponentFlag) == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(82 == GrColorUnpackG(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT(255 == GrColorUnpackA(xpi.fInvariantOutput.fBlendedColor)); - TEST_ASSERT((kG_GrColorComponentFlag | - kA_GrColorComponentFlag) == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(0 == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kSC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -static void test_color_white_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kRGBA_GrColorComponentFlags, false); - covPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, true); - - SkASSERT(colorPOI.isOpaque()); - SkASSERT(colorPOI.isSolidWhite()); - SkASSERT(!covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISA_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kNone_Opt) == xpi.fOptFlags); - TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDC_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -static void test_color_white_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) { - GrProcOptInfo colorPOI, covPOI; - colorPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kRGBA_GrColorComponentFlags, false); - covPOI.calcWithInitialValues(NULL, 0, GrColorPackA4(255), kRGBA_GrColorComponentFlags, true); - - SkASSERT(colorPOI.isOpaque()); - SkASSERT(colorPOI.isSolidWhite()); - SkASSERT(covPOI.isSolidWhite()); - - for (int m = 0; m <= SkXfermode::kLastCoeffMode; m++) { - SkXfermode::Mode xfermode = static_cast<SkXfermode::Mode>(m); - const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, colorPOI, covPOI); - - switch (xfermode) { - case SkXfermode::kClear_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(0 == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrc_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(GrColorPackA4(255) == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDst_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOver_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(GrColorPackA4(255) == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOver_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstIn_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kSkipDraw_OptFlag | - kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(!xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcOut_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstOut_Mode: - TEST_ASSERT(!xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(0 == xpi.fInvariantOutput.fBlendedColor); - TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreColor_OptFlag | - kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kSrcATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kDstATop_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kXor_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kIDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kPlus_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kModulate_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kZero_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kSC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - case SkXfermode::kScreen_Mode: - TEST_ASSERT(xpi.fInvariantOutput.fWillBlendWithDst); - TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fInvariantOutput.fBlendedColorFlags); - TEST_ASSERT((kIgnoreCoverage_OptFlag | - kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags); - TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType); - TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType); - TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation); - TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend); - TEST_ASSERT(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend); - TEST_ASSERT(xpi.fBlendInfo.fWriteColor); - break; - default: - ERRORF(reporter, "Invalid xfermode."); - break; - } - } -} - -#endif - |