Make GrFragmentProcessor auto-compare coord xforms.

Review URL: https://codereview.chromium.org/657923002
diff --git a/include/gpu/GrCoordTransform.h b/include/gpu/GrCoordTransform.h
index db71ff1..42598dd 100644
--- a/include/gpu/GrCoordTransform.h
+++ b/include/gpu/GrCoordTransform.h
@@ -91,12 +91,14 @@
         return &fMatrix;
     }
 
-    bool operator== (const GrCoordTransform& other) const {
-        return fSourceCoords == other.fSourceCoords &&
-               fMatrix.cheapEqualTo(other.fMatrix) &&
-               fReverseY == other.fReverseY;
+    bool operator== (const GrCoordTransform& that) const {
+        return fSourceCoords == that.fSourceCoords &&
+               fMatrix.cheapEqualTo(that.fMatrix) &&
+               fReverseY == that.fReverseY;
     }
 
+    bool operator!= (const GrCoordTransform& that) const { return !(*this == that); }
+
     GrCoordSet sourceCoords() const { return fSourceCoords; }
     const SkMatrix& getMatrix() const { return fMatrix; }
     bool reverseY() const { return fReverseY; }
diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h
index f872d90..4642307 100644
--- a/include/gpu/GrFragmentProcessor.h
+++ b/include/gpu/GrFragmentProcessor.h
@@ -46,7 +46,7 @@
         generate the same shader code. To test for identical code generation use the prceossor' keys
         computed by the GrBackendProcessorFactory. */
     bool isEqual(const GrFragmentProcessor& other) const {
-        if (&this->getFactory() != &other.getFactory()) {
+        if (&this->getFactory() != &other.getFactory() || !this->hasSameTransforms(other)) {
             return false;
         }
         bool result = this->onIsEqual(other);
@@ -61,11 +61,20 @@
 protected:
     /**
      * Fragment Processor subclasses call this from their constructor to register coordinate
-     * transformations. The processor subclass manages the lifetime of the transformations (this
-     * function only stores a pointer). The GrCoordTransform is typically a member field of the
-     * GrProcessor subclass. When the matrix has perspective, the transformed coordinates will have
-     * 3 components. Otherwise they'll have 2. This must only be called from the constructor because
-     * GrProcessors are immutable.
+     * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
+     * in their FS code. The matrix expresses a transformation from local space. For a given
+     * fragment the matrix will be applied to the local coordinate that maps to the fragment.
+     *
+     * When the transformation has perspective, the transformed coordinates will have
+     * 3 components. Otherwise they'll have 2. 
+     *
+     * This must only be called from the constructor because GrProcessors are immutable. The
+     * processor subclass manages the lifetime of the transformations (this function only stores a
+     * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass. 
+     *
+     * A processor subclass that has multiple methods of construction should always add its coord
+     * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
+     * compares transforms and will assume they line up across the two processor instances.
      */
     void addCoordTransform(const GrCoordTransform*);
 
@@ -84,10 +93,15 @@
     void setWillNotUseInputColor() { fWillUseInputColor = false; }
 
 private:
-    /** Subclass implements this to support isEqual(). It will only be called if it is known that
-        the two prceossor are of the same subclass (i.e. they return the same object from
-        getFactory()).*/
-    virtual bool onIsEqual(const GrFragmentProcessor& other) const = 0;
+    /**
+     * Subclass implements this to support isEqual(). It will only be called if it is known that
+     * the two processors are of the same subclass (i.e. they return the same object from
+     * getFactory()). The processor subclass should not compare its coord transforms as that will
+     * be performed automatically in the non-virtual isEqual().
+     */
+    virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
+
+    bool hasSameTransforms(const GrFragmentProcessor&) const;
 
     SkSTArray<4, const GrCoordTransform*, true>  fCoordTransforms;
     bool                                         fWillReadDstColor;
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index de17806..68cdcc6 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -579,7 +579,6 @@
                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
                fNumOctaves == s.fNumOctaves &&
                fStitchTiles == s.fStitchTiles &&
-               fCoordTransform.getMatrix() == s.fCoordTransform.getMatrix() &&
                fAlpha == s.fAlpha &&
                fPermutationsAccess.getTexture() == s.fPermutationsAccess.getTexture() &&
                fNoiseAccess.getTexture() == s.fNoiseAccess.getTexture() &&
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index b297b14..f131d72 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -1205,8 +1205,7 @@
         return fTextureAccess.getTexture() == s.fTextureAccess.getTexture()  &&
             fTextureAccess.getParams().getTileModeX() ==
                 s.fTextureAccess.getParams().getTileModeX() &&
-            this->useAtlas() == s.useAtlas() &&
-            fCoordTransform.getMatrix().cheapEqualTo(s.fCoordTransform.getMatrix());
+            this->useAtlas() == s.useAtlas();
     }
 
     return false;
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index fbcd0f3..a0ad99e 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -175,3 +175,16 @@
     fCoordTransforms.push_back(transform);
     SkDEBUGCODE(transform->setInProcessor();)
 }
+
+bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
+    if (fCoordTransforms.count() != that.fCoordTransforms.count()) {
+        return false;
+    }
+    int count = fCoordTransforms.count();
+    for (int i = 0; i < count; ++i) {
+        if (*fCoordTransforms[i] != *that.fCoordTransforms[i]) {
+            return false;
+        }
+    }
+    return true;
+}
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index ad13c2e..c16c088 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -38,9 +38,7 @@
      */
     bool hasSameTextureParamsMatrixAndSourceCoords(const GrSingleTextureEffect& other) const {
         // We don't have to check the accesses' swizzles because they are inferred from the texture.
-        return fTextureAccess == other.fTextureAccess &&
-               fCoordTransform.getMatrix().cheapEqualTo(other.fCoordTransform.getMatrix()) &&
-               fCoordTransform.sourceCoords() == other.fCoordTransform.sourceCoords();
+        return fTextureAccess == other.fTextureAccess;
     }
 
     /**