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;