Remove GrXferProcessor::getOptimizations.

This replaces GrXferProcessor::getOptimizations with a new function on GrXPFactory. The results are made available via FragmentProcessorAnalysis.

Bug: skia:
Change-Id: I535985458c9d13ad858cac94e957e2fdbe332036
Reviewed-on: https://skia-review.googlesource.com/10218
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2017-03-28 16:32:05 -04:00 committed by Skia Commit-Bot
parent 02bb6df081
commit 318538484f
20 changed files with 440 additions and 486 deletions

View File

@ -212,6 +212,9 @@ struct GrTBlendModifiesDst : skstd::bool_constant<
*
* By inspection we can see this will work as long as dstCoeff has a 1, and any other term in
* dstCoeff references S.
*
* Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src
* color so folding in coverage is allowed.
*/
template<GrBlendEquation Equation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
struct GrTBlendCanTweakAlphaForCoverage : skstd::bool_constant<
@ -220,7 +223,8 @@ struct GrTBlendCanTweakAlphaForCoverage : skstd::bool_constant<
!GR_BLEND_COEFF_REFS_SRC(SrcCoeff) &&
(kOne_GrBlendCoeff == DstCoeff ||
kISC_GrBlendCoeff == DstCoeff ||
kISA_GrBlendCoeff == DstCoeff))> {};
kISA_GrBlendCoeff == DstCoeff)) ||
!GrTBlendModifiesDst<Equation, SrcCoeff, DstCoeff>::value> {};
#define GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(EQUATION, SRC_COEFF, DST_COEFF) \
GrTBlendCanTweakAlphaForCoverage<EQUATION, SRC_COEFF, DST_COEFF>::value

View File

