Reland "Centralize geometry processor vertex shader transform code"

This is a reland of 0426947243e1d6b470830c4d3b1c5704ed1f23e1

Original change's description:
> Centralize geometry processor vertex shader transform code
> 
> GrGLSLGeometryProcessors no longer have to call emitTransforms() in
> their onEmitCode() function. Instead, the GpArgs struct allows them to
> set a GrShaderVar that holds the computed or explicitly provided local
> coordinates in the vertex shader.
> 
> The base GrGLSLGeometryProcessor now automatically uses that to collect
> all of the transforms that can then be lifted out of FPs to the vertex
> shader, and base their computation on the GP provided local coordinate.
> 
> As part of this, there is no more built-in magic concatenation of a
> local matrix / inverse view matrix to these coordinate transforms. GP
> implementations that relied on this now manage their own uniform for this
> matrix and compute the local coordinate before assigning to GpArgs.
> 
> The base GrGLSLGeometryProcessor is updated to provide helpers for this
> pattern.
> 
> Bug: skia:10396
> Change-Id: I56afb3fff4b806f6015ab13626ac1afde9ef5c2b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/297027
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>

Bug: skia:10396
Change-Id: If1347bcacb7c405a66f9d4c5b0059e9d735b3f9a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/298062
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index ca11c0d..2dc3e1a 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -577,14 +577,11 @@
 
             // Setup position
             this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name());
-
-            // emit transforms
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 qe.fInPosition.asShaderVar(),
-                                 qe.fLocalMatrix,
-                                 args.fFPCoordTransformHandler);
+            if (qe.fUsesLocalCoords) {
+                this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+                                      qe.fInPosition.asShaderVar(), qe.fLocalMatrix,
+                                      &fLocalMatrixUniform);
+            }
 
             fragBuilder->codeAppendf("half edgeAlpha;");
 
@@ -611,18 +608,24 @@
                                   const GrShaderCaps&,
                                   GrProcessorKeyBuilder* b) {
             const QuadEdgeEffect& qee = gp.cast<QuadEdgeEffect>();
-            b->add32(SkToBool(qee.fUsesLocalCoords && qee.fLocalMatrix.hasPerspective()));
+            uint32_t key = (uint32_t) qee.fUsesLocalCoords;
+            key |= ComputeMatrixKey(qee.fLocalMatrix) << 1;
+            b->add32(key);
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
                      const GrPrimitiveProcessor& gp,
                      const CoordTransformRange& transformRange) override {
             const QuadEdgeEffect& qe = gp.cast<QuadEdgeEffect>();
-            this->setTransformDataHelper(qe.fLocalMatrix, pdman, transformRange);
+            this->setTransformDataHelper(pdman, transformRange);
+            this->setTransform(pdman, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
         }
 
     private:
         typedef GrGLSLGeometryProcessor INHERITED;
+
+        SkMatrix      fLocalMatrix = SkMatrix::InvalidMatrix();
+        UniformHandle fLocalMatrixUniform;
     };
 
     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 6f663f6..5ee04a4 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -876,14 +876,19 @@
 private:
     UniformHandle fParamUniform;
     UniformHandle fColorUniform;
+    UniformHandle fLocalMatrixUniform;
+
+    SkMatrix      fLocalMatrix;
     SkPMColor4f   fColor;
     SkScalar      fPrevRadius;
     SkScalar      fPrevCenterX;
     SkScalar      fPrevIntervalLength;
+
     typedef GrGLSLGeometryProcessor INHERITED;
 };
 
 GLDashingCircleEffect::GLDashingCircleEffect() {
+    fLocalMatrix = SkMatrix::InvalidMatrix();
     fColor = SK_PMColor4fILLEGAL;
     fPrevRadius = SK_ScalarMin;
     fPrevCenterX = SK_ScalarMin;
@@ -915,14 +920,10 @@
 
     // Setup position
     this->writeOutputPosition(vertBuilder, gpArgs, dce.fInPosition.name());
-
-    // emit transforms
-    this->emitTransforms(vertBuilder,
-                         varyingHandler,
-                         uniformHandler,
-                         dce.fInPosition.asShaderVar(),
-                         dce.localMatrix(),
-                         args.fFPCoordTransformHandler);
+    if (dce.usesLocalCoords()) {
+        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, dce.fInPosition.asShaderVar(),
+                              dce.localMatrix(), &fLocalMatrixUniform);
+    }
 
     // transforms all points so that we can compare them to our test circle
     fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);",
