Simplify wangs_formula::VectorXform

Adds a SkM44 constructor as well as the existing SkMatrix one.

Only stores the 2x2 matrix as columns instead of caching the swizzles
that might be used. Removes the matrix-type specific branching.

I didn't see any performance difference on motionmark skps on my
machine, so hopefully the bots don't report anything serious and we
can keep the simplification.

Bug: b/238761548, skia:13012
Change-Id: I824283720e722a315859e009d3adf3499c8a80a0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/565337
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/graphite/render/TessellateStrokesRenderStep.cpp b/src/gpu/graphite/render/TessellateStrokesRenderStep.cpp
index edb2fc94..e78f6a1 100644
--- a/src/gpu/graphite/render/TessellateStrokesRenderStep.cpp
+++ b/src/gpu/graphite/render/TessellateStrokesRenderStep.cpp
@@ -105,7 +105,7 @@
     // more accurately compute how many *parametric* segments are needed.
     // getMaxScale() returns -1 if it can't compute a scale factor (e.g. perspective), taking the
     // absolute value automatically converts that to an identity scale factor for our purposes.
-    writer.setShaderTransform(wangs_formula::VectorXform{params.transform()},
+    writer.setShaderTransform(wangs_formula::VectorXform{params.transform().matrix()},
                               params.transform().maxScaleFactor());
 
     SkASSERT(params.isStroke());
diff --git a/src/gpu/tessellate/WangsFormula.h b/src/gpu/tessellate/WangsFormula.h
index 73bdbff..0209f43 100644
--- a/src/gpu/tessellate/WangsFormula.h
+++ b/src/gpu/tessellate/WangsFormula.h
@@ -8,6 +8,7 @@
 #ifndef skgpu_tessellate_WangsFormula_DEFINED
 #define skgpu_tessellate_WangsFormula_DEFINED
 
+#include "include/core/SkM44.h"
 #include "include/core/SkMatrix.h"
 #include "include/core/SkPoint.h"
 #include "include/core/SkString.h"
@@ -63,54 +64,33 @@
 //
 class VectorXform {
 public:
-    AI VectorXform() : fType(Type::kIdentity) {}
+    AI VectorXform() : fC0{1.0f, 0.f}, fC1{0.f, 1.f} {}
     AI explicit VectorXform(const SkMatrix& m) { *this = m; }
+    AI explicit VectorXform(const SkM44& m) { *this = m; }
+
     AI VectorXform& operator=(const SkMatrix& m) {
         SkASSERT(!m.hasPerspective());
-        if (m.getType() & SkMatrix::kAffine_Mask) {
-            fType = Type::kAffine;
-            fScaleXSkewY = {m.getScaleX(), m.getSkewY()};
-            fSkewXScaleY = {m.getSkewX(), m.getScaleY()};
-            fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
-            fSkewXYXY = {m.getSkewX(), m.getSkewY(), m.getSkewX(), m.getSkewY()};
-        } else if (m.getType() & SkMatrix::kScale_Mask) {
-            fType = Type::kScale;
-            fScaleXY = {m.getScaleX(), m.getScaleY()};
-            fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
-        } else {
-            SkASSERT(!(m.getType() & ~SkMatrix::kTranslate_Mask));
-            fType = Type::kIdentity;
-        }
+        fC0 = {m.rc(0,0), m.rc(1,0)};
+        fC1 = {m.rc(0,1), m.rc(1,1)};
+        return *this;
+    }
+    AI VectorXform& operator=(const SkM44& m) {
+        SkASSERT(m.rc(3,0) == 0.f && m.rc(3,1) == 0.f && m.rc(3,2) == 0.f && m.rc(3,3) == 1.f);
+        fC0 = {m.rc(0,0), m.rc(1,0)};
+        fC1 = {m.rc(0,1), m.rc(1,1)};
         return *this;
     }
     AI skvx::float2 operator()(skvx::float2 vector) const {
-        switch (fType) {
-            case Type::kIdentity:
-                return vector;
-            case Type::kScale:
-                return fScaleXY * vector;
-            case Type::kAffine:
-                return fScaleXSkewY * skvx::float2(vector[0]) + fSkewXScaleY * vector[1];
-        }
-        SkUNREACHABLE;
+        return fC0 * vector.x() + fC1 * vector.y();
     }
     AI skvx::float4 operator()(skvx::float4 vectors) const {
-        switch (fType) {
-            case Type::kIdentity:
-                return vectors;
-            case Type::kScale:
-                return vectors * fScaleXYXY;
-            case Type::kAffine:
-                return fScaleXYXY * vectors + fSkewXYXY * vectors.yxwz();
-        }
-        SkUNREACHABLE;
+        return join(fC0 * vectors.x() + fC1 * vectors.y(),
+                    fC0 * vectors.z() + fC1 * vectors.w());
     }
 private:
-    enum class Type { kIdentity, kScale, kAffine } fType;
-    union { skvx::float2 fScaleXY, fScaleXSkewY; };
-    skvx::float2 fSkewXScaleY;
-    skvx::float4 fScaleXYXY;
-    skvx::float4 fSkewXYXY;
+    // First and second columns of 2x2 matrix
+    skvx::float2 fC0;
+    skvx::float2 fC1;
 };
 
 // Returns Wang's formula, raised to the 4th power, specialized for a quadratic curve.