@ -52,37 +52,32 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
bool isHWAA = kHWAntialias_Flag & args.fFlags;
// Create XferProcessor from DS's XPFactory
bool hasMixedSamples = args.fRenderTarget->isMixedSampled() && (isHWAA || isStencilEnabled());
const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
sk_sp<GrXferProcessor> xferProcessor;
if (xpFactory) {
xferProcessor.reset(xpFactory->createXferProcessor(*args.fAnalysis, 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));
{
bool hasMixedSamples =
args.fRenderTarget->isMixedSampled() && (isHWAA || this->isStencilEnabled());
sk_sp<GrXferProcessor> xferProcessor;
const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
if (xpFactory) {
xferProcessor.reset(xpFactory->createXferProcessor(*args.fAnalysis, 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));
}
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);
GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
&GrPorterDuffXPFactory::SimpleSrcOverXP();
optFlags = xpForOpts->getOptimizations(*args.fAnalysis);
// No need to have an override color if it isn't even going to be used.
if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) {
if (args.fAnalysis->isInputColorIgnored()) {
// No need to have an override color if it isn't even going to be used.
overrideColor = GrColor_ILLEGAL;
}
fXferProcessor.reset(xferProcessor.get());
if ((optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) {
colorFPsToEliminate = args.fProcessors->numColorFragmentProcessors();
}
@ -122,7 +117,7 @@ GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
if (args.fAnalysis->usesLocalCoords()) {
optimizations.fFlags |= GrPipelineOptimizations::kReadsLocalCoords_Flag;
}
if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
if (args.fAnalysis->isCompatibleWithCoverageAsAlpha()) {
optimizations.fFlags |= GrPipelineOptimizations::kCanTweakAlphaForCoverage_Flag;
}
return optimizations;

View File

@ -41,9 +41,11 @@ public:
bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
bool isConstant(GrColor* color) const {
bool isConstant(GrColor* color = nullptr) const {
if (kColorIsKnown_Flag & fFlags) {
*color = fColor;
if (color) {
*color = fColor;
}
return true;
}
return false;

View File

@ -65,20 +65,6 @@ public:
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Blending
////
/**
* Checks whether the xp will need destination in a texture to correctly blend.
*/
bool willXPNeedDstTexture(const GrCaps& caps,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) const {
return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis);
}
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Stencil

View File

@ -9,6 +9,7 @@
#include "GrAppliedClip.h"
#include "GrCaps.h"
#include "GrPipelineAnalysis.h"
#include "GrXferProcessor.h"
GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
fXPFactory = paint.fXPFactory;
@ -97,7 +98,7 @@ void GrProcessorSet::FragmentProcessorAnalysis::internalInit(
fps += processors.fColorFragmentProcessorCnt;
int n = processors.numCoverageFragmentProcessors();
bool hasCoverageFP = n > 0;
fUsesLocalCoords = colorInfo.usesLocalCoords();
bool coverageUsesLocalCoords = false;
for (int i = 0; i < n; ++i) {
if (!fps[i]->compatibleWithCoverageAsAlpha()) {
fCompatibleWithCoverageAsAlpha = false;
@ -105,12 +106,12 @@ void GrProcessorSet::FragmentProcessorAnalysis::internalInit(
// compatible with the coverage-as-alpha optimization.
GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
}
fUsesLocalCoords |= fps[i]->usesLocalCoords();
coverageUsesLocalCoords |= fps[i]->usesLocalCoords();
}
if (clipFP) {
fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
fUsesLocalCoords |= clipFP->usesLocalCoords();
coverageUsesLocalCoords |= clipFP->usesLocalCoords();
hasCoverageFP = true;
}
fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor);
@ -126,12 +127,44 @@ void GrProcessorSet::FragmentProcessorAnalysis::internalInit(
fOutputColorType = static_cast<unsigned>(ColorType::kUnknown);
}
GrPipelineAnalysisCoverage outputCoverage;
if (GrPipelineAnalysisCoverage::kLCD == coverageInput) {
fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kLCD);
outputCoverage = GrPipelineAnalysisCoverage::kLCD;
} else if (hasCoverageFP || GrPipelineAnalysisCoverage::kSingleChannel == coverageInput) {
fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kSingleChannel);
outputCoverage = GrPipelineAnalysisCoverage::kSingleChannel;
} else {
fOutputCoverageType = static_cast<unsigned>(GrPipelineAnalysisCoverage::kNone);
outputCoverage = GrPipelineAnalysisCoverage::kNone;
}
fOutputCoverageType = static_cast<unsigned>(outputCoverage);
GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
processors.fXPFactory, colorInfo.outputColor(), outputCoverage, caps);
if (!processors.numCoverageFragmentProcessors() &&
GrPipelineAnalysisCoverage::kNone == coverageInput) {
fCanCombineOverlappedStencilAndCover = SkToBool(
props & GrXPFactory::AnalysisProperties::kCanCombineOverlappedStencilAndCover);
} else {
// If we have non-clipping coverage processors we don't try to merge stencil steps as its
// unclear whether it will be correct. We don't expect this to happen in practice.
fCanCombineOverlappedStencilAndCover = false;
}
fRequiresDstTexture = SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
fIgnoresInputColor = SkToBool(props & GrXPFactory::AnalysisProperties::kIgnoresInputColor);
fCompatibleWithCoverageAsAlpha &=
SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
if (props & GrXPFactory::AnalysisProperties::kIgnoresInputColor) {
fInitialColorProcessorsToEliminate = processors.numColorFragmentProcessors();
// If the output of the last color stage is known then the kIgnoresInputColor optimization
// may depend upon it being the input to the xp.
if (!outputColor.isConstant(&fInputColor)) {
// Otherwise, the only property the XP factory could have relied upon to compute
// kIgnoresInputColor is opaqueness.
fInputColor = GrColor_WHITE;
}
fValidInputColor = true;
fUsesLocalCoords = coverageUsesLocalCoords;
} else {
fUsesLocalCoords = coverageUsesLocalCoords | colorInfo.usesLocalCoords();
}
}
@ -149,9 +182,12 @@ void GrProcessorSet::FragmentProcessorAnalysis::init(const GrPipelineAnalysisCol
GrProcessorSet::FragmentProcessorAnalysis::FragmentProcessorAnalysis(
const GrPipelineAnalysisColor& colorInput,
const GrPipelineAnalysisCoverage coverageInput,
const GrXPFactory* factory,
const GrCaps& caps)
: FragmentProcessorAnalysis() {
this->internalInit(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps);
GrPaint paint;
paint.setXPFactory(factory);
this->internalInit(colorInput, coverageInput, GrProcessorSet(std::move(paint)), nullptr, caps);
}
void GrProcessorSet::analyzeAndEliminateFragmentProcessors(

View File

@ -79,13 +79,16 @@ public:
: fIsInitializedWithProcessorSet(false)
, fCompatibleWithCoverageAsAlpha(true)
, fValidInputColor(false)
, fRequiresDstTexture(false)
, fCanCombineOverlappedStencilAndCover(true)
, fIgnoresInputColor(false)
, fOutputCoverageType(static_cast<unsigned>(GrPipelineAnalysisCoverage::kNone))
, fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
, fInitialColorProcessorsToEliminate(0) {}
// This version is used by a unit test that assumes no clip, no processors, and no PLS.
// This version is used by a unit test that assumes no clip and no fragment processors.
FragmentProcessorAnalysis(const GrPipelineAnalysisColor&, GrPipelineAnalysisCoverage,
const GrCaps&);
const GrXPFactory*, const GrCaps&);
void init(const GrPipelineAnalysisColor&, GrPipelineAnalysisCoverage, const GrProcessorSet&,
const GrAppliedClip*, const GrCaps&);
@ -119,7 +122,12 @@ public:
}
bool usesLocalCoords() const { return fUsesLocalCoords; }
bool requiresDstTexture() const { return fRequiresDstTexture; }
bool canCombineOverlappedStencilAndCover() const {
return fCanCombineOverlappedStencilAndCover;
}
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
bool isInputColorIgnored() const { return fIgnoresInputColor; }
bool isOutputColorOpaque() const {
return ColorType::kOpaque == this->outputColorType() ||
ColorType::kOpaqueConstant == this->outputColorType();
@ -154,11 +162,17 @@ public:
PackedBool fUsesLocalCoords : 1;
PackedBool fCompatibleWithCoverageAsAlpha : 1;
PackedBool fValidInputColor : 1;
PackedBool fRequiresDstTexture : 1;
PackedBool fCanCombineOverlappedStencilAndCover : 1;
// These could be removed if we created the XP from the XPFactory when doing analysis.
PackedBool fIgnoresInputColor : 1;
unsigned fOutputCoverageType : 2;
unsigned fOutputColorType : 2;
unsigned fInitialColorProcessorsToEliminate : 32 - 8;
unsigned fInitialColorProcessorsToEliminate : 32 - 11;
GrColor fInputColor;
// This could be removed if we created the XP from the XPFactory when doing analysis.
GrColor fKnownOutputColor;
friend class GrProcessorSet;

View File

@ -1743,7 +1743,7 @@ uint32_t GrRenderTargetContext::addMeshDrawOp(const GrPipelineBuilder& pipelineB
args.fCaps = this->caps();
args.fAnalysis = &analysis;
if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
if (analysis.requiresDstTexture()) {
this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
if (!args.fDstTexture.texture()) {
return SK_InvalidUniqueID;

View File

@ -29,11 +29,6 @@ GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
}
}
GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(
const FragmentProcessorAnalysis& analysis) const {
return this->onGetOptimizations(analysis);
}
bool GrXferProcessor::hasSecondaryOutput() const {
if (!this->willReadDstColor()) {
return this->onHasSecondaryOutput();
@ -175,39 +170,31 @@ SkString GrXferProcessor::BlendInfo::dump() const {
///////////////////////////////////////////////////////////////////////////////
bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& caps,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
bool result;
GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
const GrXPFactory* factory,
const GrPipelineAnalysisColor& color,
const GrPipelineAnalysisCoverage& coverage,
const GrCaps& caps) {
AnalysisProperties result;
if (factory) {
result = !caps.shaderCaps()->dstReadInShaderSupport() &&
factory->willReadDstInShader(caps, analysis);
result = factory->analysisProperties(color, coverage, caps);
} else {
result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis);
result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps);
}
SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture));
if ((result & AnalysisProperties::kReadsDstInShader) &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
result |= AnalysisProperties::kRequiresDstTexture;
}
return result;
}
bool GrXPFactory::CompatibleWithCoverageAsAlpha(const GrXPFactory* factory, bool colorIsOpaque) {
if (factory) {
return factory->compatibleWithCoverageAsAlpha(colorIsOpaque);
}
return GrPorterDuffXPFactory::SrcOverIsCompatibleWithCoverageAsAlpha();
}
bool GrXPFactory::CanCombineOverlappedStencilAndCover(const GrXPFactory* factory,
bool colorIsOpaque) {
if (factory) {
return factory->canCombineOverlappedStencilAndCover(colorIsOpaque);
}
return GrPorterDuffXPFactory::SrcOverCanCombineOverlappedStencilAndCover(colorIsOpaque);
}
GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture,
const GrCaps& caps) const {
#ifdef SK_DEBUG
if (this->willReadDstInShader(caps, analysis)) {
if (analysis.requiresDstTexture()) {
if (!caps.shaderCaps()->dstReadInShaderSupport()) {
SkASSERT(dstTexture && dstTexture->texture());
} else {

View File

@ -107,32 +107,6 @@ public:
the object. */
virtual GrGLSLXferProcessor* createGLSLInstance() const = 0;
/**
* Optimizations for blending / coverage that an OptDrawState should apply to itself.
*/
enum OptFlags {
/**
* GrXferProcessor will ignore color, thus no need to provide
*/
kIgnoreColor_OptFlag = 0x1,
/**
* Can tweak alpha for coverage.
*/
kCanTweakAlphaForCoverage_OptFlag = 0x2,
};
static const OptFlags kNone_OptFlags = (OptFlags)0;
GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);
/**
* Determines which optimizations (as described by the ptFlags above) can be performed by
* the draw with this xfer processor. If this function is called, the xfer processor may change
* its state to reflected the given blend optimizations. Callers are required to honor the
* returned OptFlags.
*/
OptFlags getOptimizations(const FragmentProcessorAnalysis&) const;
/**
* Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
* is updated to contain the type of barrier needed.
@ -224,8 +198,6 @@ protected:
private:
void notifyRefCntIsZero() const final {}
virtual OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const = 0;
/**
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
* processor's GL backend implementation.
@ -265,10 +237,6 @@ private:
typedef GrFragmentProcessor INHERITED;
};
GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
///////////////////////////////////////////////////////////////////////////////
/**
* We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
* known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
@ -305,22 +273,20 @@ public:
const DstTexture*,
const GrCaps& caps) const;
/**
* This will return true if the xfer processor needs the dst color in the shader and the way
* that the color will be made available to the xfer processor is by sampling a texture.
*/
static bool WillNeedDstTexture(const GrXPFactory*,
const GrCaps&,
const FragmentProcessorAnalysis&);
enum class AnalysisProperties : unsigned {
kNone = 0x0,
kReadsDstInShader = 0x1,
kRequiresDstTexture = 0x2,
kCompatibleWithAlphaAsCoverage = 0x4,
kIgnoresInputColor = 0x8,
kCanCombineOverlappedStencilAndCover = 0x10
};
GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(AnalysisProperties);
static bool CompatibleWithCoverageAsAlpha(const GrXPFactory*, bool colorIsOpaque);
/**
* This indicates whether the the xfer processor will produce the same bleneded color result
* if a series of overlapping stencil and cover operations are replaced by a series of stencil
* operations and a single cover. A uniform src color is assumed.
**/
static bool CanCombineOverlappedStencilAndCover(const GrXPFactory*, bool colorIsOpaque);
static AnalysisProperties GetAnalysisProperties(const GrXPFactory*,
const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&);
protected:
constexpr GrXPFactory() {}
@ -332,17 +298,17 @@ private:
const DstTexture*) const = 0;
/**
* Returns true if the XP generated by this factory will explicitly read dst in the fragment
* shader.
* Subclass analysis implementation. This should not return kNeedsDstInTexture as that will be
* inferred by the base class based on kReadsDstInShader and the caps.
*/
virtual bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
virtual bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const = 0;
virtual bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const { return false; }
virtual AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&) const = 0;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop
#endif
#endif
GR_MAKE_BITFIELD_CLASS_OPS(GrXPFactory::AnalysisProperties);
#endif

View File

@ -33,8 +33,6 @@ public:
private:
CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
@ -103,12 +101,6 @@ GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
return new GLCoverageSetOpXP(*this);
}
GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(
const FragmentProcessorAnalysis&) const {
// We never look at the color input
return GrXferProcessor::kIgnoreColor_OptFlag;
}
void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
switch (fRegionOp) {
case SkRegion::kReplace_Op:

View File

@ -35,11 +35,12 @@ private:
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
return false;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&) const override {
return AnalysisProperties::kIgnoresInputColor;
}
bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return false; }
GR_DECLARE_XP_FACTORY_TEST;