@@ -951,7 +952,8 @@
         pdman.set4fv(fColorUniform, 1, dce.color().vec());
         fColor = dce.color();
     }
-    this->setTransformDataHelper(dce.localMatrix(), pdman, transformRange);
+    this->setTransformDataHelper(pdman, transformRange);
+    this->setTransform(pdman, fLocalMatrixUniform, dce.localMatrix(), &fLocalMatrix);
 }
 
 void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
@@ -959,8 +961,9 @@
                                    GrProcessorKeyBuilder* b) {
     const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>();
     uint32_t key = 0;
-    key |= dce.usesLocalCoords() && dce.localMatrix().hasPerspective() ? 0x1 : 0x0;
+    key |= dce.usesLocalCoords() ? 0x1 : 0x0;
     key |= static_cast<uint32_t>(dce.aaMode()) << 1;
+    key |= ComputeMatrixKey(dce.localMatrix()) << 3;
     b->add32(key);
 }
 
@@ -1086,6 +1089,10 @@
 private:
     SkPMColor4f   fColor;
     UniformHandle fColorUniform;
+
+    SkMatrix      fLocalMatrix;
+    UniformHandle fLocalMatrixUniform;
+
     typedef GrGLSLGeometryProcessor INHERITED;
 };
 
@@ -1118,14 +1125,10 @@
 
     // Setup position
     this->writeOutputPosition(vertBuilder, gpArgs, de.fInPosition.name());
-
-    // emit transforms
-    this->emitTransforms(vertBuilder,
-                         varyingHandler,
-                         uniformHandler,
-                         de.fInPosition.asShaderVar(),
-                         de.localMatrix(),
-                         args.fFPCoordTransformHandler);
+    if (de.usesLocalCoords()) {
+        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, de.fInPosition.asShaderVar(),
+                              de.localMatrix(), &fLocalMatrixUniform);
+    }
 
     // transforms all points so that we can compare them to our test rect
     fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);",
@@ -1178,7 +1181,8 @@
         pdman.set4fv(fColorUniform, 1, de.color().vec());
         fColor = de.color();
     }
-    this->setTransformDataHelper(de.localMatrix(), pdman, transformRange);
+    this->setTransformDataHelper(pdman, transformRange);
+    this->setTransform(pdman, fLocalMatrixUniform, de.localMatrix(), &fLocalMatrix);
 }
 
 void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,
@@ -1186,8 +1190,9 @@
                                  GrProcessorKeyBuilder* b) {
     const DashingLineEffect& de = gp.cast<DashingLineEffect>();
     uint32_t key = 0;
-    key |= de.usesLocalCoords() && de.localMatrix().hasPerspective() ? 0x1 : 0x0;
-    key |= static_cast<int>(de.aaMode()) << 8;
+    key |= de.usesLocalCoords() ? 0x1 : 0x0;
+    key |= static_cast<int>(de.aaMode()) << 1;
+    key |= ComputeMatrixKey(de.localMatrix()) << 3;
     b->add32(key);
 }
 
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index d538805..111cc7e 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -185,12 +185,7 @@
             // emit transforms using either explicit local coords or positions
             const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr()
                                                                           : gp.positionAttr();
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 coordsAttr.asShaderVar(),
-                                 SkMatrix::I(),
-                                 args.fFPCoordTransformHandler);
+            gpArgs->fLocalCoordVar = coordsAttr.asShaderVar();
 
             // Add varyings and globals for all custom attributes
             using Usage = SkVertices::Attribute::Usage;
@@ -306,7 +301,7 @@
             const VerticesGP& vgp = gp.cast<VerticesGP>();
             uint32_t key = 0;
             key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
-            key |= ComputePosKey(vgp.viewMatrix()) << 20;
+            key |= ComputeMatrixKey(vgp.viewMatrix()) << 20;
             b->add32(key);
             b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get()));
 
