Create GrXferProcessor while doing GrProcessorSet analysis.
Bug: skia: Change-Id: I62a628f9c0536ffb05c8f9d0c9ded5657f93b48e Reviewed-on: https://skia-review.googlesource.com/11482 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
44320dda94
commit
0ae0e23696
@ -20,6 +20,8 @@
|
||||
|
||||
void GrPipeline::init(const InitArgs& args) {
|
||||
SkASSERT(args.fRenderTarget);
|
||||
SkASSERT(args.fProcessors);
|
||||
SkASSERT(args.fProcessors->isFinalized());
|
||||
|
||||
fRenderTarget.reset(args.fRenderTarget);
|
||||
|
||||
@ -48,17 +50,8 @@ void GrPipeline::init(const InitArgs& args) {
|
||||
|
||||
fDrawFace = static_cast<int16_t>(args.fDrawFace);
|
||||
|
||||
bool isHWAA = kHWAntialias_Flag & args.fFlags;
|
||||
fXferProcessor.reset(args.fProcessors->xferProcessor());
|
||||
|
||||
// Create XferProcessor from DS's XPFactory
|
||||
{
|
||||
bool hasMixedSamples =
|
||||
args.fRenderTarget->isMixedSampled() && (isHWAA || this->isStencilEnabled());
|
||||
sk_sp<GrXferProcessor> xferProcessor =
|
||||
GrXPFactory::MakeXferProcessor(args.fProcessors->xpFactory(), args.fXPInputColor,
|
||||
args.fXPInputCoverage, hasMixedSamples, *args.fCaps);
|
||||
fXferProcessor.reset(xferProcessor.get());
|
||||
}
|
||||
if (args.fDstTexture.texture()) {
|
||||
fDstTexture.reset(args.fDstTexture.texture());
|
||||
fDstTextureOffset = args.fDstTexture.offset();
|
||||
|
@ -56,9 +56,7 @@ public:
|
||||
struct InitArgs {
|
||||
uint32_t fFlags = 0;
|
||||
GrDrawFace fDrawFace = GrDrawFace::kBoth;
|
||||
const GrProcessorSet* fProcessors = nullptr;
|
||||
GrProcessorAnalysisColor fXPInputColor;
|
||||
GrProcessorAnalysisCoverage fXPInputCoverage = GrProcessorAnalysisCoverage::kNone;
|
||||
const GrProcessorSet* fProcessors = nullptr; // Must be finalized
|
||||
const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
|
||||
const GrAppliedClip* fAppliedClip = nullptr;
|
||||
GrRenderTarget* fRenderTarget = nullptr;
|
||||
|
@ -63,12 +63,12 @@ public:
|
||||
|
||||
const GrProcessorSet& processors() const { return fProcessors; }
|
||||
|
||||
void analyzeAndEliminateFragmentProcessors(GrProcessorSet::Analysis* analysis,
|
||||
const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrAppliedClip* clip, const GrCaps& caps) {
|
||||
fProcessors.analyzeAndEliminateFragmentProcessors(analysis, colorInput, coverageInput, clip,
|
||||
caps);
|
||||
GrProcessorSet::Analysis finalizeProcessors(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrAppliedClip* clip, bool isMixedSamples,
|
||||
const GrCaps& caps, GrColor* overrideColor) {
|
||||
return fProcessors.finalize(colorInput, coverageInput, clip, isMixedSamples, caps,
|
||||
overrideColor);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include "GrAppliedClip.h"
|
||||
#include "GrCaps.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "effects/GrPorterDuffXferProcessor.h"
|
||||
|
||||
GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
|
||||
fXPFactory = paint.fXPFactory;
|
||||
GrProcessorSet::GrProcessorSet(GrPaint&& paint) : fXP(paint.getXPFactory()) {
|
||||
fFlags = 0;
|
||||
if (paint.numColorFragmentProcessors() <= kMaxColorProcessors) {
|
||||
fColorFragmentProcessorCnt = paint.numColorFragmentProcessors();
|
||||
@ -40,27 +40,22 @@ GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
|
||||
|
||||
GrProcessorSet::~GrProcessorSet() {
|
||||
for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
|
||||
if (this->isPendingExecution()) {
|
||||
if (this->isFinalized()) {
|
||||
fFragmentProcessors[i]->completedExecution();
|
||||
} else {
|
||||
fFragmentProcessors[i]->unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrProcessorSet::makePendingExecution() {
|
||||
SkASSERT(!(kPendingExecution_Flag & fFlags));
|
||||
fFlags |= kPendingExecution_Flag;
|
||||
for (int i = fFragmentProcessorOffset; i < fFragmentProcessors.count(); ++i) {
|
||||
fFragmentProcessors[i]->addPendingExecution();
|
||||
fFragmentProcessors[i]->unref();
|
||||
if (this->isFinalized() && this->xferProcessor()) {
|
||||
this->xferProcessor()->completedExecution();
|
||||
}
|
||||
}
|
||||
|
||||
bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
|
||||
SkASSERT(this->isFinalized());
|
||||
SkASSERT(that.isFinalized());
|
||||
int fpCount = this->numFragmentProcessors();
|
||||
if (((fFlags ^ that.fFlags) & ~kPendingExecution_Flag) ||
|
||||
fpCount != that.numFragmentProcessors() ||
|
||||
if (((fFlags ^ that.fFlags) & ~kFinalized_Flag) || fpCount != that.numFragmentProcessors() ||
|
||||
fColorFragmentProcessorCnt != that.fColorFragmentProcessorCnt) {
|
||||
return false;
|
||||
}
|
||||
@ -72,34 +67,43 @@ bool GrProcessorSet::operator==(const GrProcessorSet& that) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (fXPFactory != that.fXPFactory) {
|
||||
return false;
|
||||
// Most of the time both of these are null
|
||||
if (!this->xferProcessor() && !that.xferProcessor()) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
const GrXferProcessor& thisXP = this->xferProcessor()
|
||||
? *this->xferProcessor()
|
||||
: GrPorterDuffXPFactory::SimpleSrcOverXP();
|
||||
const GrXferProcessor& thatXP = that.xferProcessor()
|
||||
? *that.xferProcessor()
|
||||
: GrPorterDuffXPFactory::SimpleSrcOverXP();
|
||||
return thisXP.isEqual(thatXP);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
GrProcessorSet::Analysis GrProcessorSet::finalize(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrAppliedClip* clip, bool isMixedSamples,
|
||||
const GrCaps& caps, GrColor* overrideInputColor) {
|
||||
SkASSERT(!this->isFinalized());
|
||||
SkASSERT(!fFragmentProcessorOffset);
|
||||
|
||||
void GrProcessorSet::Analysis::internalInit(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrProcessorSet& processors,
|
||||
const GrFragmentProcessor* clipFP,
|
||||
const GrCaps& caps) {
|
||||
GrColorFragmentProcessorAnalysis colorInfo(colorInput);
|
||||
fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
|
||||
fValidInputColor = colorInput.isConstant(&fInputColor);
|
||||
GrProcessorSet::Analysis analysis;
|
||||
|
||||
const GrFragmentProcessor* const* fps =
|
||||
processors.fFragmentProcessors.get() + processors.fFragmentProcessorOffset;
|
||||
colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt);
|
||||
fCompatibleWithCoverageAsAlpha &= colorInfo.allProcessorsCompatibleWithCoverageAsAlpha();
|
||||
fps += processors.fColorFragmentProcessorCnt;
|
||||
int n = processors.numCoverageFragmentProcessors();
|
||||
const GrFragmentProcessor* clipFP = clip ? clip->clipCoverageFragmentProcessor() : nullptr;
|
||||
GrColorFragmentProcessorAnalysis colorAnalysis(colorInput);
|
||||
analysis.fCompatibleWithCoverageAsAlpha = GrProcessorAnalysisCoverage::kLCD != coverageInput;
|
||||
|
||||
const GrFragmentProcessor* const* fps = fFragmentProcessors.get() + fFragmentProcessorOffset;
|
||||
colorAnalysis.analyzeProcessors(fps, fColorFragmentProcessorCnt);
|
||||
analysis.fCompatibleWithCoverageAsAlpha &=
|
||||
colorAnalysis.allProcessorsCompatibleWithCoverageAsAlpha();
|
||||
fps += fColorFragmentProcessorCnt;
|
||||
int n = this->numCoverageFragmentProcessors();
|
||||
bool hasCoverageFP = n > 0;
|
||||
bool coverageUsesLocalCoords = false;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (!fps[i]->compatibleWithCoverageAsAlpha()) {
|
||||
fCompatibleWithCoverageAsAlpha = false;
|
||||
analysis.fCompatibleWithCoverageAsAlpha = false;
|
||||
// Other than tests that exercise atypical behavior we expect all coverage FPs to be
|
||||
// compatible with the coverage-as-alpha optimization.
|
||||
GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
|
||||
@ -108,21 +112,14 @@ void GrProcessorSet::Analysis::internalInit(const GrProcessorAnalysisColor& colo
|
||||
}
|
||||
|
||||
if (clipFP) {
|
||||
fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
|
||||
analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
|
||||
coverageUsesLocalCoords |= clipFP->usesLocalCoords();
|
||||
hasCoverageFP = true;
|
||||
}
|
||||
fInitialColorProcessorsToEliminate = colorInfo.initialProcessorsToEliminate(&fInputColor);
|
||||
fValidInputColor |= SkToBool(fInitialColorProcessorsToEliminate);
|
||||
|
||||
GrProcessorAnalysisColor outputColor = colorInfo.outputColor();
|
||||
if (outputColor.isConstant(&fKnownOutputColor)) {
|
||||
fOutputColorType = static_cast<unsigned>(ColorType::kConstant);
|
||||
} else if (outputColor.isOpaque()) {
|
||||
fOutputColorType = static_cast<unsigned>(ColorType::kOpaque);
|
||||
} else {
|
||||
fOutputColorType = static_cast<unsigned>(ColorType::kUnknown);
|
||||
}
|
||||
int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
|
||||
analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(
|
||||
colorFPsToEliminate ? Analysis::kOverridden_InputColorType
|
||||
: Analysis::kOriginal_InputColorType);
|
||||
|
||||
GrProcessorAnalysisCoverage outputCoverage;
|
||||
if (GrProcessorAnalysisCoverage::kLCD == coverageInput) {
|
||||
@ -132,82 +129,51 @@ void GrProcessorSet::Analysis::internalInit(const GrProcessorAnalysisColor& colo
|
||||
} else {
|
||||
outputCoverage = GrProcessorAnalysisCoverage::kNone;
|
||||
}
|
||||
fOutputCoverageType = static_cast<unsigned>(outputCoverage);
|
||||
|
||||
GrXPFactory::AnalysisProperties props = GrXPFactory::GetAnalysisProperties(
|
||||
processors.fXPFactory, colorInfo.outputColor(), outputCoverage, caps);
|
||||
if (!processors.numCoverageFragmentProcessors() &&
|
||||
this->xpFactory(), colorAnalysis.outputColor(), outputCoverage, caps);
|
||||
if (!this->numCoverageFragmentProcessors() &&
|
||||
GrProcessorAnalysisCoverage::kNone == coverageInput) {
|
||||
fCanCombineOverlappedStencilAndCover = SkToBool(
|
||||
analysis.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;
|
||||
analysis.fCanCombineOverlappedStencilAndCover = false;
|
||||
}
|
||||
fRequiresDstTexture = SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
|
||||
fIgnoresInputColor = SkToBool(props & GrXPFactory::AnalysisProperties::kIgnoresInputColor);
|
||||
fCompatibleWithCoverageAsAlpha &=
|
||||
analysis.fRequiresDstTexture =
|
||||
SkToBool(props & GrXPFactory::AnalysisProperties::kRequiresDstTexture);
|
||||
analysis.fCompatibleWithCoverageAsAlpha &=
|
||||
SkToBool(props & GrXPFactory::AnalysisProperties::kCompatibleWithAlphaAsCoverage);
|
||||
fRequiresBarrierBetweenOverlappingDraws = SkToBool(
|
||||
analysis.fRequiresBarrierBetweenOverlappingDraws = SkToBool(
|
||||
props & GrXPFactory::AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws);
|
||||
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;
|
||||
colorFPsToEliminate = this->numColorFragmentProcessors();
|
||||
analysis.fInputColorType =
|
||||
static_cast<Analysis::PackedInputColorType>(Analysis::kIgnored_InputColorType);
|
||||
analysis.fUsesLocalCoords = coverageUsesLocalCoords;
|
||||
} else {
|
||||
fUsesLocalCoords = coverageUsesLocalCoords | colorInfo.usesLocalCoords();
|
||||
analysis.fUsesLocalCoords = coverageUsesLocalCoords | colorAnalysis.usesLocalCoords();
|
||||
}
|
||||
}
|
||||
|
||||
void GrProcessorSet::Analysis::init(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrProcessorSet& processors,
|
||||
const GrAppliedClip* appliedClip,
|
||||
const GrCaps& caps) {
|
||||
const GrFragmentProcessor* clipFP =
|
||||
appliedClip ? appliedClip->clipCoverageFragmentProcessor() : nullptr;
|
||||
this->internalInit(colorInput, coverageInput, processors, clipFP, caps);
|
||||
fIsInitializedWithProcessorSet = true;
|
||||
}
|
||||
|
||||
GrProcessorSet::Analysis::Analysis(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrXPFactory* factory,
|
||||
const GrCaps& caps)
|
||||
: Analysis() {
|
||||
GrPaint paint;
|
||||
paint.setXPFactory(factory);
|
||||
this->internalInit(colorInput, coverageInput, GrProcessorSet(std::move(paint)), nullptr, caps);
|
||||
}
|
||||
|
||||
void GrProcessorSet::analyzeAndEliminateFragmentProcessors(
|
||||
Analysis* analysis,
|
||||
const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrAppliedClip* clip,
|
||||
const GrCaps& caps) {
|
||||
analysis->init(colorInput, coverageInput, *this, clip, caps);
|
||||
if (analysis->fInitialColorProcessorsToEliminate > 0) {
|
||||
for (unsigned i = 0; i < analysis->fInitialColorProcessorsToEliminate; ++i) {
|
||||
if (this->isPendingExecution()) {
|
||||
fFragmentProcessors[i + fFragmentProcessorOffset]->completedExecution();
|
||||
} else {
|
||||
fFragmentProcessors[i + fFragmentProcessorOffset]->unref();
|
||||
}
|
||||
fFragmentProcessors[i + fFragmentProcessorOffset] = nullptr;
|
||||
}
|
||||
fFragmentProcessorOffset += analysis->fInitialColorProcessorsToEliminate;
|
||||
fColorFragmentProcessorCnt -= analysis->fInitialColorProcessorsToEliminate;
|
||||
SkASSERT(fFragmentProcessorOffset + fColorFragmentProcessorCnt <=
|
||||
fFragmentProcessors.count());
|
||||
analysis->fInitialColorProcessorsToEliminate = 0;
|
||||
for (int i = 0; i < colorFPsToEliminate; ++i) {
|
||||
fFragmentProcessors[i]->unref();
|
||||
fFragmentProcessors[i] = nullptr;
|
||||
}
|
||||
for (int i = colorFPsToEliminate; i < fFragmentProcessors.count(); ++i) {
|
||||
fFragmentProcessors[i]->addPendingExecution();
|
||||
fFragmentProcessors[i]->unref();
|
||||
}
|
||||
fFragmentProcessorOffset = colorFPsToEliminate;
|
||||
fColorFragmentProcessorCnt -= colorFPsToEliminate;
|
||||
|
||||
auto xp = GrXPFactory::MakeXferProcessor(this->xpFactory(), colorAnalysis.outputColor(),
|
||||
outputCoverage, isMixedSamples, caps);
|
||||
fXP.fProcessor = xp.get();
|
||||
if (fXP.fProcessor) {
|
||||
fXP.fProcessor->addPendingExecution();
|
||||
}
|
||||
fFlags |= kFinalized_Flag;
|
||||
|
||||
analysis.fIsInitialized = true;
|
||||
return analysis;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "SkTemplates.h"
|
||||
|
||||
class GrAppliedClip;
|
||||
class GrXferProcessor;
|
||||
class GrXPFactory;
|
||||
|
||||
class GrProcessorSet : private SkNoncopyable {
|
||||
@ -22,14 +23,6 @@ public:
|
||||
|
||||
~GrProcessorSet();
|
||||
|
||||
/**
|
||||
* If an op is recorded with this processor set then this must be called to ensure pending
|
||||
* reads and writes are propagated to resources referred to by the processors. Otherwise,
|
||||
* data hazards may occur.
|
||||
*/
|
||||
void makePendingExecution();
|
||||
bool isPendingExecution() const { return SkToBool(kPendingExecution_Flag & fFlags); }
|
||||
|
||||
int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
|
||||
int numCoverageFragmentProcessors() const {
|
||||
return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
|
||||
@ -46,7 +39,10 @@ public:
|
||||
return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset];
|
||||
}
|
||||
|
||||
const GrXPFactory* xpFactory() const { return fXPFactory; }
|
||||
const GrXferProcessor* xferProcessor() const {
|
||||
SkASSERT(this->isFinalized());
|
||||
return fXP.fProcessor;
|
||||
}
|
||||
|
||||
bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
|
||||
bool disableOutputConversionToSRGB() const {
|
||||
@ -54,74 +50,20 @@ public:
|
||||
}
|
||||
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
|
||||
|
||||
/** Comparisons are only legal on finalized processor sets. */
|
||||
bool operator==(const GrProcessorSet& that) const;
|
||||
bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
|
||||
|
||||
/**
|
||||
* This is used to track analysis of color and coverage values through the processors.
|
||||
* This is used to report results of processor analysis when a processor set is finalized (see
|
||||
* below).
|
||||
*/
|
||||
class Analysis {
|
||||
public:
|
||||
/**
|
||||
* This constructor allows an op to record its initial color in an Analysis member and then
|
||||
* then run analysis later when the analysis inputs are available. If the analysis produces
|
||||
* color fragment processor elimination then the input color is replaced by the expected
|
||||
* input to the first non-eliminated processor. Otherwise, the original input color is
|
||||
* preserved. The only reason to use this is to save space on the op by not separately
|
||||
* storing the initial color.
|
||||
*/
|
||||
explicit Analysis(GrColor initialColor) : Analysis() {
|
||||
fInputColor = initialColor;
|
||||
fValidInputColor = true;
|
||||
}
|
||||
|
||||
Analysis()
|
||||
: fIsInitializedWithProcessorSet(false)
|
||||
, fCompatibleWithCoverageAsAlpha(true)
|
||||
, fValidInputColor(false)
|
||||
, fRequiresDstTexture(false)
|
||||
, fCanCombineOverlappedStencilAndCover(true)
|
||||
, fIgnoresInputColor(false)
|
||||
, fRequiresBarrierBetweenOverlappingDraws(false)
|
||||
, fOutputCoverageType(static_cast<unsigned>(GrProcessorAnalysisCoverage::kNone))
|
||||
, fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
|
||||
, fInitialColorProcessorsToEliminate(0) {}
|
||||
|
||||
// This version is used by a unit test that assumes no clip and no fragment processors.
|
||||
Analysis(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage, const GrXPFactory*,
|
||||
const GrCaps&);
|
||||
|
||||
void init(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage,
|
||||
const GrProcessorSet&, const GrAppliedClip*, const GrCaps&);
|
||||
|
||||
bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
|
||||
|
||||
/**
|
||||
* If the return is greater than or equal to zero then 'newInputColor' should be used as the
|
||||
* input color to the GrPipeline derived from this processor set, replacing the GrDrawOp's
|
||||
* initial color. If the return is less than zero then newInputColor has not been
|
||||
* modified and no modification need be made to the pipeline's input color by the op.
|
||||
*/
|
||||
int getInputColorOverrideAndColorProcessorEliminationCount(GrColor* newInputColor) const {
|
||||
if (fValidInputColor) {
|
||||
*newInputColor = fInputColor;
|
||||
return fInitialColorProcessorsToEliminate;
|
||||
}
|
||||
SkASSERT(!fInitialColorProcessorsToEliminate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valid if initialProcessorsToEliminate returns true or this analysis was initialized with
|
||||
* a known color via constructor or init(). If color fragment processors are eliminated then
|
||||
* this returns the expected input to the first non-eliminated processors. Otherwise it is
|
||||
* the color passed to the constructor or init().
|
||||
*/
|
||||
GrColor inputColor() const {
|
||||
SkASSERT(fValidInputColor);
|
||||
return fInputColor;
|
||||
}
|
||||
Analysis(const Analysis&) = default;
|
||||
Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }
|
||||
|
||||
bool isInitialized() const { return fIsInitialized; }
|
||||
bool usesLocalCoords() const { return fUsesLocalCoords; }
|
||||
bool requiresDstTexture() const { return fRequiresDstTexture; }
|
||||
bool canCombineOverlappedStencilAndCover() const {
|
||||
@ -131,60 +73,54 @@ public:
|
||||
return fRequiresBarrierBetweenOverlappingDraws;
|
||||
}
|
||||
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
|
||||
bool isInputColorIgnored() const { return fIgnoresInputColor; }
|
||||
GrProcessorAnalysisCoverage outputCoverage() const {
|
||||
return static_cast<GrProcessorAnalysisCoverage>(fOutputCoverageType);
|
||||
}
|
||||
GrProcessorAnalysisColor outputColor() const {
|
||||
switch (this->outputColorType()) {
|
||||
case ColorType::kConstant:
|
||||
return fKnownOutputColor;
|
||||
case ColorType::kOpaque:
|
||||
return GrProcessorAnalysisColor::Opaque::kYes;
|
||||
case ColorType::kUnknown:
|
||||
return GrProcessorAnalysisColor::Opaque::kNo;
|
||||
}
|
||||
SkFAIL("Unexpected color type");
|
||||
return GrProcessorAnalysisColor::Opaque::kNo;
|
||||
|
||||
bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
|
||||
bool inputColorIsOverridden() const {
|
||||
return fInputColorType == kOverridden_InputColorType;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class ColorType : unsigned { kUnknown, kConstant, kOpaque };
|
||||
enum InputColorType : uint32_t {
|
||||
kOriginal_InputColorType,
|
||||
kOverridden_InputColorType,
|
||||
kIgnored_InputColorType
|
||||
};
|
||||
|
||||
ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
|
||||
// MSVS 2015 won't pack different underlying types
|
||||
using PackedBool = uint32_t;
|
||||
using PackedInputColorType = uint32_t;
|
||||
|
||||
void internalInit(const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage,
|
||||
const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
|
||||
|
||||
// MSVS 2015 won't pack a bool with an unsigned.
|
||||
using PackedBool = unsigned;
|
||||
|
||||
PackedBool fIsInitializedWithProcessorSet : 1;
|
||||
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;
|
||||
PackedBool fRequiresBarrierBetweenOverlappingDraws : 1;
|
||||
unsigned fOutputCoverageType : 2;
|
||||
unsigned fOutputColorType : 2;
|
||||
|
||||
unsigned fInitialColorProcessorsToEliminate : 32 - 12;
|
||||
|
||||
GrColor fInputColor;
|
||||
// This could be removed if we created the XP from the XPFactory when doing analysis.
|
||||
GrColor fKnownOutputColor;
|
||||
PackedBool fIsInitialized : 1;
|
||||
PackedInputColorType fInputColorType : 2;
|
||||
|
||||
friend class GrProcessorSet;
|
||||
};
|
||||
GR_STATIC_ASSERT(sizeof(Analysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
|
||||
GR_STATIC_ASSERT(sizeof(Analysis) == sizeof(uint32_t));
|
||||
|
||||
void analyzeAndEliminateFragmentProcessors(Analysis*,
|
||||
const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrAppliedClip*, const GrCaps&);
|
||||
/**
|
||||
* This analyzes the processors given an op's input color and coverage as well as a clip. The
|
||||
* state of the processor set may change to an equivalent but more optimal set of processors.
|
||||
* This new state requires that the caller respect the returned 'inputColorOverride'. This is
|
||||
* indicated by the returned Analysis's inputColorIsOverriden(). 'inputColorOverride' will not
|
||||
* be written if the analysis does not override the input color.
|
||||
*
|
||||
* This must be called before the processor set is used to construct a GrPipeline and may only
|
||||
* be called once.
|
||||
*
|
||||
* This also puts the processors in "pending execution" state and must be called when an op
|
||||
* that owns a processor set is recorded to ensure pending and writes are propagated to
|
||||
* resources referred to by the processors. Otherwise, data hazards may occur.
|
||||
*/
|
||||
Analysis finalize(const GrProcessorAnalysisColor& colorInput,
|
||||
const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*,
|
||||
bool isMixedSamples, const GrCaps&, GrColor* inputColorOverride);
|
||||
|
||||
bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
|
||||
|
||||
private:
|
||||
// This absurdly large limit allows Analysis and this to pack fields together.
|
||||
@ -194,11 +130,22 @@ private:
|
||||
kUseDistanceVectorField_Flag = 0x1,
|
||||
kDisableOutputConversionToSRGB_Flag = 0x2,
|
||||
kAllowSRGBInputs_Flag = 0x4,
|
||||
kPendingExecution_Flag = 0x8
|
||||
kFinalized_Flag = 0x8
|
||||
};
|
||||
|
||||
const GrXPFactory* fXPFactory = nullptr;
|
||||
union XP {
|
||||
XP(const GrXPFactory* factory) : fFactory(factory) {}
|
||||
const GrXPFactory* fFactory;
|
||||
const GrXferProcessor* fProcessor;
|
||||
};
|
||||
|
||||
const GrXPFactory* xpFactory() const {
|
||||
SkASSERT(!this->isFinalized());
|
||||
return fXP.fFactory;
|
||||
}
|
||||
|
||||
SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
|
||||
XP fXP;
|
||||
uint8_t fColorFragmentProcessorCnt;
|
||||
uint8_t fFragmentProcessorOffset = 0;
|
||||
uint8_t fFlags;
|
||||
|
@ -1688,30 +1688,33 @@ uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipeline
|
||||
}
|
||||
|
||||
GrResourceProvider* resourceProvider = fContext->resourceProvider();
|
||||
if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
|
||||
bool usesStencil = pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip();
|
||||
if (usesStencil) {
|
||||
if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
|
||||
SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
|
||||
return SK_InvalidUniqueID;
|
||||
}
|
||||
}
|
||||
|
||||
GrProcessorSet::Analysis analysis;
|
||||
op->analyzeProcessors(&analysis, &pipelineBuilder, &appliedClip, *this->caps());
|
||||
bool isMixedSamples = fRenderTargetProxy->isMixedSampled() &&
|
||||
(pipelineBuilder.isHWAntialias() || usesStencil);
|
||||
|
||||
GrColor overrideColor;
|
||||
GrProcessorSet::Analysis analysis = op->analyzeUpdateAndRecordProcessors(
|
||||
&pipelineBuilder, &appliedClip, isMixedSamples, *this->caps(), &overrideColor);
|
||||
|
||||
GrPipeline::InitArgs args;
|
||||
pipelineBuilder.getPipelineInitArgs(&args);
|
||||
args.fAppliedClip = &appliedClip;
|
||||
args.fRenderTarget = rt;
|
||||
args.fCaps = this->caps();
|
||||
args.fXPInputColor = analysis.outputColor();
|
||||
args.fXPInputCoverage = analysis.outputCoverage();
|
||||
|
||||
if (analysis.requiresDstTexture()) {
|
||||
if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
|
||||
return SK_InvalidUniqueID;
|
||||
}
|
||||
}
|
||||
op->initPipeline(args, analysis);
|
||||
op->initPipeline(args, analysis, overrideColor);
|
||||
// TODO: We need to add pipeline dependencies on textures, etc before recording this op.
|
||||
op->setClippedBounds(bounds);
|
||||
return this->getOpList()->addOp(std::move(op), this);
|
||||
|
@ -332,17 +332,19 @@ void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar
|
||||
}
|
||||
|
||||
bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) {
|
||||
GrProcessorSet::Analysis analysis;
|
||||
SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
|
||||
GrProcessorAnalysisCoverage coverageInput;
|
||||
bool isMixedSamples = false;
|
||||
if (GrAAType::kCoverage == fInfo.aaType() ||
|
||||
(GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
|
||||
coverageInput = GrProcessorAnalysisCoverage::kSingleChannel;
|
||||
} else {
|
||||
coverageInput = GrProcessorAnalysisCoverage::kNone;
|
||||
isMixedSamples = GrAAType::kMixedSamples == fInfo.aaType();
|
||||
}
|
||||
fProcessors.analyzeAndEliminateFragmentProcessors(&analysis, this->getSingleInstance().fColor,
|
||||
coverageInput, clip, caps);
|
||||
fAnalysisColor = analysis.outputColor();
|
||||
GrProcessorSet::Analysis analysis =
|
||||
fProcessors.finalize(this->getSingleInstance().fColor, coverageInput, clip,
|
||||
isMixedSamples, caps, &this->getSingleDraw().fInstance.fColor);
|
||||
|
||||
Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command.
|
||||
SkASSERT(draw.fGeometry.isEmpty());
|
||||
@ -363,11 +365,6 @@ bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAp
|
||||
fInstancedRendering->fParams.push_back_n(fParams.count(), fParams.begin());
|
||||
}
|
||||
|
||||
GrColor overrideColor;
|
||||
if (analysis.getInputColorOverrideAndColorProcessorEliminationCount(&overrideColor) >= 0) {
|
||||
SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
|
||||
this->getSingleDraw().fInstance.fColor = overrideColor;
|
||||
}
|
||||
fInfo.fCannotTweakAlphaForCoverage = !analysis.isCompatibleWithCoverageAsAlpha();
|
||||
|
||||
fInfo.fUsesLocalCoords = analysis.usesLocalCoords();
|
||||
@ -378,7 +375,6 @@ bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAp
|
||||
void InstancedRendering::Op::wasRecorded() {
|
||||
SkASSERT(!fIsTracked);
|
||||
fInstancedRendering->fTrackedOps.addToTail(this);
|
||||
fProcessors.makePendingExecution();
|
||||
fIsTracked = true;
|
||||
}
|
||||
|
||||
@ -413,7 +409,6 @@ bool InstancedRendering::Op::onCombineIfPossible(GrOp* other, const GrCaps& caps
|
||||
this->joinBounds(*that);
|
||||
fInfo = combinedInfo;
|
||||
fPixelLoad += that->fPixelLoad;
|
||||
fAnalysisColor = GrProcessorAnalysisColor::Combine(fAnalysisColor, that->fAnalysisColor);
|
||||
// Adopt the other op's draws.
|
||||
fNumDraws += that->fNumDraws;
|
||||
fNumChangesInGeometry += that->fNumChangesInGeometry;
|
||||
@ -470,21 +465,9 @@ void InstancedRendering::Op::onExecute(GrOpFlushState* state) {
|
||||
|
||||
state->gpu()->handleDirtyContext();
|
||||
|
||||
const GrAppliedClip* clip = state->drawOpArgs().fAppliedClip;
|
||||
GrProcessorAnalysisCoverage coverage;
|
||||
if (GrAAType::kCoverage == fInfo.aaType() ||
|
||||
(clip && clip->clipCoverageFragmentProcessor()) ||
|
||||
(GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
|
||||
coverage = GrProcessorAnalysisCoverage::kSingleChannel;
|
||||
} else {
|
||||
coverage = GrProcessorAnalysisCoverage::kNone;
|
||||
}
|
||||
|
||||
GrPipeline pipeline;
|
||||
GrPipeline::InitArgs args;
|
||||
args.fXPInputColor = fAnalysisColor;
|
||||
args.fXPInputCoverage = coverage;
|
||||
args.fAppliedClip = clip;
|
||||
args.fAppliedClip = state->drawOpArgs().fAppliedClip;
|
||||
args.fCaps = &state->caps();
|
||||
args.fProcessors = &fProcessors;
|
||||
args.fFlags = GrAATypeIsHW(fInfo.aaType()) ? GrPipeline::kHWAntialias_Flag : 0;
|
||||
|
@ -151,7 +151,6 @@ protected:
|
||||
OpInfo fInfo;
|
||||
SkScalar fPixelLoad;
|
||||
GrProcessorSet fProcessors;
|
||||
GrProcessorAnalysisColor fAnalysisColor;
|
||||
SkSTArray<5, ParamsTexel, true> fParams;
|
||||
bool fIsTracked : 1;
|
||||
bool fRequiresBarrierOnOverlap : 1;
|
||||
|
@ -76,7 +76,8 @@ public:
|
||||
* This is called after the GrAppliedClip has been computed and just prior to recording the op
|
||||
* or combining it with a previously recorded op. It is used to determine whether a copy of the
|
||||
* destination (or destination texture itself) needs to be provided to the xp when this op
|
||||
* executes.
|
||||
* executes. This is guaranteed to be called before an op is recorded. However, this is also
|
||||
* called on ops that are not recorded because they combine with a previously recorded op.
|
||||
*/
|
||||
virtual bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) = 0;
|
||||
|
||||
|
@ -12,13 +12,15 @@
|
||||
#include "SkTemplates.h"
|
||||
|
||||
GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
|
||||
GrPathRendering::FillType fill, GrAA aa)
|
||||
GrPathRendering::FillType fill, GrAAType aaType)
|
||||
: INHERITED(classID)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fInputColor(paint.getColor())
|
||||
, fProcessorSet(std::move(paint))
|
||||
, fAnalysis(paint.getColor())
|
||||
, fFillType(fill)
|
||||
, fAA(aa) {}
|
||||
, fAAType(aaType) {
|
||||
SkASSERT(fAAType != GrAAType::kCoverage);
|
||||
}
|
||||
|
||||
SkString GrDrawPathOp::dumpInfo() const {
|
||||
SkString string;
|
||||
@ -38,16 +40,13 @@ void GrDrawPathOpBase::initPipeline(const GrOpFlushState& state, GrPipeline* pip
|
||||
0xffff>()
|
||||
};
|
||||
GrPipeline::InitArgs args;
|
||||
auto analysis = this->processorAnalysis();
|
||||
args.fProcessors = &this->processors();
|
||||
args.fFlags = GrAA::kYes == fAA ? GrPipeline::kHWAntialias_Flag : 0;
|
||||
args.fFlags = GrAATypeIsHW(fAAType) ? GrPipeline::kHWAntialias_Flag : 0;
|
||||
args.fUserStencil = &kCoverPass;
|
||||
args.fAppliedClip = state.drawOpArgs().fAppliedClip;
|
||||
args.fRenderTarget = state.drawOpArgs().fRenderTarget;
|
||||
args.fCaps = &state.caps();
|
||||
args.fDstTexture = state.drawOpArgs().fDstTexture;
|
||||
args.fXPInputColor = analysis.outputColor();
|
||||
args.fXPInputCoverage = analysis.outputCoverage();
|
||||
|
||||
return pipeline->init(args);
|
||||
}
|
||||
@ -90,9 +89,9 @@ SkString GrDrawPathRangeOp::dumpInfo() const {
|
||||
|
||||
GrDrawPathRangeOp::GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
|
||||
SkScalar y, GrPaint&& paint, GrPathRendering::FillType fill,
|
||||
GrAA aa, GrPathRange* range, const InstanceData* instanceData,
|
||||
const SkRect& bounds)
|
||||
: INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aa)
|
||||
GrAAType aaType, GrPathRange* range,
|
||||
const InstanceData* instanceData, const SkRect& bounds)
|
||||
: INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aaType)
|
||||
, fPathRange(range)
|
||||
, fTotalPathCount(instanceData->count())
|
||||
, fScale(scale) {
|
||||
|
@ -23,31 +23,33 @@ class GrPaint;
|
||||
|
||||
class GrDrawPathOpBase : public GrDrawOp {
|
||||
protected:
|
||||
GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
|
||||
GrPathRendering::FillType fill, GrAA aa);
|
||||
GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&&,
|
||||
GrPathRendering::FillType, GrAAType);
|
||||
FixedFunctionFlags fixedFunctionFlags() const override {
|
||||
return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
|
||||
if (GrAATypeIsHW(fAAType)) {
|
||||
return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
|
||||
}
|
||||
return FixedFunctionFlags::kUsesStencil;
|
||||
}
|
||||
bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
|
||||
return this->doProcessorAnalysis(caps, clip).requiresDstTexture();
|
||||
}
|
||||
|
||||
void wasRecorded() override { fProcessorSet.makePendingExecution(); }
|
||||
|
||||
protected:
|
||||
const SkMatrix& viewMatrix() const { return fViewMatrix; }
|
||||
GrColor color() const { return fAnalysis.inputColor(); }
|
||||
GrColor color() const { return fInputColor; }
|
||||
GrPathRendering::FillType fillType() const { return fFillType; }
|
||||
const GrProcessorSet& processors() const { return fProcessorSet; }
|
||||
void initPipeline(const GrOpFlushState&, GrPipeline*);
|
||||
const GrProcessorSet::Analysis& doProcessorAnalysis(const GrCaps& caps,
|
||||
const GrAppliedClip* clip) {
|
||||
fProcessorSet.analyzeAndEliminateFragmentProcessors(
|
||||
&fAnalysis, fAnalysis.inputColor(), GrProcessorAnalysisCoverage::kNone, clip, caps);
|
||||
bool isMixedSamples = GrAAType::kMixedSamples == fAAType;
|
||||
fAnalysis = fProcessorSet.finalize(fInputColor, GrProcessorAnalysisCoverage::kNone, clip,
|
||||
isMixedSamples, caps, &fInputColor);
|
||||
return fAnalysis;
|
||||
}
|
||||
const GrProcessorSet::Analysis& processorAnalysis() const {
|
||||
SkASSERT(fAnalysis.isInitializedWithProcessorSet());
|
||||
SkASSERT(fAnalysis.isInitialized());
|
||||
return fAnalysis;
|
||||
}
|
||||
|
||||
@ -55,10 +57,11 @@ private:
|
||||
void onPrepare(GrOpFlushState*) final {}
|
||||
|
||||
SkMatrix fViewMatrix;
|
||||
GrColor fInputColor;
|
||||
GrProcessorSet fProcessorSet;
|
||||
GrProcessorSet::Analysis fAnalysis;
|
||||
GrPathRendering::FillType fFillType;
|
||||
GrAA fAA;
|
||||
GrAAType fAAType;
|
||||
|
||||
typedef GrDrawOp INHERITED;
|
||||
};
|
||||
@ -67,9 +70,10 @@ class GrDrawPathOp final : public GrDrawPathOpBase {
|
||||
public:
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa,
|
||||
GrPath* path) {
|
||||
return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, std::move(paint), aa, path));
|
||||
static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint,
|
||||
GrAAType aaType, GrPath* path) {
|
||||
return std::unique_ptr<GrDrawOp>(
|
||||
new GrDrawPathOp(viewMatrix, std::move(paint), aaType, path));
|
||||
}
|
||||
|
||||
const char* name() const override { return "DrawPath"; }
|
||||
@ -77,8 +81,8 @@ public:
|
||||
SkString dumpInfo() const override;
|
||||
|
||||
private:
|
||||
GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, const GrPath* path)
|
||||
: GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa)
|
||||
GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAAType aaType, const GrPath* path)
|
||||
: GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aaType)
|
||||
, fPath(path) {
|
||||
this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
|
||||
}
|
||||
@ -160,11 +164,12 @@ public:
|
||||
|
||||
static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
|
||||
SkScalar y, GrPaint&& paint,
|
||||
GrPathRendering::FillType fill, GrAA aa,
|
||||
GrPathRendering::FillType fill, GrAAType aaType,
|
||||
GrPathRange* range, const InstanceData* instanceData,
|
||||
const SkRect& bounds) {
|
||||
return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(
|
||||
viewMatrix, scale, x, y, std::move(paint), fill, aa, range, instanceData, bounds));
|
||||
return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(viewMatrix, scale, x, y,
|
||||
std::move(paint), fill, aaType,
|
||||
range, instanceData, bounds));
|
||||
}
|
||||
|
||||
const char* name() const override { return "DrawPathRange"; }
|
||||
@ -173,8 +178,8 @@ public:
|
||||
|
||||
private:
|
||||
GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y,
|
||||
GrPaint&& paint, GrPathRendering::FillType fill, GrAA aa, GrPathRange* range,
|
||||
const InstanceData* instanceData, const SkRect& bounds);
|
||||
GrPaint&& paint, GrPathRendering::FillType fill, GrAAType aaType,
|
||||
GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds);
|
||||
|
||||
TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); }
|
||||
|
||||
|
@ -101,20 +101,22 @@ public:
|
||||
* Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
|
||||
* initial color and coverage from this op's geometry processor.
|
||||
*/
|
||||
void analyzeProcessors(GrProcessorSet::Analysis* analysis,
|
||||
GrPipelineBuilder* pipelineBuilder,
|
||||
const GrAppliedClip* appliedClip,
|
||||
const GrCaps& caps) const {
|
||||
GrProcessorSet::Analysis analyzeUpdateAndRecordProcessors(GrPipelineBuilder* pipelineBuilder,
|
||||
const GrAppliedClip* appliedClip,
|
||||
bool isMixedSamples,
|
||||
const GrCaps& caps,
|
||||
GrColor* overrideColor) const {
|
||||
GrProcessorAnalysisColor inputColor;
|
||||
GrProcessorAnalysisCoverage inputCoverage;
|
||||
this->getProcessorAnalysisInputs(&inputColor, &inputCoverage);
|
||||
pipelineBuilder->analyzeAndEliminateFragmentProcessors(analysis, inputColor, inputCoverage,
|
||||
appliedClip, caps);
|
||||
return pipelineBuilder->finalizeProcessors(inputColor, inputCoverage, appliedClip,
|
||||
isMixedSamples, caps, overrideColor);
|
||||
}
|
||||
|
||||
void initPipeline(const GrPipeline::InitArgs& args, const GrProcessorSet::Analysis& analysis) {
|
||||
void initPipeline(const GrPipeline::InitArgs& args, const GrProcessorSet::Analysis& analysis,
|
||||
GrColor overrideColor) {
|
||||
fPipeline.init(args);
|
||||
this->applyPipelineOptimizations(PipelineOptimizations(analysis));
|
||||
this->applyPipelineOptimizations(PipelineOptimizations(analysis, overrideColor));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,11 +140,11 @@ protected:
|
||||
*/
|
||||
class PipelineOptimizations {
|
||||
public:
|
||||
PipelineOptimizations(const GrProcessorSet::Analysis& analysis) {
|
||||
PipelineOptimizations(const GrProcessorSet::Analysis& analysis, GrColor overrideColor) {
|
||||
fFlags = 0;
|
||||
if (analysis.getInputColorOverrideAndColorProcessorEliminationCount(&fOverrideColor) >=
|
||||
0) {
|
||||
if (analysis.inputColorIsOverridden()) {
|
||||
fFlags |= kUseOverrideColor_Flag;
|
||||
fOverrideColor = overrideColor;
|
||||
}
|
||||
if (analysis.usesLocalCoords()) {
|
||||
fFlags |= kReadsLocalCoords_Flag;
|
||||
|
@ -145,9 +145,8 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
|
||||
std::move(coverOp));
|
||||
}
|
||||
} else {
|
||||
GrAA aa = GrBoolToAA(GrAATypeIsHW(args.fAAType));
|
||||
std::unique_ptr<GrDrawOp> op =
|
||||
GrDrawPathOp::Make(viewMatrix, std::move(args.fPaint), aa, path.get());
|
||||
GrDrawPathOp::Make(viewMatrix, std::move(args.fPaint), args.fAAType, path.get());
|
||||
args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
|
||||
}
|
||||
|
||||
|
@ -570,9 +570,7 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
|
||||
SkScalar y, const SkIRect& clipBounds,
|
||||
GrAtlasTextContext* fallbackTextContext,
|
||||
const SkPaint& originalSkPaint) const {
|
||||
GrAA runAA = this->isAntiAlias();
|
||||
SkASSERT(fInstanceData);
|
||||
SkASSERT(renderTargetContext->isStencilBufferMultisampled() || GrAA::kNo == runAA);
|
||||
|
||||
if (fInstanceData->count()) {
|
||||
static constexpr GrUserStencilSettings kCoverPass(
|
||||
@ -606,9 +604,18 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
|
||||
renderTargetContext->height());
|
||||
|
||||
// The run's "font" overrides the anti-aliasing of the passed in SkPaint!
|
||||
GrAAType aaType;
|
||||
if (this->aa() == GrAA::kYes) {
|
||||
SkASSERT(renderTargetContext->isStencilBufferMultisampled());
|
||||
aaType = renderTargetContext->isUnifiedMultisampled() ? GrAAType::kMSAA
|
||||
: GrAAType::kMixedSamples;
|
||||
} else {
|
||||
aaType = GrAAType::kNone;
|
||||
}
|
||||
|
||||
std::unique_ptr<GrDrawOp> op = GrDrawPathRangeOp::Make(
|
||||
viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y,
|
||||
std::move(grPaint), GrPathRendering::kWinding_FillType, runAA, glyphs.get(),
|
||||
std::move(grPaint), GrPathRendering::kWinding_FillType, aaType, glyphs.get(),
|
||||
fInstanceData.get(), bounds);
|
||||
|
||||
renderTargetContext->addDrawOp(clip, std::move(op));
|
||||
|
@ -83,7 +83,7 @@ private:
|
||||
|
||||
size_t computeSizeInCache() const;
|
||||
|
||||
GrAA isAntiAlias() const { return fFont.isAntiAlias() ? GrAA::kYes : GrAA::kNo; }
|
||||
GrAA aa() const { return fFont.isAntiAlias() ? GrAA::kYes : GrAA::kNo; }
|
||||
|
||||
private:
|
||||
typedef GrDrawPathRangeOp::InstanceData InstanceData;
|
||||
|
@ -91,17 +91,8 @@ public:
|
||||
virtual ~TestSampleLocationsInterface() {}
|
||||
};
|
||||
|
||||
static void construct_dummy_pipeline(GrRenderTargetContext* dc, GrPipeline* pipeline) {
|
||||
GrPipelineBuilder dummyBuilder(GrPaint(), GrAAType::kNone);
|
||||
GrScissorState dummyScissor;
|
||||
GrWindowRectsState dummyWindows;
|
||||
|
||||
GrPipeline::InitArgs args;
|
||||
dummyBuilder.getPipelineInitArgs(&args);
|
||||
args.fRenderTarget = dc->accessRenderTarget();
|
||||
args.fCaps = dc->caps();
|
||||
args.fDstTexture = GrXferProcessor::DstTexture();
|
||||
pipeline->init(args);
|
||||
static sk_sp<GrPipeline> construct_dummy_pipeline(GrRenderTargetContext* dc) {
|
||||
return sk_sp<GrPipeline>(new GrPipeline(dc->accessRenderTarget(), SkBlendMode::kSrcOver));
|
||||
}
|
||||
|
||||
void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
|
||||
@ -146,11 +137,10 @@ void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInter
|
||||
for (int i = 0; i < numTestPatterns; ++i) {
|
||||
testInterface->overrideSamplePattern(kTestPatterns[i]);
|
||||
for (GrRenderTargetContext* dc : {bottomUps[i].get(), topDowns[i].get()}) {
|
||||
GrPipeline dummyPipeline;
|
||||
construct_dummy_pipeline(dc, &dummyPipeline);
|
||||
sk_sp<GrPipeline> dummyPipeline = construct_dummy_pipeline(dc);
|
||||
GrRenderTarget* rt = dc->accessRenderTarget();
|
||||
assert_equal(reporter, kTestPatterns[i],
|
||||
rt->renderTargetPriv().getMultisampleSpecs(dummyPipeline),
|
||||
rt->renderTargetPriv().getMultisampleSpecs(*dummyPipeline),
|
||||
kBottomLeft_GrSurfaceOrigin == rt->origin());
|
||||
}
|
||||
}
|
||||
|
@ -55,16 +55,30 @@ enum {
|
||||
kISCModulate_OutputType
|
||||
};
|
||||
|
||||
static GrProcessorSet::Analysis do_analysis(const GrXPFactory* xpf,
|
||||
const GrProcessorAnalysisColor& colorInput,
|
||||
GrProcessorAnalysisCoverage coverageInput,
|
||||
const GrCaps& caps) {
|
||||
GrPaint paint;
|
||||
paint.setXPFactory(xpf);
|
||||
GrProcessorSet procs(std::move(paint));
|
||||
GrColor overrideColor;
|
||||
GrProcessorSet::Analysis analysis =
|
||||
procs.finalize(colorInput, coverageInput, nullptr, false, caps, &overrideColor);
|
||||
return analysis;
|
||||
}
|
||||
|
||||
class GrPorterDuffTest {
|
||||
public:
|
||||
struct XPInfo {
|
||||
XPInfo(skiatest::Reporter* reporter, SkBlendMode xfermode, const GrCaps& caps,
|
||||
GrProcessorAnalysisColor inputColor, GrProcessorAnalysisCoverage inputCoverage) {
|
||||
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
|
||||
GrProcessorSet::Analysis analysis(inputColor, inputCoverage, xpf, caps);
|
||||
|
||||
GrProcessorSet::Analysis analysis = do_analysis(xpf, inputColor, inputCoverage, caps);
|
||||
fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha();
|
||||
fCanCombineOverlappedStencilAndCover = analysis.canCombineOverlappedStencilAndCover();
|
||||
fIgnoresInputColor = analysis.isInputColorIgnored();
|
||||
fIgnoresInputColor = analysis.inputColorIsIgnored();
|
||||
sk_sp<GrXferProcessor> xp(
|
||||
GrXPFactory::MakeXferProcessor(xpf, inputColor, inputCoverage, false, caps));
|
||||
TEST_ASSERT(!analysis.requiresDstTexture());
|
||||
@ -1040,8 +1054,6 @@ DEF_GPUTEST(PorterDuffNoDualSourceBlending, reporter, /*factory*/) {
|
||||
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
|
||||
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
|
||||
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
|
||||
GrProcessorSet::Analysis analysis;
|
||||
analysis = GrProcessorSet::Analysis(colorInput, coverageType, xpf, caps);
|
||||
sk_sp<GrXferProcessor> xp(
|
||||
GrXPFactory::MakeXferProcessor(xpf, colorInput, coverageType, false, caps));
|
||||
if (!xp) {
|
||||
|
Loading…
Reference in New Issue
Block a user