Make analysis optional to GrPipeline::init().

GrXPFactory::createXferProcessor now takes GrPipelineAnalysisColor and GrPipelineAnalysisCoverage rather than GrProcessorSet::FragmentProcessorAnalysis.

This will make it so ops do not have to retain the analysis or rerun it to create pipelines at flush time.

Change-Id: Ib28ba65de425b20c2647329275f209aec168c3df
Reviewed-on: https://skia-review.googlesource.com/10474
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Brian Salomon 2017-03-29 14:25:04 -04:00 committed by Skia Commit-Bot
parent 978533c302
commit 1c6025cc9d
19 changed files with 113 additions and 130 deletions

View File

@ -19,7 +19,10 @@
#include "ops/GrOp.h"
void GrPipeline::init(const InitArgs& args) {
SkASSERT(args.fAnalysis);
if (args.fAnalysis) {
SkASSERT(args.fAnalysis->outputColor() == args.fInputColor);
SkASSERT(args.fAnalysis->outputCoverage() == args.fInputCoverage);
}
SkASSERT(args.fRenderTarget);
fRenderTarget.reset(args.fRenderTarget);
@ -58,27 +61,33 @@ void GrPipeline::init(const InitArgs& args) {
sk_sp<GrXferProcessor> xferProcessor;
const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
if (xpFactory) {
xferProcessor.reset(xpFactory->createXferProcessor(*args.fAnalysis, hasMixedSamples,
xferProcessor.reset(xpFactory->createXferProcessor(args.fInputColor,
args.fInputCoverage, hasMixedSamples,
&args.fDstTexture, *args.fCaps));
SkASSERT(xferProcessor);
} else {
// This may return nullptr in the common case of src-over implemented using hw blending.
xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
*args.fCaps, *args.fAnalysis, hasMixedSamples, &args.fDstTexture));
*args.fCaps, args.fInputColor, args.fInputCoverage, hasMixedSamples,
&args.fDstTexture));
}
fXferProcessor.reset(xferProcessor.get());
}
// This is for the legacy GrPipeline creation in GrMeshDrawOp where analysis does not
// eliminate fragment processors from GrProcessorSet.
GrColor overrideColor = GrColor_ILLEGAL;
int colorFPsToEliminate =
args.fAnalysis->getInputColorOverrideAndColorProcessorEliminationCount(&overrideColor);
colorFPsToEliminate = SkTMax(colorFPsToEliminate, 0);
if (args.fAnalysis->isInputColorIgnored()) {
// No need to have an override color if it isn't even going to be used.
overrideColor = GrColor_ILLEGAL;
colorFPsToEliminate = args.fProcessors->numColorFragmentProcessors();
// This is for the legacy GrPipeline creation in GrMeshDrawOp where analysis does not eliminate
// fragment processors from GrProcessorSet.
int colorFPsToEliminate = 0;
if (args.fAnalysis) {
GrColor overrideColor = GrColor_ILLEGAL;
colorFPsToEliminate =
args.fAnalysis->getInputColorOverrideAndColorProcessorEliminationCount(
&overrideColor);
colorFPsToEliminate = SkTMax(colorFPsToEliminate, 0);
if (args.fAnalysis->isInputColorIgnored()) {
// No need to have an override color if it isn't even going to be used.
overrideColor = GrColor_ILLEGAL;
colorFPsToEliminate = args.fProcessors->numColorFragmentProcessors();
}
}
// Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline, possibly removing some of the

View File

@ -57,7 +57,10 @@ public:
uint32_t fFlags = 0;
GrDrawFace fDrawFace = GrDrawFace::kBoth;
const GrProcessorSet* fProcessors = nullptr;
const GrProcessorSet::FragmentProcessorAnalysis* fAnalysis;
GrPipelineAnalysisColor fInputColor;
GrPipelineAnalysisCoverage fInputCoverage = GrPipelineAnalysisCoverage::kNone;
// This is only used for GrMeshDrawOp's legacy pipeline creation system.
const GrProcessorSet::FragmentProcessorAnalysis* fAnalysis = nullptr;
const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
const GrAppliedClip* fAppliedClip = nullptr;
GrRenderTarget* fRenderTarget = nullptr;

View File

@ -51,6 +51,13 @@ public:
return false;
}
bool operator==(const GrPipelineAnalysisColor& that) const {
if (fFlags != that.fFlags) {
return false;
}
return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
}
private:
enum Flags {
kColorIsKnown_Flag = 0x1,

View File

@ -119,8 +119,7 @@ void GrProcessorSet::FragmentProcessorAnalysis::internalInit(
GrPipelineAnalysisColor outputColor = colorInfo.outputColor();
if (outputColor.isConstant(&fKnownOutputColor)) {
fOutputColorType = static_cast<unsigned>(outputColor.isOpaque() ? ColorType::kOpaqueConstant
: ColorType::kConstant);
fOutputColorType = static_cast<unsigned>(ColorType::kConstant);
} else if (outputColor.isOpaque()) {
fOutputColorType = static_cast<unsigned>(ColorType::kOpaque);
} else {

View File

@ -128,27 +128,24 @@ public:
}
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
bool isInputColorIgnored() const { return fIgnoresInputColor; }
bool isOutputColorOpaque() const {
return ColorType::kOpaque == this->outputColorType() ||
ColorType::kOpaqueConstant == this->outputColorType();
}
bool hasKnownOutputColor(GrColor* color = nullptr) const {
bool constant = ColorType::kConstant == this->outputColorType() ||
ColorType::kOpaqueConstant == this->outputColorType();
if (constant && color) {
*color = fKnownOutputColor;
}
return constant;
}
GrPipelineAnalysisCoverage outputCoverageType() const {
GrPipelineAnalysisCoverage outputCoverage() const {
return static_cast<GrPipelineAnalysisCoverage>(fOutputCoverageType);
}
bool hasCoverage() const {
return this->outputCoverageType() != GrPipelineAnalysisCoverage::kNone;
GrPipelineAnalysisColor outputColor() const {
switch (this->outputColorType()) {
case ColorType::kConstant:
return fKnownOutputColor;
case ColorType::kOpaque:
return GrPipelineAnalysisColor::Opaque::kYes;
case ColorType::kUnknown:
return GrPipelineAnalysisColor::Opaque::kNo;
}
SkFAIL("Unexpected color type");
return GrPipelineAnalysisColor::Opaque::kNo;
}
private:
enum class ColorType : unsigned { kUnknown, kOpaqueConstant, kConstant, kOpaque };
enum class ColorType : unsigned { kUnknown, kConstant, kOpaque };
ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }

View File

@ -1742,6 +1742,8 @@ uint32_t GrRenderTargetContext::addMeshDrawOp(const GrPipelineBuilder& pipelineB
args.fRenderTarget = rt;
args.fCaps = this->caps();
args.fAnalysis = &analysis;
args.fInputColor = analysis.outputColor();
args.fInputCoverage = analysis.outputCoverage();
if (analysis.requiresDstTexture()) {
this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);

View File

@ -189,21 +189,11 @@ GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
return result;
}
GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis,
GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineAnalysisColor& color,
GrPipelineAnalysisCoverage coverage,
bool hasMixedSamples,
const DstTexture* dstTexture,
const GrCaps& caps) const {
#ifdef SK_DEBUG
if (analysis.requiresDstTexture()) {
if (!caps.shaderCaps()->dstReadInShaderSupport()) {
SkASSERT(dstTexture && dstTexture->texture());
} else {
SkASSERT(!dstTexture || !dstTexture->texture());
}
} else {
SkASSERT(!dstTexture || !dstTexture->texture());
}
SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
#endif
return this->onCreateXferProcessor(caps, analysis, hasMixedSamples, dstTexture);
return this->onCreateXferProcessor(caps, color, coverage, hasMixedSamples, dstTexture);
}

View File

@ -268,7 +268,8 @@ public:
typedef GrXferProcessor::DstTexture DstTexture;
GrXferProcessor* createXferProcessor(const FragmentProcessorAnalysis&,
GrXferProcessor* createXferProcessor(const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage,
bool hasMixedSamples,
const DstTexture*,
const GrCaps& caps) const;
@ -293,7 +294,8 @@ protected:
private:
virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage,
bool hasMixedSamples,
const DstTexture*) const = 0;

View File

@ -218,11 +218,11 @@ const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool inv
return nullptr;
}
GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage,
bool hasMixedSamples,
const DstTexture*) const {
// We don't support inverting coverage with mixed samples. We don't expect to ever want this in
// the future, however we could at some point make this work using an inverted coverage
// modulation table. Note that an inverted table still won't work if there are coverage procs.

View File

@ -30,9 +30,8 @@ public:
private:
constexpr GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
GrXferProcessor* onCreateXferProcessor(const GrCaps&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
GrXferProcessor* onCreateXferProcessor(const GrCaps&, const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage, bool hasMixedSamples,
const DstTexture*) const override;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,

View File

@ -213,9 +213,8 @@ public:
: fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {}
private:
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage, bool hasMixedSamples,
const DstTexture*) const override;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
@ -234,11 +233,12 @@ private:
#endif
GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage coverage,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
if (can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps)) {
if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) {
SkASSERT(!dstTexture || !dstTexture->texture());
return new CustomXP(fMode, fHWBlendEquation);
}