@@ -323,19 +318,14 @@
                      const CoordTransformRange& transformRange) override {
             const VerticesGP& vgp = gp.cast<VerticesGP>();
 
-            if (!vgp.viewMatrix().isIdentity() &&
-                !SkMatrixPriv::CheapEqual(fViewMatrix, vgp.viewMatrix())) {
-                fViewMatrix = vgp.viewMatrix();
-                pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
-            }
+            this->setTransform(pdman, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);
+            this->setTransformDataHelper(pdman, transformRange);
 
             if (!vgp.colorAttr().isInitialized() && vgp.color() != fColor) {
                 pdman.set4fv(fColorUniform, 1, vgp.color().vec());
                 fColor = vgp.color();
             }
 
-            this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
-
             fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get());
 
             for (const auto& matrixUni : fCustomMatrixUniforms) {
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index 76122e5..630955f 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -680,15 +680,13 @@
         v->codeAppend("float2 aa_outset = aa_bloat_direction.xy * aa_bloatradius;");
         v->codeAppend("float2 vertexpos = corner + radius_outset * radii + aa_outset;");
 
-        // Emit transforms.
+        // Write positions
         GrShaderVar localCoord("", kFloat2_GrSLType);
         if (proc.fFlags & ProcessorFlags::kHasLocalCoords) {
             v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
                                                "local_rect.zw * (1 + vertexpos)) * .5;");
-            localCoord.set(kFloat2_GrSLType, "localcoord");
+            gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
         }
-        this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
-                             args.fFPCoordTransformHandler);
 
         // Transform to device space.
         SkASSERT(!(proc.fFlags & ProcessorFlags::kHasPerspective));
@@ -743,7 +741,7 @@
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
                  const CoordTransformRange& transformRange) override {
-        this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+        this->setTransformDataHelper(pdman, transformRange);
     }
 };
 
@@ -781,15 +779,13 @@
         // [-1,-1,+1,+1] space.
         v->codeAppend("float2 vertexpos = corner + radius_outset * radii;");
 
-        // Emit transforms.
+        // Write positions
         GrShaderVar localCoord("", kFloat2_GrSLType);
         if (hasLocalCoords) {
             v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
                                                "local_rect.zw * (1 + vertexpos)) * .5;");
-            localCoord.set(kFloat2_GrSLType, "localcoord");
+            gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
         }
-        this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
-                             args.fFPCoordTransformHandler);
 
         // Transform to device space.
         if (!hasPerspective) {
@@ -849,7 +845,7 @@
 
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
                  const CoordTransformRange& transformRange) override {
-        this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+        this->setTransformDataHelper(pdman, transformRange);
     }
 };
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 7efe3a3..fe9983f 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -49,7 +49,7 @@
             void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
                          const CoordTransformRange& transformRange) override {
                 const auto& latticeGP = proc.cast<LatticeGP>();
-                this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+                this->setTransformDataHelper(pdman, transformRange);
                 fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get());
             }
 
@@ -62,11 +62,8 @@
 
                 args.fVaryingHandler->emitAttributes(latticeGP);
                 this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name());
-                this->emitTransforms(args.fVertBuilder,
-                                     args.fVaryingHandler,
-                                     args.fUniformHandler,
-                                     latticeGP.fInTextureCoords.asShaderVar(),
-                                     args.fFPCoordTransformHandler);
+                gpArgs->fLocalCoordVar = latticeGP.fInTextureCoords.asShaderVar();
+
                 args.fFragBuilder->codeAppend("float2 textureCoords;");
                 args.fVaryingHandler->addPassThroughAttribute(latticeGP.fInTextureCoords,
                                                               "textureCoords");
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index d857557..f720f63 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -155,14 +155,9 @@
 
             // Setup position
             this->writeOutputPosition(vertBuilder, gpArgs, cgp.fInPosition.name());
-
-            // emit transforms
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 cgp.fInPosition.asShaderVar(),
-                                 cgp.fLocalMatrix,
-                                 args.fFPCoordTransformHandler);
+            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+                                  cgp.fInPosition.asShaderVar(), cgp.fLocalMatrix,
+                                  &fLocalMatrixUniform);
 
             fragBuilder->codeAppend("float d = length(circleEdge.xy);");
             fragBuilder->codeAppend("half distanceToOuterEdge = half(circleEdge.z * (1.0 - d));");
