Revert "Revert "Create GrXferProcessor while doing GrProcessorSet analysis.""

This reverts commit 5dac9b3b5bf7e9c06c207cb92e257535c7d9ec95.

Bug: skia:
Change-Id: I3db2ec6776eb10c1f863b3992a2c8048c54b130f
Reviewed-on: https://skia-review.googlesource.com/12620
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp
index 8bdf6b6..9361764 100644
--- a/src/gpu/GrProcessorSet.cpp
+++ b/src/gpu/GrProcessorSet.cpp
@@ -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() {
     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 @@
             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 @@
     }
 
     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 @@
     } 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;
 }