[sksg] Add 3x3 Concat Transform specialization

When both inputs are 3x3, use 3x3 Concat.

TBR=
Change-Id: Ife6a98792c2ed57a2a987fe5d0bdf265aeb64b0a
Reviewed-on: https://skia-review.googlesource.com/c/182968
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/sksg/include/SkSGTransform.h b/modules/sksg/include/SkSGTransform.h
index c3ba6c2..9f0fd77 100644
--- a/modules/sksg/include/SkSGTransform.h
+++ b/modules/sksg/include/SkSGTransform.h
@@ -26,6 +26,8 @@
 protected:
     Transform();
 
+    virtual bool is44() const = 0;
+
     virtual SkMatrix   asMatrix  () const = 0;
     virtual SkMatrix44 asMatrix44() const = 0;
 
@@ -49,6 +51,8 @@
 
     SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
 
+    bool is44() const override { return false; }
+
     SkMatrix   asMatrix  () const override;
     SkMatrix44 asMatrix44() const override;
 
@@ -72,6 +76,8 @@
 
     SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
 
+    bool is44() const override { return true; }
+
     SkMatrix   asMatrix  () const override;
     SkMatrix44 asMatrix44() const override;
 
diff --git a/modules/sksg/src/SkSGGeometryTransform.cpp b/modules/sksg/src/SkSGGeometryTransform.cpp
index f338236..2602a46 100644
--- a/modules/sksg/src/SkSGGeometryTransform.cpp
+++ b/modules/sksg/src/SkSGGeometryTransform.cpp
@@ -37,7 +37,7 @@
 
     // We don't care about matrix reval results.
     fTransform->revalidate(ic, ctm);
-    const auto m = TransformPriv::AsMatrix(fTransform);
+    const auto m = TransformPriv::As<SkMatrix>(fTransform);
 
     auto bounds = fChild->revalidate(ic, ctm);
     fTransformedPath = fChild->asPath();
diff --git a/modules/sksg/src/SkSGTransform.cpp b/modules/sksg/src/SkSGTransform.cpp
index e869c3a..c36205d 100644
--- a/modules/sksg/src/SkSGTransform.cpp
+++ b/modules/sksg/src/SkSGTransform.cpp
@@ -14,9 +14,11 @@
 
 namespace {
 
-// Always compose in 4x4 for now.
+template <typename T>
 class Concat final : public Transform {
 public:
+    template <typename = std::enable_if<std::is_same<T, SkMatrix  >::value ||
+                                        std::is_same<T, SkMatrix44>::value >>
     Concat(sk_sp<Transform> a, sk_sp<Transform> b)
         : fA(std::move(a)), fB(std::move(b)) {
         SkASSERT(fA);
@@ -36,11 +38,13 @@
         fA->revalidate(ic, ctm);
         fB->revalidate(ic, ctm);
 
-        fComposed.setConcat(TransformPriv::AsMatrix44(fA),
-                            TransformPriv::AsMatrix44(fB));
+        fComposed.setConcat(TransformPriv::As<T>(fA),
+                            TransformPriv::As<T>(fB));
         return SkRect::MakeEmpty();
     }
 
+    bool is44() const override { return std::is_same<T, SkMatrix44>::value; }
+
     SkMatrix asMatrix() const override {
         return fComposed;
     }
@@ -51,7 +55,7 @@
 
 private:
     const sk_sp<Transform> fA, fB;
-    SkMatrix44             fComposed;
+    T                      fComposed;
 
     using INHERITED = Transform;
 };
@@ -66,8 +70,13 @@
         return b;
     }
 
-    return b ? sk_make_sp<Concat>(std::move(a), std::move(b))
-             : a;
+    if (!b) {
+        return a;
+    }
+
+    return TransformPriv::Is44(a) || TransformPriv::Is44(b)
+        ? sk_sp<Transform>(new Concat<SkMatrix44>(std::move(a), std::move(b)))
+        : sk_sp<Transform>(new Concat<SkMatrix  >(std::move(a), std::move(b)));
 }
 
 sk_sp<Matrix> Matrix::Make(const SkMatrix& m) {
@@ -117,7 +126,7 @@
 }
 
 void TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
-    const auto m = TransformPriv::AsMatrix(fTransform);
+    const auto m = TransformPriv::As<SkMatrix>(fTransform);
     SkAutoCanvasRestore acr(canvas, !m.isIdentity());
     canvas->concat(m);
     this->INHERITED::onRender(canvas, ctx);
@@ -129,7 +138,7 @@
     // We don't care about matrix reval results.
     fTransform->revalidate(ic, ctm);
 
-    const auto m = TransformPriv::AsMatrix(fTransform);
+    const auto m = TransformPriv::As<SkMatrix>(fTransform);
     auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
     m.mapRect(&bounds);
 
diff --git a/modules/sksg/src/SkSGTransformPriv.h b/modules/sksg/src/SkSGTransformPriv.h
index 6582938..20441c1 100644
--- a/modules/sksg/src/SkSGTransformPriv.h
+++ b/modules/sksg/src/SkSGTransformPriv.h
@@ -15,13 +15,27 @@
 // Helper for accessing implementation-private Transform methods.
 class TransformPriv final {
 public:
-    static SkMatrix   AsMatrix  (const sk_sp<Transform>& t) { return t->asMatrix();   }
-    static SkMatrix44 AsMatrix44(const sk_sp<Transform>& t) { return t->asMatrix44(); }
+
+    static bool Is44(const sk_sp<Transform>&t) { return t->is44(); }
+
+    template <typename T, typename = std::enable_if<std::is_same<T, SkMatrix  >::value ||
+                                                    std::is_same<T, SkMatrix44>::value >>
+    static T As(const sk_sp<Transform>&);
 
 private:
     TransformPriv() = delete;
 };
 
+template <>
+inline SkMatrix TransformPriv::As<SkMatrix>(const sk_sp<Transform>& t) {
+    return t->asMatrix();
+}
+
+template <>
+inline SkMatrix44 TransformPriv::As<SkMatrix44>(const sk_sp<Transform>& t) {
+    return t->asMatrix44();
+}
+
 } // namespace sksg
 
 #endif // SkSGTransformPriv_DEFINED