Add support for blending of LCD for all blend modes.
BUG=skia: Review URL: https://codereview.chromium.org/1313623002
This commit is contained in:
parent
79bd2aee8c
commit
723b0501e2
133
gm/lcdblendmodes.cpp
Normal file
133
gm/lcdblendmodes.cpp
Normal file
@ -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; )
|
||||
}
|
@ -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;
|
||||
|
@ -105,3 +105,4 @@ void GrPipelineBuilder::calcCoverageInvariantOutput(const GrDrawBatch* batch) co
|
||||
fCoverageProcInfo.calcCoverageWithBatch(batch, fCoverageFragmentProcessors.begin(),
|
||||
this->numCoverageFragmentProcessors());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() ||
|
||||
|
@ -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
|
||||
|
||||
@ -138,6 +139,15 @@ GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
|
||||
BlendFormula::kNone_OutputType, \
|
||||
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.
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user