View File

@ -81,11 +81,11 @@ void DisableColorXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const
}
///////////////////////////////////////////////////////////////////////////////
GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage,
bool hasMixedSamples,
const DstTexture* dst) const {
return DisableColorXP::Create();
}

View File

@ -31,9 +31,8 @@ private:
AnalysisProperties::kIgnoresInputColor;
}
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage, bool hasMixedSamples,
const DstTexture* dstTexture) const override;
GR_DECLARE_XP_FACTORY_TEST;

View File

@ -521,7 +521,7 @@ GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
class PDLCDXferProcessor : public GrXferProcessor {
public:
static GrXferProcessor* Create(SkBlendMode xfermode, const FragmentProcessorAnalysis& analysis);
static GrXferProcessor* Create(SkBlendMode xfermode, const GrPipelineAnalysisColor& inputColor);
~PDLCDXferProcessor() override;
@ -603,12 +603,12 @@ PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
}
GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode,
const FragmentProcessorAnalysis& analysis) {
const GrPipelineAnalysisColor& color) {
if (SkBlendMode::kSrcOver != xfermode) {
return nullptr;
}
GrColor blendConstant;
if (!analysis.hasKnownOutputColor(&blendConstant)) {
if (!color.isConstant(&blendConstant)) {
return nullptr;
}
blendConstant = GrUnpremulColor(blendConstant);
@ -698,25 +698,26 @@ const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
}
}
GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysisColor& color,
GrPipelineAnalysisCoverage coverage,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
BlendFormula blendFormula;
if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
if (coverage == GrPipelineAnalysisCoverage::kLCD) {
if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() &&
!caps.shaderCaps()->dualSourceBlendingSupport() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
// If we don't have dual source blending or in shader dst reads, we fall back to this
// trick for rendering SrcOver LCD text instead of doing a dst copy.
SkASSERT(!dstTexture || !dstTexture->texture());
return PDLCDXferProcessor::Create(fBlendMode, analysis);
return PDLCDXferProcessor::Create(fBlendMode, color);
}
blendFormula = get_lcd_blend_formula(fBlendMode);
} else {
blendFormula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
hasMixedSamples, fBlendMode);
blendFormula =
get_blend_formula(color.isOpaque(), GrPipelineAnalysisCoverage::kNone != coverage,
hasMixedSamples, fBlendMode);
}
if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
@ -809,15 +810,15 @@ const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
const GrPipelineAnalysisColor& color,
GrPipelineAnalysisCoverage coverage,
bool hasMixedSamples,
const GrXferProcessor::DstTexture* dstTexture) {
// We want to not make an xfer processor if possible. Thus for the simple case where we are not
// doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
// the general case where we convert a src-over blend that has solid coverage and an opaque
// color to src-mode, which allows disabling of blending.
if (analysis.outputCoverageType() != GrPipelineAnalysisCoverage::kLCD) {
if (coverage != GrPipelineAnalysisCoverage::kLCD) {
// We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
// We don't simply return the address of that XP here because our caller would have to unref
// it and since it is a global object and GrProgramElement's ref-cnting system is not thread
@ -825,13 +826,13 @@ GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
return nullptr;
}
if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dualSourceBlendingSupport() &&
if (color.isConstant() && !caps.shaderCaps()->dualSourceBlendingSupport() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
// If we don't have dual source blending or in shader dst reads, we fall
// back to this trick for rendering SrcOver LCD text instead of doing a
// dst copy.
SkASSERT(!dstTexture || !dstTexture->texture());
return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, analysis);
return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, color);
}
BlendFormula blendFormula;

