Add GrProcOptInfo class to track various output information for color and coverage...
authoregdaniel <egdaniel@google.com>
Thu, 13 Nov 2014 19:00:34 +0000 (11:00 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 13 Nov 2014 19:00:34 +0000 (11:00 -0800)
BUG=skia:

Review URL: https://codereview.chromium.org/719203002

gyp/gpu.gypi
include/gpu/GrInvariantOutput.h
src/gpu/GrDrawState.cpp
src/gpu/GrDrawState.h
src/gpu/GrInvariantOutput.cpp
src/gpu/GrOptDrawState.cpp
src/gpu/GrPaint.cpp
src/gpu/GrProcOptInfo.cpp [new file with mode: 0644]
src/gpu/GrProcOptInfo.h [new file with mode: 0644]
src/gpu/GrProcessor.cpp

index 430bac9..1bad40a 100644 (file)
       '<(skia_src_path)/gpu/GrProgramDesc.h',
       '<(skia_src_path)/gpu/GrProgramElement.cpp',
       '<(skia_src_path)/gpu/GrProcessor.cpp',
+      '<(skia_src_path)/gpu/GrProcOptInfo.cpp',
+      '<(skia_src_path)/gpu/GrProcOptInfo.h',
       '<(skia_src_path)/gpu/GrGpuResourceRef.cpp',
       '<(skia_src_path)/gpu/GrPlotMgr.h',
       '<(skia_src_path)/gpu/GrRecordReplaceDraw.cpp',
index 8f38d1f..0805ac7 100644 (file)
@@ -92,22 +92,9 @@ public:
         }
     }
 
-    bool isOpaque() const {
-        return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
-    }
-
-    bool isSolidWhite() const {
-        return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
-    }
-
     GrColor color() const { return fColor; }
     uint8_t validFlags() const { return fValidFlags; }
 