View File

@ -98,8 +98,6 @@ public:
}
private:
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
GrXferBarrierType onXferBarrier(const GrRenderTarget*, const GrCaps&) const override;
@ -189,11 +187,68 @@ bool CustomXP::onIsEqual(const GrXferProcessor& other) const {
return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation;
}
GrXferProcessor::OptFlags CustomXP::onGetOptimizations(
const FragmentProcessorAnalysis& analysis) const {
/*
Most the optimizations we do here are based on tweaking alpha for coverage.
GrXferBarrierType CustomXP::onXferBarrier(const GrRenderTarget* rt, const GrCaps& caps) const {
if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
return kBlend_GrXferBarrierType;
}
return kNone_GrXferBarrierType;
}
void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const {
if (this->hasHWBlendEquation()) {
blendInfo->fEquation = this->hwBlendEquation();
}
}
///////////////////////////////////////////////////////////////////////////////
// See the comment above GrXPFactory's definition about this warning suppression.
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
class CustomXPFactory : public GrXPFactory {
public:
constexpr CustomXPFactory(SkBlendMode mode)
: fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {}
private:
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&) const override;
GR_DECLARE_XP_FACTORY_TEST;
SkBlendMode fMode;
GrBlendEquation fHWBlendEquation;
typedef GrXPFactory INHERITED;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop
#endif
GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
if (can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps)) {
SkASSERT(!dstTexture || !dstTexture->texture());
return new CustomXP(fMode, fHWBlendEquation);
}
return new CustomXP(dstTexture, hasMixedSamples, fMode);
}
GrXPFactory::AnalysisProperties CustomXPFactory::analysisProperties(
const GrPipelineAnalysisColor&, const GrPipelineAnalysisCoverage& coverage,
const GrCaps& caps) const {
/*
The general SVG blend equation is defined in the spec as follows:
Dca' = B(Sc, Dc) * Sa * Da + Y * Sca * (1-Da) + Z * Dca * (1-Sa)
@ -287,76 +342,12 @@ GrXferProcessor::OptFlags CustomXP::onGetOptimizations(
= f*Sa - f*Sa * Da + Da
= f*Sa + Da - f*Sa * Da
= blend(f*Sa, Da)
*/
OptFlags flags = kNone_OptFlags;
if (analysis.isCompatibleWithCoverageAsAlpha()) {
flags |= kCanTweakAlphaForCoverage_OptFlag;
*/
if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) {
return AnalysisProperties::kCompatibleWithAlphaAsCoverage;
}
return flags;
}
GrXferBarrierType CustomXP::onXferBarrier(const GrRenderTarget* rt, const GrCaps& caps) const {
if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
return kBlend_GrXferBarrierType;
}
return kNone_GrXferBarrierType;
}
void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const {
if (this->hasHWBlendEquation()) {
blendInfo->fEquation = this->hwBlendEquation();
}
}
///////////////////////////////////////////////////////////////////////////////
// See the comment above GrXPFactory's definition about this warning suppression.
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
class CustomXPFactory : public GrXPFactory {
public:
constexpr CustomXPFactory(SkBlendMode mode)
: fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {}
private:
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return true; }
GR_DECLARE_XP_FACTORY_TEST;
SkBlendMode fMode;
GrBlendEquation fHWBlendEquation;
typedef GrXPFactory INHERITED;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop
#endif
GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
if (can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps)) {
SkASSERT(!dstTexture || !dstTexture->texture());
return new CustomXP(fMode, fHWBlendEquation);
}
return new CustomXP(dstTexture, hasMixedSamples, fMode);
}
bool CustomXPFactory::willReadDstInShader(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) const {
return !can_use_hw_blend_equation(fHWBlendEquation, analysis.outputCoverageType(), caps);
return AnalysisProperties::kCompatibleWithAlphaAsCoverage |
AnalysisProperties::kReadsDstInShader;
}
GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);

