Fixed sample_matrix_constant GM

This GM was not actually doing what the name implied, and when
switched over to use a constant matrix, turned out to not work.

This fixes it so constant matrices properly affect child processors.

Change-Id: I1f6b271dbf43c18515c0c72701bf8bbf60eb4c59
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293716
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gm/sample_matrix_constant.cpp b/gm/sample_matrix_constant.cpp
index e369230..bf9aecc 100644
--- a/gm/sample_matrix_constant.cpp
+++ b/gm/sample_matrix_constant.cpp
@@ -21,7 +21,8 @@
 
     SampleMatrixConstantEffect(std::unique_ptr<GrFragmentProcessor> child)
             : INHERITED(CLASS_ID, kNone_OptimizationFlags) {
-        child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kVariable));
+        child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kConstantOrUniform,
+                                                  child.get(), "float3x3(0.5)"));
         this->registerChildProcessor(std::move(child));
     }
 
@@ -43,7 +44,7 @@
 class GLSLSampleMatrixConstantEffect : public GrGLSLFragmentProcessor {
     void emitCode(EmitArgs& args) override {
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-        SkString sample = this->invokeChildWithMatrix(0, args, "float3x3(0.5)");
+        SkString sample = this->invokeChild(0, args);
         fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, sample.c_str());
     }
 };
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index e4b18c8..5b66339 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -74,25 +74,35 @@
     fFlags |= kHasCoordTransforms_Flag;
 }
 
-void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix matrix) {
-    if (matrix == fMatrix) {
+void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix newMatrix) {
+    if (newMatrix == fMatrix) {
         return;
     }
+    SkASSERT(newMatrix.fKind != SkSL::SampleMatrix::Kind::kNone);
     SkASSERT(fMatrix.fKind != SkSL::SampleMatrix::Kind::kVariable);
+    if (this->numCoordTransforms() == 0 &&
+        (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform ||
+         newMatrix.fKind == SkSL::SampleMatrix::Kind::kMixed)) {
+        // as things stand, matrices only work when there's a coord transform, so we need to add
+        // an identity transform to keep the downstream code happy
+        static GrCoordTransform identity;
+        this->addCoordTransform(&identity);
+    }
     if (fMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
-        SkASSERT(matrix.fKind == SkSL::SampleMatrix::Kind::kVariable ||
-                 (matrix.fKind == SkSL::SampleMatrix::Kind::kMixed &&
-                  matrix.fExpression == fMatrix.fExpression));
-        fMatrix = SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kMixed, fMatrix.fOwner,
-                                     fMatrix.fExpression);
+        if (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
+            // need to base this transform on the one that happened in our parent
+            fMatrix.fBase = newMatrix.fOwner;
+        } else {
+            SkASSERT(newMatrix.fKind == SkSL::SampleMatrix::Kind::kVariable);
+            fMatrix = SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kMixed, fMatrix.fOwner,
+                                         fMatrix.fExpression);
+        }
     } else {
         SkASSERT(fMatrix.fKind == SkSL::SampleMatrix::Kind::kNone);
-        fMatrix = matrix;
+        fMatrix = newMatrix;
     }
-    if (matrix.fKind == SkSL::SampleMatrix::Kind::kVariable) {
-        for (auto& child : fChildProcessors) {
-            child->setSampleMatrix(matrix);
-        }
+    for (auto& child : fChildProcessors) {
+        child->setSampleMatrix(newMatrix);
     }
 }
 
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index 3ef36d4..d4eb2af 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -14,6 +14,8 @@
 #include "src/gpu/glsl/GrGLSLVarying.h"
 #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
 
+#include <unordered_map>
+
 void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
     GrGPArgs gpArgs;
     this->onEmitCode(args, &gpArgs);
@@ -142,23 +144,34 @@
 
 void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb,
                                                 GrGLSLUniformHandler* uniformHandler) {
+    std::unordered_map<const GrFragmentProcessor*, const char*> localCoordsMap;
     for (const auto& tr : fTransformInfos) {
         switch (tr.fFP->sampleMatrix().fKind) {
-            case SkSL::SampleMatrix::Kind::kConstantOrUniform:
+            case SkSL::SampleMatrix::Kind::kConstantOrUniform: {
+                SkString localCoords;
+                localCoordsMap.insert({ tr.fFP, tr.fName });
+                if (tr.fFP->sampleMatrix().fBase) {
+                    SkASSERT(localCoordsMap[tr.fFP->sampleMatrix().fBase]);
+                    localCoords = SkStringPrintf("float3(%s, 1)",
+                                                 localCoordsMap[tr.fFP->sampleMatrix().fBase]);
+                } else {
+                    localCoords = tr.fLocalCoords.c_str();
+                }
                 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.c_str(),
-                                    tr.fLocalCoords.c_str());
+                                    localCoords.c_str());
                 } else {
                     SkASSERT(tr.fType == kFloat3_GrSLType);
                     vb->codeAppendf("%s = %s * %s * %s", tr.fName,
                                     tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix.c_str(),
-                                    tr.fLocalCoords.c_str());
+                                    localCoords.c_str());
                 }
                 vb->codeAppend(";\n");
                 vb->codeAppend("}\n");
+            }
             default:
                 break;
         }
diff --git a/src/sksl/SkSLSampleMatrix.h b/src/sksl/SkSLSampleMatrix.h
index 7f121b0..d41141b 100644
--- a/src/sksl/SkSLSampleMatrix.h
+++ b/src/sksl/SkSLSampleMatrix.h
@@ -77,6 +77,7 @@
     // The constant or uniform expression representing the matrix (will be the empty string when
     // kind == kNone or kVariable)
     String fExpression;
+    const GrFragmentProcessor* fBase = nullptr;
 };
 
 } // namespace