-    bool willUseInputColor() const { return fWillUseInputColor; }
-    void resetWillUseInputColor() { fWillUseInputColor = true; }
-
-    void resetNonMulStageFound() { fNonMulStageFound = false; }
-
     /**
      * If isSingleComponent is true, then the flag values for r, g, b, and a must all be the
      * same. If the flags are all set then all color components must be equal.
@@ -122,6 +109,16 @@ protected:
     bool fWillUseInputColor;
 
 private:
+    friend class GrProcOptInfo;
+
+    void reset(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) {
+        fColor = color;
+        fValidFlags = flags;
+        fIsSingleComponent = isSingleComponent;
+        fNonMulStageFound = false;
+        fWillUseInputColor = true;
+    }
+
     void internalSetToTransparentBlack() {
         fValidFlags = kRGBA_GrColorComponentFlags;
         fColor = 0;
@@ -137,6 +134,19 @@ private:
         return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor));
     }
 
+    bool isOpaque() const {
+        return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
+    }
+
+    bool isSolidWhite() const {
+        return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
+    }
+
+    bool willUseInputColor() const { return fWillUseInputColor; }
+    void resetWillUseInputColor() { fWillUseInputColor = true; }
+
+    void resetNonMulStageFound() { fNonMulStageFound = false; }
+
     SkDEBUGCODE(bool colorComponentsAllEqual() const;)
     /**
      * If alpha is valid, check that any valid R,G,B values are <= A
index 513c3bf..6558b0d 100644 (file)
@@ -8,9 +8,9 @@
 #include "GrDrawState.h"
 
 #include "GrBlend.h"
-#include "GrInvariantOutput.h"
 #include "GrOptDrawState.h"
 #include "GrPaint.h"
+#include "GrProcOptInfo.h"
 
 //////////////////////////////////////////////////////////////////////////////s
 
@@ -151,6 +151,15 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
 
     fHints = that.fHints;
 
+    fColorProcInfoValid = that.fColorProcInfoValid;
+    fCoverageProcInfoValid = that.fCoverageProcInfoValid;
+    if (fColorProcInfoValid) {
+        fColorProcInfo = that.fColorProcInfo;
+    }
+    if (fCoverageProcInfoValid) {
+        fCoverageProcInfo = that.fCoverageProcInfo;
+    }
+
     memcpy(fFixedFunctionVertexAttribIndices,
             that.fFixedFunctionVertexAttribIndices,
             sizeof(fFixedFunctionVertexAttribIndices));
@@ -184,6 +193,9 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
     fDrawFace = kBoth_DrawFace;
 
     fHints = 0;
+
+    fColorProcInfoValid = false;
+    fCoverageProcInfoValid = false;
 }
 
 bool GrDrawState::setIdentityViewMatrix()  {
@@ -239,6 +251,8 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
 
     this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
     this->setCoverage(0xFF);
+    fColorProcInfoValid = false;
+    fCoverageProcInfoValid = false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -336,6 +350,8 @@ void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int co
         overlapCheck |= (mask << offsetShift);
 #endif
     }
+    fColorProcInfoValid = false;
+    fCoverageProcInfoValid = false;
     // Positions must be specified.
     SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
 }
@@ -355,6 +371,8 @@ void GrDrawState::setDefaultVertexAttribs() {
            0xff,
            sizeof(fFixedFunctionVertexAttribIndices));
     fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
+    fColorProcInfoValid = false;
+    fCoverageProcInfoValid = false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -384,24 +402,8 @@ bool GrDrawState::hasSolidCoverage() const {
         return false;
     }
 
-    GrColor color;
-    GrColorComponentFlags flags;
-    // Initialize to an unknown starting coverage if per-vertex coverage is specified.
-    if (this->hasCoverageVertexAttribute()) {
-        color = 0;
-        flags = static_cast<GrColorComponentFlags>(0);
-    } else {
-        color = this->getCoverageColor();
-        flags = kRGBA_GrColorComponentFlags;
-    }
-    GrInvariantOutput inout(color, flags, true);
-
-    // check the coverage output from the GP
-    if (this->hasGeometryProcessor()) {
-        fGeometryProcessor->computeInvariantOutput(&inout);
-    }
-
-    return inout.isSolidWhite();
+    this->calcCoverageInvariantOutput();
+    return fCoverageProcInfo.isSolidWhite();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -419,18 +421,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
 
 bool GrDrawState::willEffectReadDstColor() const {
     if (!this->isColorWriteDisabled()) {
-        for (int s = 0; s < this->numColorStages(); ++s) {
-            if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
-                return true;
-            }
-        }
-    }
-    for (int s = 0; s < this->numCoverageStages(); ++s) {
-        if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
+        this->calcColorInvariantOutput();
+        if (fColorProcInfo.readsDst()) {
             return true;
         }
     }
-    return false;
+    this->calcCoverageInvariantOutput();
+    return fCoverageProcInfo.readsDst();
 }
 
 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
@@ -451,6 +448,10 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
         int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
         SkASSERT(n >= 0);
         fDrawState->fCoverageStages.pop_back_n(n);
+        if (m + n > 0) {
+            fDrawState->fColorProcInfoValid = false;
+            fDrawState->fCoverageProcInfoValid = false;
+        }
         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
     }
     fDrawState = ds;
@@ -689,60 +690,13 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
     return kNone_BlendOpt;
 }
 
-
 bool GrDrawState::srcAlphaWillBeOne() const {
-    GrColor color;
-    GrColorComponentFlags flags;
-    // Check if per-vertex or constant color may have partial alpha
-    if (this->hasColorVertexAttribute()) {
-        if (fHints & kVertexColorsAreOpaque_Hint) {
-            flags = kA_GrColorComponentFlag;
-            color = 0xFF << GrColor_SHIFT_A;
-        } else {
-            flags = static_cast<GrColorComponentFlags>(0);
-            color = 0;
-        }
-    } else {
-        flags = kRGBA_GrColorComponentFlags;
-        color = this->getColor();
-    }
-    GrInvariantOutput inoutColor(color, flags, false);
-
-    // Run through the color stages
-    for (int s = 0; s < this->numColorStages(); ++s) {
-        const GrProcessor* processor = this->getColorStage(s).getProcessor();
-        processor->computeInvariantOutput(&inoutColor);
-    }
-
-    // Check whether coverage is treated as color. If so we run through the coverage computation.
+    this->calcColorInvariantOutput();
     if (this->isCoverageDrawing()) {
-        // The shader generated for coverage drawing runs the full coverage computation and then
-        // makes the shader output be the multiplication of color and coverage. We mirror that here.
-        if (this->hasCoverageVertexAttribute()) {
-            flags = static_cast<GrColorComponentFlags>(0);
-            color = 0;
-        } else {
-            flags = kRGBA_GrColorComponentFlags;
-            color = this->getCoverageColor();
-        }
-        GrInvariantOutput inoutCoverage(color, flags, true);
-
-        if (this->hasGeometryProcessor()) {
-            fGeometryProcessor->computeInvariantOutput(&inoutCoverage);
-        }
-
-        // Run through the coverage stages
-        for (int s = 0; s < this->numCoverageStages(); ++s) {
-            const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
-            processor->computeInvariantOutput(&inoutCoverage);
-        }
-
-        // Since the shader will multiply coverage and color, the only way the final A==1 is if
-        // coverage and color both have A==1.
-        return (inoutColor.isOpaque() && inoutCoverage.isOpaque());
+        this->calcCoverageInvariantOutput();
+        return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque());
     }
-
-    return inoutColor.isOpaque();
+    return fColorProcInfo.isOpaque();
 }
 
 bool GrDrawState::willBlendWithDst() const {
@@ -767,3 +721,43 @@ bool GrDrawState::willBlendWithDst() const {
     return false;
 }
 
+void GrDrawState::calcColorInvariantOutput() const {
+    if (!fColorProcInfoValid) {
+        GrColor color;
+        GrColorComponentFlags flags;
+        if (this->hasColorVertexAttribute()) {
+            if (fHints & kVertexColorsAreOpaque_Hint) {
+                flags = kA_GrColorComponentFlag;
+                color = 0xFF << GrColor_SHIFT_A;
+            } else {
+                flags = static_cast<GrColorComponentFlags>(0);
+                color = 0;
+            }
+        } else {
+            flags = kRGBA_GrColorComponentFlags;
+            color = this->getColor();
+        }
+        fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(),
+                                             color, flags, false);
+        fColorProcInfoValid = true;
+    }
+}
+
+void GrDrawState::calcCoverageInvariantOutput() const {
+    if (!fCoverageProcInfoValid) {
+        GrColor color;
+        GrColorComponentFlags flags;
+        // Check if per-vertex or constant color may have partial alpha
+        if (this->hasCoverageVertexAttribute()) {
+            flags = static_cast<GrColorComponentFlags>(0);
+            color = 0;
+        } else {
+            flags = kRGBA_GrColorComponentFlags;
+            color = this->getCoverageColor();
+        }
+        fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
+                                                color, flags, true, fGeometryProcessor.get());
+        fCoverageProcInfoValid = true;
+    }
+}
+
index 5c76aed..454390c 100644 (file)
@@ -14,6 +14,7 @@
 #include "GrGeometryProcessor.h"
 #include "GrGpuResourceRef.h"
 #include "GrProcessorStage.h"
+#include "GrProcOptInfo.h"
 #include "GrRenderTarget.h"
 #include "GrStencil.h"
 #include "SkMatrix.h"
@@ -181,6 +182,7 @@ public:
     void setColor(GrColor color) {
         if (color != fColor) {
             fColor = color;
+            fColorProcInfoValid = false;
         }
     }
 
@@ -212,6 +214,7 @@ public:
     void setCoverage(uint8_t coverage) {
         if (coverage != fCoverage) {
             fCoverage = coverage;
+            fCoverageProcInfoValid = false;
         }
     }
 
@@ -227,6 +230,7 @@ public:
         SkASSERT(geometryProcessor);
         SkASSERT(!this->hasGeometryProcessor());
         fGeometryProcessor.reset(SkRef(geometryProcessor));
+        fCoverageProcInfoValid = false;
         return geometryProcessor;
     }
 
@@ -270,12 +274,14 @@ public:
     const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
         SkASSERT(effect);
         SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
+        fColorProcInfoValid = false;
         return effect;
     }
 
     const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* effect) {
         SkASSERT(effect);
         SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (effect));
+        fCoverageProcInfoValid = false;
         return effect;
     }
 
@@ -802,6 +808,18 @@ private:
      */
     bool srcAlphaWillBeOne() const;
 