View File

@ -29,10 +29,6 @@ public:
private:
DisableColorXP();
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override {
return GrXferProcessor::kIgnoreColor_OptFlag;
}
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;

View File

@ -24,12 +24,13 @@ public:
private:
constexpr GrDisableColorXPFactory() {}
bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
return false;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&) const override {
return AnalysisProperties::kCompatibleWithAlphaAsCoverage |
AnalysisProperties::kIgnoresInputColor;
}
bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override { return true; }
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,

View File

@ -83,7 +83,7 @@ public:
(SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ?
kUsesInputColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2.
(kModulate_OutputType == PrimaryOut &&
((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
kNone_OutputType == SecondaryOut &&
GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ?
kCanTweakAlphaForCoverage_Property : 0))> {
@ -349,8 +349,6 @@ public:
BlendFormula getBlendFormula() const { return fBlendFormula; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
@ -445,24 +443,6 @@ GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
return new GLPorterDuffXferProcessor;
}
GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations(
const FragmentProcessorAnalysis& analysis) const {
GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
if (!fBlendFormula.modifiesDst()) {
optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
} else {
if (!fBlendFormula.usesInputColor()) {
optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
}
if (analysis.isCompatibleWithCoverageAsAlpha() &&
fBlendFormula.canTweakAlphaForCoverage()) {
optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
}
}
return optFlags;
}
///////////////////////////////////////////////////////////////////////////////
class ShaderPDXferProcessor : public GrXferProcessor {
@ -482,10 +462,6 @@ public:
SkBlendMode getXfermode() const { return fXfermode; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override {
return kNone_OptFlags;
}
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
bool onIsEqual(const GrXferProcessor& xpBase) const override {
@ -558,8 +534,6 @@ public:
private:
PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
@ -655,11 +629,6 @@ GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
return new GLPDLCDXferProcessor(*this);
}
GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations(
const FragmentProcessorAnalysis&) const {
return GrXferProcessor::kIgnoreColor_OptFlag;
}
///////////////////////////////////////////////////////////////////////////////
constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
@ -758,42 +727,53 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
return new PorterDuffXferProcessor(blendFormula);
}
bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const {
// Ignore the effect of coverage here.
BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode];
SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
return !colorFormula.usesDstColor();
}
bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) const {
if (caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
static inline GrXPFactory::AnalysisProperties analysis_properties(
const GrPipelineAnalysisColor& color, const GrPipelineAnalysisCoverage& coverage,
const GrCaps& caps, SkBlendMode mode) {
using AnalysisProperties = GrXPFactory::AnalysisProperties;
AnalysisProperties props = AnalysisProperties::kNone;
bool hasCoverage = GrPipelineAnalysisCoverage::kNone != coverage;
auto formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode];
if (formula.canTweakAlphaForCoverage()) {
props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage;
}
// 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 (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
// With dual-source blending we never need the destination color in the shader.
if (!caps.shaderCaps()->dualSourceBlendingSupport()) {
// Mixed samples implicity computes a fractional coverage from sample coverage. This could
// affect the formula used. However, we don't expect to have mixed samples without dual
// source blending.
SkASSERT(!caps.usesMixedSamples());
if (GrPipelineAnalysisCoverage::kLCD == coverage) {
// Check for special case of srcover with a known color which can be done using the
// blend constant.
if (SkBlendMode::kSrcOver == mode && color.isConstant()) {
props |= AnalysisProperties::kIgnoresInputColor;
} else {
if (get_lcd_blend_formula(mode).hasSecondaryOutput()) {
props |= AnalysisProperties::kReadsDstInShader;
}
}
} else if (formula.hasSecondaryOutput()) {
props |= AnalysisProperties::kReadsDstInShader;
}
return get_lcd_blend_formula(fBlendMode).hasSecondaryOutput();
}
// We fallback on the shader XP when the blend formula would use dual source blending but we
// don't have support for it.
static const bool kHasMixedSamples = false;
SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
auto formula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
kHasMixedSamples, fBlendMode);
return formula.hasSecondaryOutput();
if (!formula.modifiesDst() || !formula.usesInputColor()) {
props |= AnalysisProperties::kIgnoresInputColor;
}
// Ignore the effect of coverage here for overlap stencil and cover property
auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode];
SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
if (!colorFormula.usesDstColor()) {
props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover;
}
return props;
}
bool GrPorterDuffXPFactory::compatibleWithCoverageAsAlpha(bool colorIsOpaque) const {
// We assume we have coverage (or else this doesn't matter).
return gBlendTable[colorIsOpaque][1][(int)fBlendMode].canTweakAlphaForCoverage();
GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties(
const GrPipelineAnalysisColor& color,
const GrPipelineAnalysisCoverage& coverage,
const GrCaps& caps) const {
return analysis_properties(color, coverage, caps, fBlendMode);
}
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
@ -869,31 +849,9 @@ sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode ble
return sk_make_sp<PorterDuffXferProcessor>(formula);
}
bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) {
if (caps.shaderCaps()->dstReadInShaderSupport() ||
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 (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
}
auto formula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
return formula.hasSecondaryOutput();
}
// We fallback on the shader XP when the blend formula would use dual source blending but we
// don't have support for it.
static const bool kHasMixedSamples = false;
bool isOpaque = analysis.isOutputColorOpaque();
bool hasCoverage = analysis.hasCoverage();
SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
auto formula =
get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver);
return formula.hasSecondaryOutput();
GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties(
const GrPipelineAnalysisColor& color,
const GrPipelineAnalysisCoverage& coverage,
const GrCaps& caps) {
return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver);
}

