Allow gradient optimization with perspective

Before, gradients would only interpolate the linear portion of the
quadratic equation if there was no perspective. This updates them to
do so even in the case that there is perspective. The rearrangement
of math causes noise differences in the following gm tests:

gradients_no_texture_gpu
gradients_view_perspective_gpu
gradients_local_perspective_gpu
gradients_gpu

R=bsalomon@google.com

Author: cdalton@nvidia.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk/include@11595 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/GrCoordTransform.h b/gpu/GrCoordTransform.h
index afe2e5b..14e2620 100644
--- a/gpu/GrCoordTransform.h
+++ b/gpu/GrCoordTransform.h
@@ -41,12 +41,13 @@
  */
 class GrCoordTransform : public SkNoncopyable {
 public:
-    GrCoordTransform() {}
+    GrCoordTransform() { SkDEBUGCODE(fInEffect = false); }
 
     /**
      * Create a transformation that maps [0, 1] to a texture's boundaries.
      */
     GrCoordTransform(GrCoordSet sourceCoords, const GrTexture* texture) {
+        SkDEBUGCODE(fInEffect = false);
         this->reset(sourceCoords, texture);
     }
 
@@ -56,20 +57,40 @@
      * coord convention.
      */
     GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) {
+        SkDEBUGCODE(fInEffect = false);
         this->reset(sourceCoords, m, texture);
     }
 
     void reset(GrCoordSet sourceCoords, const GrTexture* texture) {
+        SkASSERT(!fInEffect);
         SkASSERT(NULL != texture);
         this->reset(sourceCoords, GrEffect::MakeDivByTextureWHMatrix(texture), texture);
     }
 
     void reset(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) {
+        SkASSERT(!fInEffect);
         fSourceCoords = sourceCoords;
         fMatrix = m;
         fReverseY = NULL != texture && kBottomLeft_GrSurfaceOrigin == texture->origin();
     }
 
+    GrCoordTransform& operator= (const GrCoordTransform& other) {
+        SkASSERT(!fInEffect);
+        fSourceCoords = other.fSourceCoords;
+        fMatrix = other.fMatrix;
+        fReverseY = other.fReverseY;
+        return *this;
+    }
+
+    /**
+     * Access the matrix for editing. Note, this must be done before adding the transform to an
+     * effect, since effects are immutable.
+     */
+    SkMatrix* accessMatrix() {
+        SkASSERT(!fInEffect);
+        return &fMatrix;
+    }
+
     bool operator== (const GrCoordTransform& other) const {
         return fSourceCoords == other.fSourceCoords &&
                fMatrix.cheapEqualTo(other.fMatrix) &&
@@ -86,6 +107,13 @@
     bool       fReverseY;
 
     typedef SkNoncopyable INHERITED;
+
+#ifdef SK_DEBUG
+public:
+    void setInEffect() const { fInEffect = true; }
+private:
+    mutable bool fInEffect;
+#endif
 };
 
 #endif