[graphite] Actually detect Transform type and scale factors
Bug: skia:12787 Change-Id: I5d061d535878df55ce57add7d0831e86caadc321 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/524009 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
371b3a68b2
commit
91b5f668e8
@ -437,7 +437,7 @@ void Device::recordDraw(const Transform& localToDevice,
|
||||
}
|
||||
// TODO: The tessellating path renderers haven't implemented perspective yet, so transform to
|
||||
// device space so we draw something approximately correct (barring local coord issues).
|
||||
if (localToDevice.type() == Transform::Type::kPerspective) {
|
||||
if (localToDevice.type() == Transform::Type::kProjection) {
|
||||
SkPath devicePath = shape.asPath();
|
||||
devicePath.transform(localToDevice.matrix().asM33());
|
||||
this->recordDraw(kIdentity, Shape(devicePath), clip, ordering, paint, nullptr);
|
||||
|
@ -22,19 +22,63 @@ Rect map_rect(const SkM44& m, const Rect& r) {
|
||||
return SkMatrixPriv::MapRect(m, r.asSkRect());
|
||||
}
|
||||
|
||||
Transform::Type get_matrix_info(const SkM44& m, SkM44* inverse, SkV2* scale) {
|
||||
// First compute the inverse.
|
||||
// TODO: Alternatively we could compute type first and have type-specific inverses, but it seems
|
||||
// useful to ensure any non-invalid matrix returns true from SkM44::invert.
|
||||
if (!m.invert(inverse)) {
|
||||
*scale = {1.f, 1.f};
|
||||
return Transform::Type::kInvalid;
|
||||
}
|
||||
|
||||
static constexpr SkV4 kNoPerspective = {0.f, 0.f, 0.f, 1.f};
|
||||
static constexpr SkV4 kNoZ = {0.f, 0.f, 1.f, 0.f};
|
||||
if (m.row(3) != kNoPerspective || m.col(2) != kNoZ || m.row(2) != kNoZ) {
|
||||
// TODO: Use SkMatrixPriv::DifferentialAreaScale, but we need a representative point then.
|
||||
// Or something like lengths of upper 2x2 divided by w?
|
||||
*scale = {1.f, 1.f};
|
||||
return Transform::Type::kProjection;
|
||||
}
|
||||
|
||||
// [sx kx 0 tx]
|
||||
// At this point, we know that m is of the form [ky sy 0 ty]
|
||||
// [0 0 1 0 ]
|
||||
// [0 0 0 1 ]
|
||||
// Other than kIdentity, none of the types depend on (tx, ty). The remaining types are
|
||||
// identified by considering the upper 2x2.
|
||||
float sx = m.rc(0, 0);
|
||||
float sy = m.rc(1, 1);
|
||||
float kx = m.rc(0, 1);
|
||||
float ky = m.rc(1, 0);
|
||||
if (kx == 0.f && ky == 0.f) {
|
||||
// 2x2 is a diagonal matrix
|
||||
*scale = {std::abs(sx), std::abs(sy)};
|
||||
if (sx == 1.f && sy == 1.f && m.rc(0, 3) == 0.f && m.rc(1, 3) == 0.f) {
|
||||
return Transform::Type::kIdentity;
|
||||
} else if (sx > 0.f && sy > 0.f) {
|
||||
return Transform::Type::kSimpleRectStaysRect;
|
||||
} else {
|
||||
// We don't need to worry about sx or sy being 0 here because that would imply the
|
||||
// matrix wasn't invertible and that was already tested.
|
||||
SkASSERT(sx != 0.f && sy != 0.f);
|
||||
return Transform::Type::kRectStaysRect;
|
||||
}
|
||||
} else if (sx == 0.f && sy == 0.f) {
|
||||
// 2x2 is an anti-diagonal matrix and represents a 90 or 270 degree rotation plus optional
|
||||
// scale and translate. Similar to before, kx and ky can't be 0 or m wouldn't be invertible.
|
||||
SkASSERT(kx != 0.f && ky != 0.f);
|
||||
*scale = {std::abs(ky), std::abs(kx)};
|
||||
return Transform::Type::kRectStaysRect;
|
||||
} else {
|
||||
*scale = {SkV2{sx, ky}.length(), SkV2{kx, sy}.length()};
|
||||
return Transform::Type::kAffine;
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Transform::Transform(const SkM44& m)
|
||||
: fM(m) {
|
||||
if (fM.invert(&fInvM)) {
|
||||
// TODO: actually detect these
|
||||
fType = (fM == SkM44()) ? Type::kIdentity : Type::kPerspective;
|
||||
fScale = {1.f, 1.f};
|
||||
} else {
|
||||
fType = Type::kInvalid;
|
||||
fInvM = SkM44();
|
||||
fScale = {1.f, 1.f};
|
||||
}
|
||||
Transform::Transform(const SkM44& m) : fM(m) {
|
||||
fType = get_matrix_info(m, &fInvM, &fScale);
|
||||
}
|
||||
|
||||
bool Transform::operator==(const Transform& t) const {
|
||||
|
@ -33,9 +33,10 @@ public:
|
||||
// The matrix transform may have skew or rotation, so a mapped rect does not fill space,
|
||||
// but there is no need to perform perspective division or w-plane clipping.
|
||||
kAffine,
|
||||
// The matrix includes perspective, so care must be taken when w is less than or near 0,
|
||||
// and perspective division and interpolation are needed for correct rendering.
|
||||
kPerspective,
|
||||
// The matrix includes perspective or modifies Z and requires further projection to 2D,
|
||||
// so care must be taken when w is less than or near 0, and homogeneous division and
|
||||
// perspective-correct interpolation are needed when rendering.
|
||||
kProjection,
|
||||
// The matrix is not invertible or not finite, so should not be used to draw.
|
||||
kInvalid,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user