+    /**
+     * If fColorProcInfoValid is false, function calculates the invariant output for the color
+     * stages and results are stored in fColorProcInfo.
+     */
+    void calcColorInvariantOutput() const;
+
+    /**
+     * If fCoverageProcInfoValid is false, function calculates the invariant output for the coverage
+     * stages and results are stored in fCoverageProcInfo.
+     */
+    void calcCoverageInvariantOutput() const;
+
     void onReset(const SkMatrix* initialViewMatrix);
 
     // Some of the auto restore objects assume that no effects are removed during their lifetime.
@@ -838,6 +856,11 @@ private:
     // not need to be compared in op==.
     int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
 
+    mutable GrProcOptInfo fColorProcInfo;
+    mutable GrProcOptInfo fCoverageProcInfo;
+    mutable bool fColorProcInfoValid;
+    mutable bool fCoverageProcInfoValid;
+
     friend class GrOptDrawState;
 
     typedef SkRefCnt INHERITED;
index 6f9a9d1..4c77df3 100644 (file)
@@ -52,5 +52,6 @@ bool GrInvariantOutput::validPreMulColor() const {
     }
     return true;
 }
+
 #endif // end DEBUG
 
index 7d8b06c..0f2fcf0 100644 (file)
@@ -11,7 +11,7 @@
 #include "GrDrawState.h"
 #include "GrDrawTargetCaps.h"
 #include "GrGpu.h"
