Add sample(child, matrix) to SkSL.

This allows fragment processors to sample their children with their
local coordinate system transformed by a matrix.

Change-Id: Ifa848bbd85b939bbc5751fec5cf8f89ee904bf39
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/282590
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index 142f3c7..5cfb986 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -8,6 +8,7 @@
 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
 
 #include "src/gpu/GrCoordTransform.h"
+#include "src/gpu/GrPipeline.h"
 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
 #include "src/gpu/glsl/GrGLSLVarying.h"
@@ -84,7 +85,7 @@
     for (int i = 0; *handler; ++*handler, ++i) {
         auto [coordTransform, fp] = handler->get();
         // Add uniform for coord transform matrix.
-        const char* matrixName;
+        SkString matrix;
         if (!fp.isSampledWithExplicitCoords() || !coordTransform.isNoOp()) {
             SkString strUniName;
             strUniName.printf("CoordTransformMatrix_%d", i);
@@ -96,9 +97,11 @@
             } else {
                 uni.fType = kFloat3x3_GrSLType;
             }
+            const char* matrixName;
             uni.fHandle =
                     uniformHandler->addUniform(&fp, flag, uni.fType, strUniName.c_str(),
                                                &matrixName);
+            matrix = matrixName;
             transformVar = uniformHandler->getUniformVariable(uni.fHandle);
         } else {
             // Install a coord transform that will be skipped.
@@ -122,14 +125,45 @@
 
             SkASSERT(fInstalledTransforms.back().fType == kFloat3x3_GrSLType);
             if (v.type() == kFloat2_GrSLType) {
-                vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), matrixName,
+                vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), matrix.c_str(),
                                 localCoordsStr.c_str());
             } else {
-                vb->codeAppendf("%s = %s * %s;", v.vsOut(), matrixName, localCoordsStr.c_str());
+                vb->codeAppendf("%s = %s * %s;", v.vsOut(), matrix.c_str(), localCoordsStr.c_str());
             }
             fsVar = GrShaderVar(SkString(v.fsIn()), v.type(), GrShaderVar::TypeModifier::In);
+            fTransformInfos.push_back({ v.vsOut(), v.type(), matrix.c_str(), localCoordsStr, &fp });
+        } else {
+            SkASSERT(fp.sampleMatrix().fKind != SkSL::SampleMatrix::Kind::kVariable);
+            if (fp.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
+                matrix += " * " + fp.sampleMatrix().fExpression;
+            }
         }
-        handler->specifyCoordsForCurrCoordTransform(transformVar, fsVar);
+        handler->specifyCoordsForCurrCoordTransform(matrix, transformVar, fsVar);
+    }
+}
+
+void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb,
+                                                GrGLSLUniformHandler* uniformHandler) {
+    for (const auto& tr : fTransformInfos) {
+        switch (tr.fFP->sampleMatrix().fKind) {
+            case SkSL::SampleMatrix::Kind::kConstantOrUniform:
+                vb->codeAppend("{\n");
+                uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb);
+                if (tr.fType == kFloat2_GrSLType) {
+                    vb->codeAppendf("%s = (%s * %s * %s).xy", tr.fName,
+                                    tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix,
+                                    tr.fLocalCoords.c_str());
+                } else {
+                    SkASSERT(tr.fType == kFloat3_GrSLType);
+                    vb->codeAppendf("%s = %s * %s * %s", tr.fName,
+                                    tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix,
+                                    tr.fName);
+                }
+                vb->codeAppend(";\n");
+                vb->codeAppend("}\n");
+            default:
+                break;
+        }
     }
 }