This is a reland of GrDomainEffect with significant changes:

1) It correctly handles GPs that have a local matrix

2) It applies its rectangle after the child FP's coord transform. It makes
the child's transform be a no-op and the builder will no longer insert code
or uniforms for the child transform. The domain effect adds its own coord
transform with the same settings as the child's original transform. The result
is that the generated code only has one coord transform matrix and that matrix
is applies in the vertex shader. The previous version of this effect applied
the transform in the fragment shader.

Bug: skia:9570

Change-Id: I514e959414aebe240e9f99e30f13265d8751b656
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257054
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp
index cf7b56b..270a14c 100644
--- a/src/gpu/GrPrimitiveProcessor.cpp
+++ b/src/gpu/GrPrimitiveProcessor.cpp
@@ -8,13 +8,15 @@
 #include "src/gpu/GrPrimitiveProcessor.h"
 
 #include "src/gpu/GrCoordTransform.h"
+#include "src/gpu/GrFragmentProcessor.h"
 
 /**
  * We specialize the vertex code for each of these matrix types.
  */
 enum MatrixType {
-    kNoPersp_MatrixType  = 0,
-    kGeneral_MatrixType  = 1,
+    kNone_MatrixType     = 0,
+    kNoPersp_MatrixType  = 1,
+    kGeneral_MatrixType  = 2,
 };
 
 GrPrimitiveProcessor::GrPrimitiveProcessor(ClassID classID) : GrProcessor(classID) {}
@@ -24,19 +26,24 @@
     return this->onTextureSampler(i);
 }
 
-uint32_t
-GrPrimitiveProcessor::getTransformKey(const SkTArray<GrCoordTransform*, true>& coords,
-                                      int numCoords) const {
+uint32_t GrPrimitiveProcessor::computeCoordTransformsKey(const GrFragmentProcessor& fp) const {
+    // This is highly coupled with the code in GrGLSLGeometryProcessor::emitTransforms().
+    SkASSERT(fp.numCoordTransforms() * 2 <= 32);
     uint32_t totalKey = 0;
-    for (int t = 0; t < numCoords; ++t) {
+    for (int t = 0; t < fp.numCoordTransforms(); ++t) {
         uint32_t key = 0;
-        const GrCoordTransform* coordTransform = coords[t];
-        if (coordTransform->matrix().hasPerspective()) {
-            key |= kGeneral_MatrixType;
+        const GrCoordTransform& coordTransform = fp.coordTransform(t);
+        if (!fp.coordTransformsApplyToLocalCoords() && coordTransform.isNoOp()) {
+            key = kNone_MatrixType;
+        } else if (coordTransform.matrix().hasPerspective()) {
+            // Note that we can also have homogeneous varyings as a result of a GP local matrix or
+            // homogeneous local coords generated by GP. We're relying on the GP to include any
+            // variability in those in its key.
+            key = kGeneral_MatrixType;
         } else {
-            key |= kNoPersp_MatrixType;
+            key = kNoPersp_MatrixType;
         }
-        key <<= t;
+        key <<= 2*t;
         SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
         totalKey |= key;
     }