aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-09-15 09:31:40 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-15 09:31:40 -0700
commit723b0501e22373bb3e6c306daaceae02cda8a124 (patch)
tree06445fa22abb512bc651bc9c631cfc8f8e9c5de4
parent79bd2aee8ca328b688c8d421973f96bcd13fd12d (diff)
Add support for blending of LCD for all blend modes.
-rw-r--r--gm/lcdblendmodes.cpp133
-rw-r--r--include/gpu/effects/GrPorterDuffXferProcessor.h4
-rw-r--r--src/gpu/GrPipelineBuilder.cpp1
-rw-r--r--src/gpu/GrProcOptInfo.cpp4
-rw-r--r--src/gpu/GrProcOptInfo.h2
-rw-r--r--src/gpu/GrTextContext.cpp2
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp79
-rw-r--r--tests/GrPorterDuffTest.cpp197
8 files changed, 402 insertions, 20 deletions
diff --git a/gm/lcdblendmodes.cpp b/gm/lcdblendmodes.cpp
new file mode 100644
index 0000000000..a2494cc343
--- /dev/null
+++ b/gm/lcdblendmodes.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+/*
+ * Tests text rendering with LCD and the various blend modes.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+
+namespace skiagm {
+
+static const int kColWidth = 180;
+static const int kNumCols = 4;
+static const int kWidth = kColWidth * kNumCols;
+static const int kHeight = 750;
+
+static SkShader* make_shader(const SkRect& bounds) {
+ const SkPoint pts[] = {
+ { bounds.left(), bounds.top() },
+ { bounds.right(), bounds.bottom() },
+ };
+ const SkColor colors[] = {
+ SK_ColorRED, SK_ColorGREEN,
+ };
+ return SkGradientShader::CreateLinear(pts,
+ colors, nullptr, SK_ARRAY_COUNT(colors),
+ SkShader::kRepeat_TileMode);
+}
+
+class LcdBlendGM : public skiagm::GM {
+public:
+ LcdBlendGM() {
+ const int kPointSize = 25;
+ fTextHeight = SkIntToScalar(kPointSize);
+ }
+
+protected:
+ SkString onShortName() override {
+ SkString name("lcdblendmodes");
+ name.append(sk_tool_utils::major_platform_os_name());
+ return name;
+ }
+
+ SkISize onISize() override { return SkISize::Make(kWidth, kHeight); }
+
+ void onDraw(SkCanvas* canvas) override {
+ this->drawColumn(canvas, SK_ColorBLACK, SK_ColorWHITE, false);
+ canvas->translate(SkIntToScalar(kColWidth), 0);
+ this->drawColumn(canvas, SK_ColorWHITE, SK_ColorBLACK, false);
+ canvas->translate(SkIntToScalar(kColWidth), 0);
+ this->drawColumn(canvas, SK_ColorGREEN, SK_ColorMAGENTA, false);
+ canvas->translate(SkIntToScalar(kColWidth), 0);
+ this->drawColumn(canvas, SK_ColorCYAN, SK_ColorMAGENTA, true);
+ }
+
+ void drawColumn(SkCanvas* canvas, SkColor backgroundColor, SkColor textColor, bool useGrad) {
+ const struct {
+ SkXfermode::Mode fMode;
+ const char* fLabel;
+ } gModes[] = {
+ { SkXfermode::kClear_Mode, "Clear" },
+ { SkXfermode::kSrc_Mode, "Src" },
+ { SkXfermode::kDst_Mode, "Dst" },
+ { SkXfermode::kSrcOver_Mode, "SrcOver" },
+ { SkXfermode::kDstOver_Mode, "DstOver" },
+ { SkXfermode::kSrcIn_Mode, "SrcIn" },
+ { SkXfermode::kDstIn_Mode, "DstIn" },
+ { SkXfermode::kSrcOut_Mode, "SrcOut" },
+ { SkXfermode::kDstOut_Mode, "DstOut" },
+ { SkXfermode::kSrcATop_Mode, "SrcATop" },
+ { SkXfermode::kDstATop_Mode, "DstATop" },
+ { SkXfermode::kXor_Mode, "Xor" },
+ { SkXfermode::kPlus_Mode, "Plus" },
+ { SkXfermode::kModulate_Mode, "Modulate" },
+ { SkXfermode::kScreen_Mode, "Screen" },
+ { SkXfermode::kOverlay_Mode, "Overlay" },
+ { SkXfermode::kDarken_Mode, "Darken" },
+ { SkXfermode::kLighten_Mode, "Lighten" },
+ { SkXfermode::kColorDodge_Mode, "ColorDodge" },
+ { SkXfermode::kColorBurn_Mode, "ColorBurn" },
+ { SkXfermode::kHardLight_Mode, "HardLight" },
+ { SkXfermode::kSoftLight_Mode, "SoftLight" },
+ { SkXfermode::kDifference_Mode, "Difference" },
+ { SkXfermode::kExclusion_Mode, "Exclusion" },
+ { SkXfermode::kMultiply_Mode, "Multiply" },
+ { SkXfermode::kHue_Mode, "Hue" },
+ { SkXfermode::kSaturation_Mode, "Saturation" },
+ { SkXfermode::kColor_Mode, "Color" },
+ { SkXfermode::kLuminosity_Mode, "Luminosity" },
+ };
+ // Draw background rect
+ SkPaint backgroundPaint;
+ backgroundPaint.setColor(backgroundColor);
+ canvas->drawRectCoords(0, 0, SkIntToScalar(kColWidth), SkIntToScalar(kHeight),
+ backgroundPaint);
+ SkScalar y = fTextHeight;
+ for (size_t m = 0; m < SK_ARRAY_COUNT(gModes); m++) {
+ SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(gModes[m].fMode));
+ SkPaint paint;
+ paint.setColor(textColor);
+ paint.setAntiAlias(true);
+ paint.setSubpixelText(true);
+ paint.setLCDRenderText(true);
+ paint.setTextSize(fTextHeight);
+ paint.setXfermode(xfermode);
+ sk_tool_utils::set_portable_typeface(&paint);
+ if (useGrad) {
+ SkRect r;
+ r.setXYWH(0, y - fTextHeight, SkIntToScalar(kColWidth), fTextHeight);
+ paint.setShader(make_shader(r))->unref();
+ }
+ SkString string(gModes[m].fLabel);
+ canvas->drawText(gModes[m].fLabel, string.size(), 0, y, paint);
+ y+=fTextHeight;
+ }
+ }
+
+private:
+ SkScalar fTextHeight;
+ typedef skiagm::GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_GM( return new LcdBlendGM; )
+}
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index a26a89293e..d297e32908 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -18,7 +18,9 @@ class GrPorterDuffXPFactory : public GrXPFactory {
public:
static GrXPFactory* Create(SkXfermode::Mode mode);
- bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const override;
+ bool supportsRGBCoverage(GrColor /*knownColor*/, uint32_t /*knownColorFlags*/) const override {
+ return true;
+ }
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index cb3b4af77e..dbef6e8755 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -105,3 +105,4 @@ void GrPipelineBuilder::calcCoverageInvariantOutput(const GrDrawBatch* batch) co
fCoverageProcInfo.calcCoverageWithBatch(batch, fCoverageFragmentProcessors.begin(),
this->numCoverageFragmentProcessors());
}
+
diff --git a/src/gpu/GrProcOptInfo.cpp b/src/gpu/GrProcOptInfo.cpp
index d7f2d7f312..6a2584d5f9 100644
--- a/src/gpu/GrProcOptInfo.cpp
+++ b/src/gpu/GrProcOptInfo.cpp
@@ -33,11 +33,13 @@ void GrProcOptInfo::calcWithInitialValues(const GrFragmentProcessor * const proc
int cnt,
GrColor startColor,
GrColorComponentFlags flags,
- bool areCoverageStages) {
+ bool areCoverageStages,
+ bool isLCD) {
GrInitInvariantOutput out;
out.fIsSingleComponent = areCoverageStages;
out.fColor = startColor;
out.fValidFlags = flags;
+ out.fIsLCDCoverage = isLCD;
fInOut.reset(out);
this->internalCalc(processors, cnt, false);
}
diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h
index b46957e7a0..dd9374dd3a 100644
--- a/src/gpu/GrProcOptInfo.h
+++ b/src/gpu/GrProcOptInfo.h
@@ -31,7 +31,7 @@ public:
, fReadsFragPosition(false) {}
void calcWithInitialValues(const GrFragmentProcessor* const *, int cnt, GrColor startColor,
- GrColorComponentFlags, bool areCoverageStages);
+ GrColorComponentFlags, bool areCoverageStages, bool isLCD = false);
void calcColorWithBatch(const GrDrawBatch*, const GrFragmentProcessor* const[], int cnt);
void calcCoverageWithBatch(const GrDrawBatch*, const GrFragmentProcessor* const[], int cnt);
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 92a851bc5a..be62619783 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -80,7 +80,7 @@ void GrTextContext::drawPosText(GrDrawContext* dc, GrRenderTarget* rt,
bool GrTextContext::ShouldDisableLCD(const SkPaint& paint) {
if (paint.getShader() ||
- !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) ||
+ !SkXfermode::AsMode(paint.getXfermode(), nullptr) ||
paint.getMaskFilter() ||
paint.getRasterizer() ||
paint.getColorFilter() ||
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 5f34f75854..4c50e47ab9 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -31,6 +31,7 @@ public:
kNone_OutputType, //<! 0
kCoverage_OutputType, //<! inputCoverage
kModulate_OutputType, //<! inputColor * inputCoverage
+ kSAModulate_OutputType, //<! inputColor.a * inputCoverage
kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
@@ -139,6 +140,15 @@ GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
/**
+ * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
+ * LCD dst-out.
+ */
+#define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
+ INIT_BLEND_FORMULA(BlendFormula::kSAModulate_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.
*/
@@ -289,6 +299,24 @@ static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = {
/* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
}}};
+static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
+ /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
+ /* src */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
+ /* dst */ NO_DST_WRITE_FORMULA,
+ /* src-over */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
+ /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
+ /* src-in */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
+ /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
+ /* src-out */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
+ /* dst-out */ COEFF_FORMULA_SA_MODULATE( kZero_GrBlendCoeff, kISC_GrBlendCoeff),
+ /* src-atop */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
+ /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
+ /* xor */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
+ /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
+ /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
+ /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
+};
+
static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
bool hasMixedSamples,
@@ -300,6 +328,14 @@ static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
}
+static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
+ SkXfermode::Mode xfermode) {
+ SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
+ SkASSERT(coveragePOI.isFourChannelOutput());
+
+ return gLCDBlendTable[xfermode];
+}
+
///////////////////////////////////////////////////////////////////////////////
class PorterDuffXferProcessor : public GrXferProcessor {
@@ -363,6 +399,13 @@ static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen
fsBuilder->codeAppendf("%s = %s;", output, inColor);
}
break;
+ case BlendFormula::kSAModulate_OutputType:
+ if (xp.readsCoverage()) {
+ fsBuilder->codeAppendf("%s = %s.a * %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);
@@ -444,7 +487,9 @@ PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI,
if (coveragePOI.isSolidWhite()) {
optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
}
- if (colorPOI.allStagesMultiplyInput() && fBlendFormula.canTweakAlphaForCoverage()) {
+ if (colorPOI.allStagesMultiplyInput() &&
+ fBlendFormula.canTweakAlphaForCoverage() &&
+ !coveragePOI.isFourChannelOutput()) {
optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
}
}
@@ -579,7 +624,6 @@ public:
private:
void emitOutputsForBlendState(const EmitArgs& args) override {
GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
-
fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
args.fInputCoverage);
}
@@ -684,12 +728,18 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrProcOptInfo& covPOI,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
+ BlendFormula blendFormula;
if (covPOI.isFourChannelOutput()) {
- SkASSERT(!dstTexture || !dstTexture->texture());
- return PDLCDXferProcessor::Create(fXfermode, colorPOI);
+ if (SkXfermode::kSrcOver_Mode == fXfermode &&
+ kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
+ SkASSERT(!dstTexture || !dstTexture->texture());
+ return PDLCDXferProcessor::Create(fXfermode, colorPOI);
+ }
+ blendFormula = get_lcd_blend_formula(covPOI, fXfermode);
+ } else {
+ blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
}
- BlendFormula blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
}
@@ -698,15 +748,6 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
return new PorterDuffXferProcessor(blendFormula);
}
-bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
- uint32_t knownColorFlags) const {
- if (SkXfermode::kSrcOver_Mode == fXfermode &&
- kRGBA_GrColorComponentFlags == knownColorFlags) {
- return true;
- }
- return false;
-}
-
void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
InvariantBlendedColor* blendedColor) const {
// Find the blended color info based on the formula that does not have coverage.
@@ -745,8 +786,16 @@ bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
if (caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
}
+
+ // When we have four channel coverage we always need to read the dst in order to correctly
+ // blend. The one exception is when we are using srcover mode and we know the input color into
+ // the XP.
if (covPOI.isFourChannelOutput()) {
- return false; // The LCD XP will abort rather than doing a dst read.
+ if (SkXfermode::kSrcOver_Mode == fXfermode &&
+ kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
+ return false;
+ }
+ return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput();
}
// We fallback on the shader XP when the blend formula would use dual source blending but we
// don't have support for it.
diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp
index 87b7a2edfa..1328272a6a 100644
--- a/tests/GrPorterDuffTest.cpp
+++ b/tests/GrPorterDuffTest.cpp
@@ -26,6 +26,7 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
+static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const GrCaps& caps);
static void test_no_dual_source_blending(skiatest::Reporter* reporter);
DEF_GPUTEST(GrPorterDuff, reporter, factory) {
@@ -46,6 +47,7 @@ DEF_GPUTEST(GrPorterDuff, reporter, factory) {
test_color_opaque_with_coverage(reporter, caps);
test_color_opaque_no_coverage(reporter, caps);
test_lcd_coverage(reporter, caps);
+ test_lcd_coverage_fallback_case(reporter, caps);
test_no_dual_source_blending(reporter);
}
@@ -57,6 +59,7 @@ enum {
kNone_OutputType,
kCoverage_OutputType,
kModulate_OutputType,
+ kSAModulate_OutputType,
kISAModulate_OutputType,
kISCModulate_OutputType
};
@@ -98,6 +101,197 @@ public:
}
};
+static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
+ GrProcOptInfo colorPOI, covPOI;
+ colorPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, false);
+ // Setting 2nd to last value to false and last to true will force covPOI to LCD coverage.
+ covPOI.calcWithInitialValues(NULL, 0, 0, kNone_GrColorComponentFlags, false, true);
+
+ SkASSERT(!colorPOI.isOpaque());
+ SkASSERT(!colorPOI.isSolidWhite());
+ SkASSERT(!covPOI.isSolidWhite());
+ SkASSERT(covPOI.isFourChannelOutput());
+
+ 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(0 == xpi.fBlendedColor.fKnownColor);
+ TEST_ASSERT(kRGBA_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kDst_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
+ TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
+ TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
+ TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
+ TEST_ASSERT(kOne_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend);
+ TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kDstOver_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kDstIn_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kDstOut_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
+ TEST_ASSERT(kSAModulate_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(kISC_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kSrcATop_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
+ TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
+ TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
+ TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
+ TEST_ASSERT(kDA_GrBlendCoeff == xpi.fBlendInfo.fSrcBlend);
+ TEST_ASSERT(kIS2C_GrBlendCoeff == xpi.fBlendInfo.fDstBlend);
+ TEST_ASSERT(xpi.fBlendInfo.fWriteColor);
+ break;
+ case SkXfermode::kDstATop_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
+ TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
+ TEST_ASSERT(kSAModulate_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::kPlus_Mode:
+ TEST_ASSERT(xpi.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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.fBlendedColor.fWillBlendWithDst);
+ TEST_ASSERT(kNone_GrColorComponentFlags == xpi.fBlendedColor.fKnownColorFlags);
+ TEST_ASSERT((kNone_OptFlags) == 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_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrProcOptInfo colorPOI, covPOI;
colorPOI.calcWithInitialValues(nullptr, 0, 0, kNone_GrColorComponentFlags, false);
@@ -112,6 +306,7 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
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.fBlendedColor.fWillBlendWithDst);
@@ -897,7 +1092,7 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
}
}
-static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
+static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const GrCaps& caps) {
class : public GrVertexBatch {
void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
out->setKnownFourComponents(GrColorPackRGBA(123, 45, 67, 221));