View File

@ -35,25 +35,21 @@ public:
by reference because it is global and its ref-cnting methods are not thread safe. */
static const GrXferProcessor& SimpleSrcOverXP();
static bool WillSrcOverNeedDstTexture(const GrCaps&, const FragmentProcessorAnalysis&);
static bool SrcOverIsCompatibleWithCoverageAsAlpha() { return true; }
static bool SrcOverCanCombineOverlappedStencilAndCover(bool colorIsOpaque) {
return colorIsOpaque;
}
static AnalysisProperties SrcOverAnalysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&);
private:
constexpr GrPorterDuffXPFactory(SkBlendMode);
bool canCombineOverlappedStencilAndCover(bool colorIsOpaque) const override;
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
bool compatibleWithCoverageAsAlpha(bool colorIsOpaque) const override;
AnalysisProperties analysisProperties(const GrPipelineAnalysisColor&,
const GrPipelineAnalysisCoverage&,
const GrCaps&) const override;
GR_DECLARE_XP_FACTORY_TEST;
static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary);

View File

@ -367,13 +367,10 @@ bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAp
SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
this->getSingleDraw().fInstance.fColor = overrideColor;
}
fInfo.fCannotTweakAlphaForCoverage =
!analysis.isCompatibleWithCoverageAsAlpha() ||
!GrXPFactory::CompatibleWithCoverageAsAlpha(fProcessors.xpFactory(),
analysis.isOutputColorOpaque());
fInfo.fCannotTweakAlphaForCoverage = !analysis.isCompatibleWithCoverageAsAlpha();
fInfo.fUsesLocalCoords = analysis.usesLocalCoords();
return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis);
return analysis.requiresDstTexture();
}
void InstancedRendering::Op::wasRecorded() {

View File

@ -148,13 +148,7 @@ bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
GrPathRendering::kWinding_FillType != that->fillType()) {
return false;
}
// If we have non-clipping coverage processors we don't try to merge as its unclear whether it
// will be correct. We don't expect this to happen in practice.
if (this->processors().numCoverageFragmentProcessors()) {
return false;
}
bool opaque = this->fragmentProcessorAnalysis().isOutputColorOpaque();
if (!GrXPFactory::CanCombineOverlappedStencilAndCover(this->processors().xpFactory(), opaque)) {
if (!this->fragmentProcessorAnalysis().canCombineOverlappedStencilAndCover()) {
return false;
}
fTotalPathCount += that->fTotalPathCount;

View File

@ -29,8 +29,7 @@ protected:
return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
}
bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
return GrXPFactory::WillNeedDstTexture(fProcessorSet.xpFactory(), caps,
this->doFragmentProcessorAnalysis(caps, clip));
return this->doFragmentProcessorAnalysis(caps, clip).requiresDstTexture();
}
void wasRecorded() override { fProcessorSet.makePendingExecution(); }