View File

@ -24,7 +24,8 @@ public:
/** Because src-over is so common we special case it for performance reasons. If this returns
null then the SimpleSrcOverXP() below should be used. */
static GrXferProcessor* CreateSrcOverXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
const GrPipelineAnalysisColor& color,
GrPipelineAnalysisCoverage coverage,
bool hasMixedSamples,
const GrXferProcessor::DstTexture*);
@ -42,9 +43,8 @@ public:
private:
constexpr GrPorterDuffXPFactory(SkBlendMode);
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrPipelineAnalysisColor&,
GrPipelineAnalysisCoverage, bool hasMixedSamples,
const DstTexture*) const override;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,

View File

@ -466,6 +466,7 @@ void InstancedRendering::Op::onExecute(GrOpFlushState* state) {
state->gpu()->handleDirtyContext();
// TODO: Don't reanalyze the processors.
GrProcessorSet::FragmentProcessorAnalysis analysis;
GrPipelineAnalysisCoverage coverageInput;
if (GrAAType::kCoverage == fInfo.aaType() ||
@ -485,7 +486,8 @@ void InstancedRendering::Op::onExecute(GrOpFlushState* state) {
GrPipeline pipeline;
GrPipeline::InitArgs args;
args.fAnalysis = &analysis;
args.fInputColor = analysis.outputColor();
args.fInputCoverage = analysis.outputCoverage();
args.fAppliedClip = clip;
args.fCaps = &state->caps();
args.fProcessors = &fProcessors;

View File

@ -38,6 +38,7 @@ void GrDrawPathOpBase::initPipeline(const GrOpFlushState& state, GrPipeline* pip
0xffff>()
};
GrPipeline::InitArgs args;
auto analysis = this->fragmentProcessorAnalysis();
args.fProcessors = &this->processors();
args.fFlags = GrAA::kYes == fAA ? GrPipeline::kHWAntialias_Flag : 0;
args.fUserStencil = &kCoverPass;
@ -45,8 +46,8 @@ void GrDrawPathOpBase::initPipeline(const GrOpFlushState& state, GrPipeline* pip
args.fRenderTarget = state.drawOpArgs().fRenderTarget;
args.fCaps = &state.caps();
args.fDstTexture = state.drawOpArgs().fDstTexture;
args.fAnalysis =
&this->doFragmentProcessorAnalysis(state.caps(), state.drawOpArgs().fAppliedClip);
args.fInputColor = analysis.outputColor();
args.fInputCoverage = analysis.outputCoverage();
return pipeline->init(args);
}

View File

@ -96,11 +96,9 @@ static void construct_dummy_pipeline(GrRenderTargetContext* dc, GrPipeline* pipe
GrScissorState dummyScissor;
GrWindowRectsState dummyWindows;
GrProcessorSet::FragmentProcessorAnalysis analysis;
GrPipeline::InitArgs args;
dummyBuilder.getPipelineInitArgs(&args);
args.fRenderTarget = dc->accessRenderTarget();
args.fAnalysis = &analysis;
args.fCaps = dc->caps();
args.fDstTexture = GrXferProcessor::DstTexture();
pipeline->init(args);

View File

@ -66,7 +66,8 @@ public:
fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
fCanCombineOverlappedStencilAndCover = analysis.canCombineOverlappedStencilAndCover();
fIgnoresInputColor = analysis.isInputColorIgnored();
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
sk_sp<GrXferProcessor> xp(
xpf->createXferProcessor(inputColor, inputCoverage, false, nullptr, caps));
TEST_ASSERT(!analysis.requiresDstTexture());
GetXPOutputTypes(xp.get(), &fPrimaryOutputType, &fSecondaryOutputType);
xp->getBlendInfo(&fBlendInfo);
@ -987,39 +988,12 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
}
static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const GrCaps& caps) {
class TestLCDCoverageOp : public GrMeshDrawOp {
public:
DEFINE_OP_CLASS_ID
TestLCDCoverageOp() : INHERITED(ClassID()) {}
const char* name() const override { return "Test LCD Text Op"; }
private:
void getFragmentProcessorAnalysisInputs(
GrPipelineAnalysisColor* color,
GrPipelineAnalysisCoverage* coverage) const override {
color->setToConstant(GrColorPackRGBA(123, 45, 67, 221));
*coverage = GrPipelineAnalysisCoverage::kLCD;
}
void applyPipelineOptimizations(const PipelineOptimizations&) override {}
bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
void onPrepareDraws(Target*) const override {}
typedef GrMeshDrawOp INHERITED;
} testLCDCoverageOp;
GrProcessorSet::FragmentProcessorAnalysis analysis;
testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), nullptr, caps);
SkASSERT(analysis.hasKnownOutputColor());
SkASSERT(analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD);
TEST_ASSERT(!analysis.requiresDstTexture());
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver);
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
GrPipelineAnalysisColor color = GrColorPackRGBA(123, 45, 67, 221);
GrPipelineAnalysisCoverage coverage = GrPipelineAnalysisCoverage::kLCD;
SkASSERT(!(GrXPFactory::GetAnalysisProperties(xpf, color, coverage, caps) &
GrXPFactory::AnalysisProperties::kRequiresDstTexture));
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(color, coverage, false, nullptr, caps));
if (!xp) {
ERRORF(reporter, "Failed to create an XP with LCD coverage.");
return;
@ -1072,8 +1046,8 @@ DEF_GPUTEST(PorterDuffNoDualSourceBlending, reporter, /*factory*/) {
caps);
GrXferProcessor::DstTexture* dstTexture =
analysis.requiresDstTexture() ? &fakeDstTexture : nullptr;
sk_sp<GrXferProcessor> xp(
xpf->createXferProcessor(analysis, false, dstTexture, caps));
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(colorInput, coverageType, false,
dstTexture, caps));
if (!xp) {
ERRORF(reporter, "Failed to create an XP without dual source blending.");
return;