From 9d82f9e4b8c33b429b1c8a5b2a1d5e9636faad93 Mon Sep 17 00:00:00 2001 From: Michael Ludwig Date: Wed, 29 Jun 2022 14:43:59 -0400 Subject: [PATCH] [graphite] Add more utility and SkM44/SkMatrix interop to Transform class Change-Id: I028bd133778d14edcb22ccef0c35c5a8e3d7d552 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/554516 Reviewed-by: Jim Van Verth Commit-Queue: Michael Ludwig Reviewed-by: Brian Salomon --- include/core/SkM44.h | 1 + src/gpu/graphite/geom/Transform.cpp | 55 ++++++++++++++++++++++ src/gpu/graphite/geom/Transform_graphite.h | 18 +++++++ 3 files changed, 74 insertions(+) diff --git a/include/core/SkM44.h b/include/core/SkM44.h index ae08b4400c..7fdbcb8e82 100644 --- a/include/core/SkM44.h +++ b/include/core/SkM44.h @@ -30,6 +30,7 @@ struct SK_API SkV2 { friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; } friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; } friend SkV2 operator/(SkV2 v, SkScalar s) { return {v.x/s, v.y/s}; } + friend SkV2 operator/(SkScalar s, SkV2 v) { return {s/v.x, s/v.y}; } void operator+=(SkV2 v) { *this = *this + v; } void operator-=(SkV2 v) { *this = *this - v; } diff --git a/src/gpu/graphite/geom/Transform.cpp b/src/gpu/graphite/geom/Transform.cpp index ac688ba353..6c5de8a059 100644 --- a/src/gpu/graphite/geom/Transform.cpp +++ b/src/gpu/graphite/geom/Transform.cpp @@ -93,6 +93,15 @@ Transform::Transform(const SkM44& m) : fM(m) { fType = get_matrix_info(m, &fInvM, &fScale); } +const Transform& Transform::Identity() { + static const Transform kIdentity{SkM44()}; + return kIdentity; +} +const Transform& Transform::Invalid() { + static const Transform kInvalid{SkM44(SkM44::kNaN_Constructor)}; + return kInvalid; +} + bool Transform::operator==(const Transform& t) const { // Checking fM should be sufficient as all other values are computed from it. SkASSERT(fM != t.fM || (fInvM == t.fInvM && fType == t.fType && fScale == t.fScale)); @@ -131,4 +140,50 @@ void Transform::inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count return map_points(fInvM, deviceIn, localOut, count); } +Transform Transform::preTranslate(float x, float y) const { + Transform t = *this; + t.fM.preTranslate(x, y); + t.fInvM.postTranslate(-x, -y); + + // Under normal conditions, type and scale won't change, but if we've overflown the translation + // components, mark the matrix as invalid. + if (!t.fM.isFinite() || !t.fInvM.isFinite()) { + t.fType = Type::kInvalid; + } + return t; +} + +Transform Transform::postTranslate(float x, float y) const { + Transform t = *this; + t.fM.postTranslate(x, y); + t.fInvM.preTranslate(-x, -y); + if (!t.fM.isFinite() || !t.fInvM.isFinite()) { + t.fType = Type::kInvalid; + } + return t; +} + +Transform Transform::concat(const Transform& t) const { + Transform c = {fM * t.fM, t.fInvM * fInvM, std::max(fType, t.fType), {fScale * t.fScale}}; + if (!c.fM.isFinite() || !c.fInvM.isFinite()) { + c.fType = Type::kInvalid; + } + return c; +} + +Transform Transform::concatInverse(const Transform& t) const { + Transform c = {fM * t.fInvM, t.fM * fInvM, std::max(fType, t.fType), {fScale * (1.f/t.fScale)}}; + if (!c.fM.isFinite() || !c.fInvM.isFinite()) { + c.fType = Type::kInvalid; + } + return c; +} + +Transform Transform::concatInverse(const SkM44& t) const { + // saves a multiply compared to inverting just t and then computing fM*t^-1 and t*fInvM, if we + // instead start with (t*fInvM) and swap definition of computed fM and fInvM. + Transform inverse{t * fInvM}; + return {inverse.fInvM, inverse.fM, inverse.fType, 1.f / inverse.fScale}; +} + } // namespace skgpu::graphite diff --git a/src/gpu/graphite/geom/Transform_graphite.h b/src/gpu/graphite/geom/Transform_graphite.h index dc1dddea4c..790131f0f2 100644 --- a/src/gpu/graphite/geom/Transform_graphite.h +++ b/src/gpu/graphite/geom/Transform_graphite.h @@ -44,6 +44,9 @@ public: explicit Transform(const SkM44& m); Transform(const Transform& t) = default; + static const Transform& Identity(); + static const Transform& Invalid(); + Transform& operator=(const Transform& t) = default; operator const SkM44&() const { return fM; } @@ -70,7 +73,22 @@ public: void mapPoints(const SkV4* localIn, SkV4* deviceOut, int count) const; void inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count) const; + // Returns a transform equal to the pre- or post-translating this matrix + Transform preTranslate(float x, float y) const; + Transform postTranslate(float x, float y) const; + + // Returns a transform equal to (this * t) + Transform concat(const Transform& t) const; + Transform concat(const SkM44& t) const { return Transform(fM * t); } + + // Returns a transform equal to (this * t^-1) + Transform concatInverse(const Transform& t) const; + Transform concatInverse(const SkM44& t) const; + private: + Transform(const SkM44& m, const SkM44& invM, Type type, const SkV2 scale) + : fM(m), fInvM(invM), fType(type), fScale(scale) {} + SkM44 fM; SkM44 fInvM; // M^-1 Type fType;