-#include "GrInvariantOutput.h"
+#include "GrProcOptInfo.h"
 
 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
                                BlendOptFlags blendOptFlags,
@@ -239,23 +239,14 @@ void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds,
             color = 0;
         }
     }
-    GrInvariantOutput inout(color, flags, false);
-
-    for (int i = 0; i < ds.numColorStages(); ++i) {
-        const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
-        fp->computeInvariantOutput(&inout);
-        if (!inout.willUseInputColor()) {
-            *firstColorStageIdx = i;
-            descInfo->fInputColorIsUsed = false;
-        }
-        if (kRGBA_GrColorComponentFlags == inout.validFlags()) {
-            *firstColorStageIdx = i + 1;
-            fColor = inout.color();
-            descInfo->fInputColorIsUsed = true;
+    GrProcOptInfo poi;
+    if (ds.numColorStages() > 0) {
+        poi.calcWithInitialValues(&ds.getColorStage(0), ds.numColorStages(), color, flags, false);
+        *firstColorStageIdx = poi.firstEffectiveStageIndex();
+        descInfo->fInputColorIsUsed = poi.inputColorIsUsed();
+        fColor = poi.inputColorToEffectiveStage();
+        if (poi.removeVertexAttrib()) {
             *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
-            // Since we are clearing all previous color stages we are in a state where we have found
-            // zero stages that don't multiply the inputColor.
-            inout.resetNonMulStageFound();
         }
     }
 }
index 3663787..7d89535 100644 (file)
@@ -9,7 +9,7 @@
 #include "GrPaint.h"
 
 #include "GrBlend.h"
-#include "GrInvariantOutput.h"
+#include "GrProcOptInfo.h"
 #include "effects/GrSimpleTextureEffect.h"
 
 void GrPaint::addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
@@ -37,8 +37,8 @@ bool GrPaint::isOpaque() const {
 }
 
 bool GrPaint::isOpaqueAndConstantColor(GrColor* color) const {
-    GrColor tempColor;
-    uint32_t colorComps;
+    GrColor tempColor = 0;
+    uint32_t colorComps = 0;
     if (this->getOpaqueAndKnownColor(&tempColor, &colorComps)) {
         if (kRGBA_GrColorComponentFlags == colorComps) {
             *color = tempColor;
@@ -52,29 +52,24 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
                                      uint32_t* solidColorKnownComponents) const {
 
     // TODO: Share this implementation with GrDrawState
+    
+    GrProcOptInfo coverageProcInfo;
+    coverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(),
+                                           0xFFFFFFFF, kRGBA_GrColorComponentFlags, true);
 
-    GrInvariantOutput inoutCoverage(0xFFFFFFFF,
-                                    kRGBA_GrColorComponentFlags,
-                                    true);
-    int count = fCoverageStages.count();
-    for (int i = 0; i < count; ++i) {
-        fCoverageStages[i].getProcessor()->computeInvariantOutput(&inoutCoverage);
-    }
-    if (!inoutCoverage.isSolidWhite()) {
+    if (!coverageProcInfo.isSolidWhite()) {
         return false;
     }
 
-    GrInvariantOutput inout(fColor, kRGBA_GrColorComponentFlags, false);
-    count = fColorStages.count();
-    for (int i = 0; i < count; ++i) {
-        fColorStages[i].getProcessor()->computeInvariantOutput(&inout);
-    }
+    GrProcOptInfo colorProcInfo;
+    colorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(), fColor,
+                                        kRGBA_GrColorComponentFlags, false);
 
     SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents));
 
     GrBlendCoeff srcCoeff = fSrcBlendCoeff;
     GrBlendCoeff dstCoeff = fDstBlendCoeff;
-    GrSimplifyBlend(&srcCoeff, &dstCoeff, inout.color(), inout.validFlags(),
+    GrSimplifyBlend(&srcCoeff, &dstCoeff, colorProcInfo.color(), colorProcInfo.validFlags(),
                     0, 0, 0);
 
     bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoeff);
@@ -87,8 +82,8 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
                     break;
 
                 case kOne_GrBlendCoeff:
-                    *solidColor = inout.color();
-                    *solidColorKnownComponents = inout.validFlags();
+                    *solidColor = colorProcInfo.color();
+                    *solidColorKnownComponents = colorProcInfo.validFlags();
                     break;
 
                 // The src coeff should never refer to the src and if it refers to dst then opaque
diff --git a/src/gpu/GrProcOptInfo.cpp b/src/gpu/GrProcOptInfo.cpp
new file mode 100644 (file)
index 0000000..c3ca100
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrProcOptInfo.h"
+
+#include "GrGeometryProcessor.h"
+#include "GrProcessorStage.h"
+
+void GrProcOptInfo::calcWithInitialValues(const GrFragmentStage* stages,
+                                          int stageCount,
+                                          GrColor startColor,
+                                          GrColorComponentFlags flags,
+                                          bool areCoverageStages,
+                                          const GrGeometryProcessor* gp) {
+    fInOut.reset(startColor, flags, areCoverageStages);
+    fFirstEffectStageIndex = 0;
+    fInputColorIsUsed = true;
+    fInputColor = startColor;
+    fRemoveVertexAttrib = false;
+    fReadsDst = false;
+
+    if (areCoverageStages && gp) {
+        gp->computeInvariantOutput(&fInOut);
+    }
+
+    for (int i = 0; i < stageCount; ++i) {
+        const GrFragmentProcessor* processor = stages[i].getProcessor();
+        fInOut.resetWillUseInputColor();
+        processor->computeInvariantOutput(&fInOut);
+        #ifdef SK_DEBUG
+        fInOut.validate();
+        #endif
+        if (!fInOut.willUseInputColor()) {
+            fFirstEffectStageIndex = i;
+            fInputColorIsUsed = false;
+            fReadsDst = false; // Reset this since we don't care if previous stages read dst
+        }
+        if (processor->willReadDstColor()) {
+            fReadsDst = true;
+        }
+        if (kRGBA_GrColorComponentFlags == fInOut.validFlags()) {
+            fFirstEffectStageIndex = i + 1;
+            fInputColor = fInOut.color();
+            fInputColorIsUsed = true;
+            fRemoveVertexAttrib = true;
+            // Since we are clearing all previous color stages we are in a state where we have found
+            // zero stages that don't multiply the inputColor.
+            fInOut.resetNonMulStageFound();
+            fReadsDst = false; // Reset this since we don't care if previous stages read dst
+        }
+    }
+}
diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h
new file mode 100644 (file)
index 0000000..5252e85
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrProcOptInfo_DEFINED
+#define GrProcOptInfo_DEFINED
+
+#include "GrColor.h"
+#include "GrInvariantOutput.h"
+
+class GrFragmentStage;
+class GrGeometryProcessor;
+
+/**
+ * GrProcOptInfo gathers invariant data from a set of processor stages.It is used to recognize
+ * optimizations related to eliminating stages and vertex attributes that aren't necessary for a
+ * draw.
+ */
+class GrProcOptInfo {
+public:
+    GrProcOptInfo()
+        : fInOut(0, static_cast<GrColorComponentFlags>(0), false)
+        , fFirstEffectStageIndex(0)
+        , fInputColorIsUsed(true)
+        , fInputColor(0)
+        , fRemoveVertexAttrib(false)
+        , fReadsDst(false) {}
+
+    void calcWithInitialValues(const GrFragmentStage*, int stageCount, GrColor startColor,
+                               GrColorComponentFlags flags, bool areCoverageStages,
+                               const GrGeometryProcessor* gp = NULL);
+
+    bool isSolidWhite() const { return fInOut.isSolidWhite(); }
+    bool isOpaque() const { return fInOut.isOpaque(); }
+
+    GrColor color() const { return fInOut.color(); }
+    uint8_t validFlags() const { return fInOut.validFlags(); }
+
+    /**
+     * Returns the index of the first effective color stage. If an intermediate stage doesn't read
+     * its input or has a known output, then we can ignore all earlier stages since they will not
+     * affect the final output. Thus the first effective stage index is the index to the first stage
+     * that will have an effect on the final output.
+     *
+     * If stages before the firstEffectiveStageIndex are removed, corresponding values from
+     * inputColorIsUsed(), inputColorToEffectiveStage(), removeVertexAttribs(), and readsDst() must
+     * be used when setting up the draw to ensure correct drawing.
+     */
+    int firstEffectiveStageIndex() const { return fFirstEffectStageIndex; }
+
+    /**
+     * True if the first effective stage reads its input, false otherwise.
+     */
+    bool inputColorIsUsed() const { return fInputColorIsUsed; }
+
+    /**
+     * If input color is used and per-vertex colors are not used, this is the input color to the
+     * first effective stage.
+     */
+    GrColor inputColorToEffectiveStage() const { return fInputColor; }
+
+    /**
+     * Given the set of optimizations determined by GrProcOptInfo, should the caller remove the
+     * color/coverage vertex attribute that was input to the first stage.
+     */
+    bool removeVertexAttrib() const { return fRemoveVertexAttrib; }
+
+    /**
+     * Returns true if any of the stages preserved by GrProcOptInfo read the dst color.
+     */
+    bool readsDst() const { return fReadsDst; }
+
+private:
+    GrInvariantOutput fInOut;
+    int fFirstEffectStageIndex;
+    bool fInputColorIsUsed;
+    GrColor fInputColor;
+    bool fRemoveVertexAttrib;
+    bool fReadsDst;
+};
+
+#endif
index 31f0004..01071da 100644 (file)
@@ -130,11 +130,7 @@ bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const {
 }
 
 void GrProcessor::computeInvariantOutput(GrInvariantOutput* inout) const {
-    inout->resetWillUseInputColor();
     this->onComputeInvariantOutput(inout);
-#ifdef SK_DEBUG
-    inout->validate();
-#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////