Combine coverage in GrAppliedClip using RunInSeries.

This lets us end up with a single coverage processor instead of an array
of them. Coverage processors simply multiply against their input so the
results are conceptually equivalent.

In practice, it is uncommon to have more than one applied clip (at least
on GMs).

Change-Id: I73d5da8015f48c6cb1d3f37257e7e0c4329579b5
Bug: skia:10217
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/305117
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
John Stiles 2020-07-22 18:18:12 -04:00 committed by Skia Commit-Bot
parent cc848b59f8
commit 59e18dc6dd
7 changed files with 43 additions and 47 deletions

View File

@ -50,11 +50,11 @@ enum SrcType {
const struct {
SkBlendMode fMode;
int fSourceTypeMask; // The source types to use this
// mode with. See draw_mode for
// an explanation of each type.
// PDF has to play some tricks
// to support the base modes,
// test those more extensively.
// mode with. See draw_mode for
// an explanation of each type.
// PDF has to play some tricks
// to support the base modes,
// test those more extensively.
} gModes[] = {
{ SkBlendMode::kClear, kAll_SrcType },
{ SkBlendMode::kSrc, kAll_SrcType },

View File

@ -104,59 +104,57 @@ public:
const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); }
uint32_t stencilStackID() const { return fHardClip.stencilStackID(); }
bool hasStencilClip() const { return fHardClip.hasStencilClip(); }
int numClipCoverageFragmentProcessors() const { return fClipCoverageFPs.count(); }
const GrFragmentProcessor* clipCoverageFragmentProcessor(int i) const {
SkASSERT(fClipCoverageFPs[i]);
return fClipCoverageFPs[i].get();
int hasCoverageFragmentProcessor() const { return fCoverageFP != nullptr; }
const GrFragmentProcessor* coverageFragmentProcessor() const {
SkASSERT(fCoverageFP != nullptr);
return fCoverageFP.get();
}
std::unique_ptr<const GrFragmentProcessor> detachClipCoverageFragmentProcessor(int i) {
SkASSERT(fClipCoverageFPs[i]);
return std::move(fClipCoverageFPs[i]);
std::unique_ptr<const GrFragmentProcessor> detachCoverageFragmentProcessor() {
SkASSERT(fCoverageFP != nullptr);
return std::move(fCoverageFP);
}
const GrAppliedHardClip& hardClip() const { return fHardClip; }
GrAppliedHardClip& hardClip() { return fHardClip; }
void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) {
SkASSERT(fp);
fClipCoverageFPs.push_back(std::move(fp));
if (fCoverageFP == nullptr) {
fCoverageFP = std::move(fp);
} else {
// Run this coverage FP in series with the previously-added coverage.
std::unique_ptr<GrFragmentProcessor> series[] = {
std::move(fCoverageFP),
std::move(fp),
};
fCoverageFP = GrFragmentProcessor::RunInSeries(series, SK_ARRAY_COUNT(series));
}
}
bool doesClip() const {
return fHardClip.doesClip() || !fClipCoverageFPs.empty();
return fHardClip.doesClip() || fCoverageFP != nullptr;
}
bool operator==(const GrAppliedClip& that) const {
if (fHardClip != that.fHardClip ||
fClipCoverageFPs.count() != that.fClipCoverageFPs.count()) {
this->hasCoverageFragmentProcessor() != that.hasCoverageFragmentProcessor()) {
return false;
}
for (int i = 0; i < fClipCoverageFPs.count(); ++i) {
if (!fClipCoverageFPs[i] || !that.fClipCoverageFPs[i]) {
if (fClipCoverageFPs[i] == that.fClipCoverageFPs[i]) {
continue; // Both are null.
}
return false;
}
if (!fClipCoverageFPs[i]->isEqual(*that.fClipCoverageFPs[i])) {
return false;
}
if (fCoverageFP != nullptr && !fCoverageFP->isEqual(*that.fCoverageFP)) {
return false;
}
return true;
}
bool operator!=(const GrAppliedClip& that) const { return !(*this == that); }
void visitProxies(const GrOp::VisitProxyFunc& func) const {
for (const std::unique_ptr<GrFragmentProcessor>& fp : fClipCoverageFPs) {
if (fp) { // This might be called after detach.
fp->visitProxies(func);
}
if (fCoverageFP != nullptr) {
fCoverageFP->visitProxies(func);
}
}
private:
GrAppliedHardClip fHardClip;
SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fClipCoverageFPs;
std::unique_ptr<GrFragmentProcessor> fCoverageFP;
};
#endif

View File

@ -311,10 +311,9 @@ bool GrOpsTask::OpChain::prependChain(OpChain* that, const GrCaps& caps,
fBounds = that->fBounds;
that->fDstProxyView.setProxyView({});
if (that->fAppliedClip) {
for (int i = 0; i < that->fAppliedClip->numClipCoverageFragmentProcessors(); ++i) {
that->fAppliedClip->detachClipCoverageFragmentProcessor(i);
}
if (that->fAppliedClip && that->fAppliedClip->hasCoverageFragmentProcessor()) {
// Obliterates the processor.
that->fAppliedClip->detachCoverageFragmentProcessor();
}
this->validate();
return true;

View File

@ -46,7 +46,7 @@ GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
fNumColorProcessors = processors.hasColorFragmentProcessor() ? 1 : 0;
int numTotalProcessors = fNumColorProcessors +
(processors.hasCoverageFragmentProcessor() ? 1 : 0) +
appliedClip.numClipCoverageFragmentProcessors();
(appliedClip.hasCoverageFragmentProcessor() ? 1 : 0);
fFragmentProcessors.reset(numTotalProcessors);
int currFPIdx = 0;
@ -56,8 +56,8 @@ GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
if (processors.hasCoverageFragmentProcessor()) {
fFragmentProcessors[currFPIdx++] = processors.detachCoverageFragmentProcessor();
}
for (int i = 0; i < appliedClip.numClipCoverageFragmentProcessors(); ++i) {
fFragmentProcessors[currFPIdx++] = appliedClip.detachClipCoverageFragmentProcessor(i);
if (appliedClip.hasCoverageFragmentProcessor()) {
fFragmentProcessors[currFPIdx++] = appliedClip.detachCoverageFragmentProcessor();
}
}

View File

@ -230,7 +230,8 @@ private:
friend bool operator&(Flags, InputFlags);
using FragmentProcessorArray = SkAutoSTArray<6, std::unique_ptr<const GrFragmentProcessor>>;
// A pipeline can contain up to three processors: color, paint coverage, and clip coverage.
using FragmentProcessorArray = SkAutoSTArray<3, std::unique_ptr<const GrFragmentProcessor>>;
GrSurfaceProxyView fDstProxyView;
SkIPoint fDstTextureOffset;

View File

@ -148,13 +148,11 @@ GrProcessorSet::Analysis GrProcessorSet::finalize(
}
coverageUsesLocalCoords |= fCoverageFragmentProcessor->usesVaryingCoords();
}
if (clip) {
hasCoverageFP = hasCoverageFP || clip->numClipCoverageFragmentProcessors();
for (int i = 0; i < clip->numClipCoverageFragmentProcessors(); ++i) {
const GrFragmentProcessor* clipFP = clip->clipCoverageFragmentProcessor(i);
analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
coverageUsesLocalCoords |= clipFP->usesVaryingCoords();
}
if (clip && clip->hasCoverageFragmentProcessor()) {
hasCoverageFP = true;
const GrFragmentProcessor* clipFP = clip->coverageFragmentProcessor();
analysis.fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
coverageUsesLocalCoords |= clipFP->usesVaryingCoords();
}
int colorFPsToEliminate = colorAnalysis.initialProcessorsToEliminate(overrideInputColor);
analysis.fInputColorType = static_cast<Analysis::PackedInputColorType>(

View File

@ -90,7 +90,7 @@ GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors(
if (fProcessors) {
GrProcessorAnalysisCoverage coverage = geometryCoverage;
if (GrProcessorAnalysisCoverage::kNone == coverage) {
coverage = clip->numClipCoverageFragmentProcessors()
coverage = clip->hasCoverageFragmentProcessor()
? GrProcessorAnalysisCoverage::kSingleChannel
: GrProcessorAnalysisCoverage::kNone;
}