@@ -210,24 +205,29 @@
                            const GrShaderCaps&,
                            GrProcessorKeyBuilder* b) {
             const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor>();
-            uint16_t key;
+            uint32_t key;
             key = cgp.fStroke ? 0x01 : 0x0;
-            key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0;
-            key |= cgp.fInClipPlane.isInitialized() ? 0x04 : 0x0;
-            key |= cgp.fInIsectPlane.isInitialized() ? 0x08 : 0x0;
-            key |= cgp.fInUnionPlane.isInitialized() ? 0x10 : 0x0;
-            key |= cgp.fInRoundCapCenters.isInitialized() ? 0x20 : 0x0;
+            key |= cgp.fInClipPlane.isInitialized() ? 0x02 : 0x0;
+            key |= cgp.fInIsectPlane.isInitialized() ? 0x04 : 0x0;
+            key |= cgp.fInUnionPlane.isInitialized() ? 0x08 : 0x0;
+            key |= cgp.fInRoundCapCenters.isInitialized() ? 0x10 : 0x0;
+            key |= (ComputeMatrixKey(cgp.fLocalMatrix) << 16);
             b->add32(key);
         }
 
         void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
                      const CoordTransformRange& transformRange) override {
-            this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>().fLocalMatrix,
-                                         pdman, transformRange);
+            this->setTransformDataHelper(pdman, transformRange);
+            this->setTransform(pdman, fLocalMatrixUniform,
+                               primProc.cast<CircleGeometryProcessor>().fLocalMatrix,
+                               &fLocalMatrix);
         }
 
     private:
         typedef GrGLSLGeometryProcessor INHERITED;
+
+        SkMatrix      fLocalMatrix = SkMatrix::InvalidMatrix();
+        UniformHandle fLocalMatrixUniform;
     };
 
     SkMatrix fLocalMatrix;
@@ -389,14 +389,10 @@
 
             // Setup position
             this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition.name());
+            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+                                  bcscgp.fInPosition.asShaderVar(), bcscgp.fLocalMatrix,
+                                  &fLocalMatrixUniform);
 
-            // emit transforms
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 bcscgp.fInPosition.asShaderVar(),
-                                 bcscgp.fLocalMatrix,
-                                 args.fFPCoordTransformHandler);
             GrShaderVar fnArgs[] = {
                     GrShaderVar("angleToEdge", kFloat_GrSLType),
                     GrShaderVar("diameter", kFloat_GrSLType),
@@ -477,18 +473,22 @@
                            GrProcessorKeyBuilder* b) {
             const ButtCapDashedCircleGeometryProcessor& bcscgp =
                     gp.cast<ButtCapDashedCircleGeometryProcessor>();
-            b->add32(bcscgp.fLocalMatrix.hasPerspective());
+            b->add32(ComputeMatrixKey(bcscgp.fLocalMatrix));
         }
 
         void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
                      const CoordTransformRange& transformRange) override {
-            this->setTransformDataHelper(
-                    primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix, pdman,
-                    transformRange);
+            this->setTransformDataHelper(pdman, transformRange);
+            this->setTransform(pdman, fLocalMatrixUniform,
+                               primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix,
+                               &fLocalMatrix);
         }
 
     private:
         typedef GrGLSLGeometryProcessor INHERITED;
+
+        SkMatrix      fLocalMatrix = SkMatrix::InvalidMatrix();
+        UniformHandle fLocalMatrixUniform;
     };
 
     SkMatrix fLocalMatrix;
@@ -588,14 +588,10 @@
 
             // Setup position
             this->writeOutputPosition(vertBuilder, gpArgs, egp.fInPosition.name());
+            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+                                  egp.fInPosition.asShaderVar(), egp.fLocalMatrix,
+                                  &fLocalMatrixUniform);
 
-            // emit transforms
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 egp.fInPosition.asShaderVar(),
-                                 egp.fLocalMatrix,
-                                 args.fFPCoordTransformHandler);
             // For stroked ellipses, we use the full ellipse equation (x^2/a^2 + y^2/b^2 = 1)
             // to compute both the edges because we need two separate test equations for
             // the single offset.