View File

@ -21,7 +21,7 @@
////////////////////////////////////////////////////////////////////////////////
static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
static void test_color_not_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
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);
@ -35,7 +35,7 @@ DEF_GPUTEST_FOR_NULLGL_CONTEXT(GrPorterDuff, reporter, ctxInfo) {
}
test_color_unknown_with_coverage(reporter, caps);
test_color_unknown_no_coverage(reporter, caps);
test_color_not_opaque_no_coverage(reporter, caps);
test_color_opaque_with_coverage(reporter, caps);
test_color_opaque_no_coverage(reporter, caps);
test_lcd_coverage(reporter, caps);
@ -55,25 +55,19 @@ enum {
kISCModulate_OutputType
};
enum {
kNone_OptFlags = GrXferProcessor::kNone_OptFlags,
kIgnoreColor_OptFlag = GrXferProcessor::kIgnoreColor_OptFlag,
kCanTweakAlphaForCoverage_OptFlag = GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag
};
class GrPorterDuffTest {
public:
struct XPInfo {
XPInfo(skiatest::Reporter* reporter, SkBlendMode xfermode, const GrCaps& caps,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
GrPipelineAnalysisColor inputColor, GrPipelineAnalysisCoverage inputCoverage) {
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
// The GrXPFactory query assumes no coverage.
fCanCombineOverlappedStencilAndCover =
!analysis.hasCoverage() && GrXPFactory::CanCombineOverlappedStencilAndCover(
xpf, analysis.isOutputColorOpaque());
GrProcessorSet::FragmentProcessorAnalysis analysis(inputColor, inputCoverage, xpf,
caps);
fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
fCanCombineOverlappedStencilAndCover = analysis.canCombineOverlappedStencilAndCover();
fIgnoresInputColor = analysis.isInputColorIgnored();
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis));
fOptFlags = xp->getOptimizations(analysis);
TEST_ASSERT(!analysis.requiresDstTexture());
GetXPOutputTypes(xp.get(), &fPrimaryOutputType, &fSecondaryOutputType);
xp->getBlendInfo(&fBlendInfo);
TEST_ASSERT(!xp->willReadDstColor());
@ -81,7 +75,8 @@ public:
}
bool fCanCombineOverlappedStencilAndCover;
int fOptFlags;
bool fCompatibleWithCoverageAsAlpha;
bool fIgnoresInputColor;
int fPrimaryOutputType;
int fSecondaryOutputType;
GrXferProcessor::BlendInfo fBlendInfo;
@ -93,19 +88,17 @@ public:
};
static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineAnalysisColor(),
GrPipelineAnalysisCoverage::kLCD, caps);
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD);
GrPipelineAnalysisColor inputColor = GrPipelineAnalysisColor::Opaque::kNo;
GrPipelineAnalysisCoverage inputCoverage = GrPipelineAnalysisCoverage::kLCD;
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
switch (xfermode) {
case SkBlendMode::kClear:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -115,7 +108,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kSrc:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -125,8 +119,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kDst:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -136,7 +130,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kSrcOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -146,7 +141,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kDstOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -156,7 +152,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kSrcIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -166,7 +163,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kDstIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -176,7 +174,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kSrcOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -186,7 +185,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kDstOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kSAModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -196,7 +196,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kSrcATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -206,7 +207,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kDstATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -216,7 +218,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kXor:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kSAModulate_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -226,7 +229,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kPlus:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -236,7 +240,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kModulate:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -246,7 +251,8 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
break;
case SkBlendMode::kScreen:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -261,20 +267,17 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
}
}
static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrProcessorSet::FragmentProcessorAnalysis analysis(
GrPipelineAnalysisColor(), GrPipelineAnalysisCoverage::kSingleChannel, caps);
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kSingleChannel);
GrPipelineAnalysisColor inputColor = GrPipelineAnalysisColor::Opaque::kNo;
GrPipelineAnalysisCoverage inputCoverage = GrPipelineAnalysisCoverage::kSingleChannel;
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
switch (xfermode) {
case SkBlendMode::kClear:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -284,7 +287,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrc:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -294,8 +298,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDst:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -305,7 +309,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -315,7 +320,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -325,7 +331,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -335,7 +342,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kISAModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -345,7 +353,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kCoverage_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -355,7 +364,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -365,7 +375,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -375,7 +386,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kISAModulate_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -385,7 +397,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kXor:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -395,7 +408,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kPlus:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -405,7 +419,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kModulate:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -415,7 +430,8 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kScreen:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -430,21 +446,18 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
}
}
static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrProcessorSet::FragmentProcessorAnalysis analysis(GrColorPackRGBA(229, 0, 154, 240),
GrPipelineAnalysisCoverage::kNone, caps);
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(analysis.hasKnownOutputColor());
SkASSERT(!analysis.hasCoverage());
static void test_color_not_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysisColor inputColor(GrColorPackRGBA(229, 0, 154, 240));
GrPipelineAnalysisCoverage inputCoverage = GrPipelineAnalysisCoverage::kNone;
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
switch (xfermode) {
case SkBlendMode::kClear:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -454,7 +467,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kSrc:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -464,8 +478,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kDst:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -475,7 +489,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kSrcOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -485,7 +500,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kDstOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -495,7 +511,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kSrcIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -505,7 +522,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kDstIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -515,7 +533,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kSrcOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -525,7 +544,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kDstOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -535,7 +555,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kSrcATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -545,7 +566,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kDstATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -555,7 +577,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kXor:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -565,7 +588,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kPlus:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -575,7 +599,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kModulate:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -585,7 +610,8 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
break;
case SkBlendMode::kScreen:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -601,21 +627,17 @@ 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) {
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineAnalysisColor::Opaque::kYes,
GrPipelineAnalysisCoverage::kSingleChannel,
caps);
SkASSERT(analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kSingleChannel);
GrPipelineAnalysisColor inputColor = GrPipelineAnalysisColor::Opaque::kYes;
GrPipelineAnalysisCoverage inputCoverage = GrPipelineAnalysisCoverage::kSingleChannel;
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
switch (xfermode) {
case SkBlendMode::kClear:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -625,7 +647,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrc:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -635,8 +658,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDst:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -646,7 +669,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -656,7 +680,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -666,7 +691,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -676,8 +702,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -687,7 +713,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -697,7 +724,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kCoverage_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -707,7 +735,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kSrcATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -717,7 +746,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kDstATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -727,7 +757,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kXor:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -737,7 +768,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kPlus:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -747,7 +779,7 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kModulate:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kNone_OptFlags) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(kISCModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kReverseSubtract_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -757,7 +789,8 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
break;
case SkBlendMode::kScreen:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -773,21 +806,18 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
}
static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineAnalysisColor::Opaque::kYes,
GrPipelineAnalysisCoverage::kNone, caps);
SkASSERT(analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(!analysis.hasCoverage());
GrPipelineAnalysisColor inputColor = GrPipelineAnalysisColor::Opaque::kYes;
GrPipelineAnalysisCoverage inputCoverage = GrPipelineAnalysisCoverage::kNone;
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, analysis);
const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
switch (xfermode) {
case SkBlendMode::kClear:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -797,7 +827,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kSrc:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -807,8 +838,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kDst:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -818,7 +849,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kSrcOver:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -828,7 +860,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kDstOver:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -838,7 +871,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kSrcIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -848,8 +882,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kDstIn:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT((kIgnoreColor_OptFlag |
kCanTweakAlphaForCoverage_OptFlag) == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -859,7 +893,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kSrcOut:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -869,7 +904,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kDstOut:
TEST_ASSERT(xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kIgnoreColor_OptFlag == xpi.fOptFlags);
TEST_ASSERT(xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kNone_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -879,7 +915,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kSrcATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -889,7 +926,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kDstATop:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -899,7 +937,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kXor:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -909,7 +948,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kPlus:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -919,7 +959,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kModulate:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kNone_OptFlags == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(!xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -929,7 +970,8 @@ static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const Gr
break;
case SkBlendMode::kScreen:
TEST_ASSERT(!xpi.fCanCombineOverlappedStencilAndCover);
TEST_ASSERT(kCanTweakAlphaForCoverage_OptFlag == xpi.fOptFlags);
TEST_ASSERT(!xpi.fIgnoresInputColor);
TEST_ASSERT(xpi.fCompatibleWithCoverageAsAlpha);
TEST_ASSERT(kModulate_OutputType == xpi.fPrimaryOutputType);
TEST_ASSERT(kNone_OutputType == xpi.fSecondaryOutputType);
TEST_ASSERT(kAdd_GrBlendEquation == xpi.fBlendInfo.fEquation);
@ -974,17 +1016,15 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
SkASSERT(analysis.hasKnownOutputColor());
SkASSERT(analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD);
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver);
TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis));
TEST_ASSERT(!analysis.requiresDstTexture());
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver);
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
if (!xp) {
ERRORF(reporter, "Failed to create an XP with LCD coverage.");
return;
}
xp->getOptimizations(analysis);
GrXferProcessor::BlendInfo blendInfo;
xp->getBlendInfo(&blendInfo);
TEST_ASSERT(blendInfo.fWriteColor);
@ -1022,15 +1062,16 @@ DEF_GPUTEST(PorterDuffNoDualSourceBlending, reporter, /*factory*/) {
GrPipelineAnalysisColor(GrColorPackRGBA(0, 82, 17, 255))};
for (const auto& colorInput : colorInputs) {
GrProcessorSet::FragmentProcessorAnalysis analysis;
for (GrPipelineAnalysisCoverage coverageType :
{GrPipelineAnalysisCoverage::kSingleChannel, GrPipelineAnalysisCoverage::kNone}) {
analysis = GrProcessorSet::FragmentProcessorAnalysis(colorInput, coverageType, caps);
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
GrProcessorSet::FragmentProcessorAnalysis analysis;
analysis = GrProcessorSet::FragmentProcessorAnalysis(colorInput, coverageType, xpf,
caps);
GrXferProcessor::DstTexture* dstTexture =
GrXPFactory::WillNeedDstTexture(xpf, caps, analysis) ? &fakeDstTexture : 0;
analysis.requiresDstTexture() ? &fakeDstTexture : nullptr;
sk_sp<GrXferProcessor> xp(
xpf->createXferProcessor(analysis, false, dstTexture, caps));
if (!xp) {
@ -1038,8 +1079,6 @@ DEF_GPUTEST(PorterDuffNoDualSourceBlending, reporter, /*factory*/) {
return;
}
TEST_ASSERT(!xp->hasSecondaryOutput());
xp->getOptimizations(analysis);
TEST_ASSERT(!xp->hasSecondaryOutput());
}
}
}