@@ -666,19 +662,23 @@
                            const GrShaderCaps&,
                            GrProcessorKeyBuilder* b) {
             const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcessor>();
-            uint16_t key = egp.fStroke ? 0x1 : 0x0;
-            key |= egp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0;
+            uint32_t key = egp.fStroke ? 0x1 : 0x0;
+            key |= ComputeMatrixKey(egp.fLocalMatrix) << 1;
             b->add32(key);
         }
 
         void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
                      const CoordTransformRange& transformRange) override {
             const EllipseGeometryProcessor& egp = primProc.cast<EllipseGeometryProcessor>();
-            this->setTransformDataHelper(egp.fLocalMatrix, pdman, transformRange);
+            this->setTransformDataHelper(pdman, transformRange);
+            this->setTransform(pdman, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix);
         }
 
     private:
         typedef GrGLSLGeometryProcessor INHERITED;
+
+        SkMatrix      fLocalMatrix = SkMatrix::InvalidMatrix();
+        UniformHandle fLocalMatrixUniform;
     };
 
     Attribute fInPosition;
@@ -791,13 +791,7 @@
                                       diegp.fInPosition.name(),
                                       diegp.fViewMatrix,
                                       &fViewMatrixUniform);
-
-            // emit transforms
-            this->emitTransforms(vertBuilder,
-                                 varyingHandler,
-                                 uniformHandler,
-                                 diegp.fInPosition.asShaderVar(),
-                                 args.fFPCoordTransformHandler);
+            gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar();
 
             // for outer curve
             fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn());
@@ -862,8 +856,8 @@
                            const GrShaderCaps&,
                            GrProcessorKeyBuilder* b) {
             const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
-            uint16_t key = static_cast<uint16_t>(diegp.fStyle);
-            key |= ComputePosKey(diegp.fViewMatrix) << 10;
+            uint32_t key = static_cast<uint32_t>(diegp.fStyle);
+            key |= ComputeMatrixKey(diegp.fViewMatrix) << 10;
             b->add32(key);
         }
 
@@ -871,17 +865,12 @@
                      const CoordTransformRange& transformRange) override {
             const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
 
-            if (!diegp.fViewMatrix.isIdentity() &&
-                !SkMatrixPriv::CheapEqual(fViewMatrix, diegp.fViewMatrix))
-            {
-                fViewMatrix = diegp.fViewMatrix;
-                pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
-            }
-            this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+            this->setTransform(pdman, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
+            this->setTransformDataHelper(pdman, transformRange);
         }
 
     private:
-        SkMatrix fViewMatrix;
+        SkMatrix      fViewMatrix;
         UniformHandle fViewMatrixUniform;
 
         typedef GrGLSLGeometryProcessor INHERITED;
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index bc5de24..ca420dd 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -571,7 +571,7 @@
             void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
                          const CoordTransformRange& transformRange) override {
                 const auto& gp = proc.cast<QuadPerEdgeAAGeometryProcessor>();
-                this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+                this->setTransformDataHelper(pdman, transformRange);
                 fTextureColorSpaceXformHelper.setData(pdman, gp.fTextureColorSpaceXform.get());
             }
 
@@ -604,18 +604,10 @@
                     gpArgs->fPositionVar = gp.fPosition.asShaderVar();
                 }
 
-                // Handle local coordinates if they exist. This is required even when the op
-                // isn't providing local coords but there are FPs called with explicit coords.
-                // It installs the uniforms that transform their coordinates in the fragment
-                // shader.
-                // NOTE: If the only usage of local coordinates is for the inline texture fetch
-                // before FPs, then there are no registered FPCoordTransforms and this ends up
-                // emitting nothing, so there isn't a duplication of local coordinates
-                this->emitTransforms(args.fVertBuilder,
-                                     args.fVaryingHandler,
-                                     args.fUniformHandler,
-                                     gp.fLocalCoord.asShaderVar(),
-                                     args.fFPCoordTransformHandler);
+                // This attribute will be uninitialized if earlier FP analysis determined no
+                // local coordinates are needed (and this will not include the inline texture
+                // fetch this GP does before invoking FPs).
+                gpArgs->fLocalCoordVar = gp.fLocalCoord.asShaderVar();
 
                 // Solid color before any texturing gets modulated in
                 if (gp.fColor.isInitialized()) {