Commit cd3730ac authored by Aaron Krajeski's avatar Aaron Krajeski Committed by Chromium LUCI CQ

Add SkM44 helper functions to cc::MathUtils

Throughout cc callers sometimes need to check if a transformation
matrix preserves axis alignment or is a perspective projection. These
functions already exist on SkMatrix, but we're trying to move away from
SkMatrix towards SkM44. Add the helper functions to cc itself with a
note to maybe add them to Skia if they start getting used outside of cc.

Bug: 1155544
Change-Id: Ieb90af59775b9ec22029e9e941acbb937179c978
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2595831Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Commit-Queue: Aaron Krajeski <aaronhk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838754}
parent 0a08373d
......@@ -868,4 +868,39 @@ bool MathUtil::IsNearlyTheSameForTesting(const gfx::Point3F& left,
return IsNearlyTheSame(left, right);
}
// Equivalent to SkMatrix::HasPerspective
bool MathUtil::SkM44HasPerspective(const SkM44& m) {
return (m.rc(3, 0) != 0 || m.rc(3, 1) != 0 || m.rc(3, 2) != 0 ||
m.rc(3, 3) != 1);
}
// Since some operations assume a 2d transformation, check to make sure that
// is the case by seeing that the z-axis is identity
bool MathUtil::SkM44Is2D(const SkM44& m) {
return (m.rc(0, 2) == 0 && m.rc(1, 2) == 0 && m.rc(2, 2) == 1 &&
m.rc(2, 0) == 0 && m.rc(2, 1) == 0 && m.rc(2, 3) == 0 &&
m.rc(3, 2) == 0);
}
// Equivalent to SkMatrix::PreservesAxisAlignment
// Checks if the transformation is a 90 degree rotation or scaling
// See SkMatrix::computeTypeMask
bool MathUtil::SkM44Preserves2DAxisAlignment(const SkM44& m) {
// Conservatively assume that perspective transforms would not preserve
// axis-alignment
if (!SkM44Is2D(m) || SkM44HasPerspective(m))
return false;
// Does the matrix have skew components
if (m.rc(0, 1) != 0 || m.rc(1, 0) != 0) {
// Rects only map to rects if both skews are non-zero and both scale
// components are zero (i.e. it's a +/-90-degree rotation)
return (m.rc(0, 0) == 0 && m.rc(1, 1) == 0 && m.rc(0, 1) != 0 &&
m.rc(1, 0) != 0);
}
// Since the matrix has no skewing, it maps to a rectangle so long as the
// scale components are non-zero
return (m.rc(0, 0) != 0 && m.rc(1, 1) != 0);
}
} // namespace cc
......@@ -13,6 +13,7 @@
#include "base/numerics/ranges.h"
#include "build/build_config.h"
#include "cc/base/base_export.h"
#include "third_party/skia/include/core/SkM44.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_f.h"
......@@ -325,6 +326,12 @@ class CC_BASE_EXPORT MathUtil {
static bool IsNearlyTheSameForTesting(const gfx::Point3F& l,
const gfx::Point3F& r);
// Helper functions for migration from SkMatrix->SkM44. It may make sense to
// move these to skia itself at some point.
static bool SkM44HasPerspective(const SkM44& m);
static bool SkM44Is2D(const SkM44& m);
static bool SkM44Preserves2DAxisAlignment(const SkM44& m);
private:
template <typename T>
static T RoundUpInternal(T n, T mul) {
......
......@@ -67,14 +67,6 @@ void IterateTextContentByOffsets(const PaintOpBuffer& buffer,
++index;
}
}
bool RotationEquivalentToAxisFlip(const SkMatrix& matrix) {
float skew_x = matrix.getSkewX();
float skew_y = matrix.getSkewY();
return ((skew_x == 1.f || skew_x == -1.f) &&
(skew_y == 1.f || skew_y == -1.f));
}
} // namespace
DisplayItemList::DisplayItemList(UsageHint usage_hint)
......@@ -386,7 +378,7 @@ DisplayItemList::GetDirectlyCompositedImageResult(
// Images that respect orientation will have 5 paint operations:
// (1) Save
// (2) Translate
// (3) Concat (rotation matrix)
// (3) Concat (with a transformation that preserves axis alignment)
// (4) DrawImageRect
// (5) Restore
// Detect these the paint op buffer and disqualify the layer as a directly
......@@ -403,8 +395,8 @@ DisplayItemList::GetDirectlyCompositedImageResult(
break;
}
case PaintOpType::Concat: {
// We only expect a single rotation. If we see another one, then this
// image won't be eligible for directly compositing.
// We only expect a single transformation. If we see another one, then
// this image won't be eligible for directly compositing.
if (transpose_image_size)
return base::nullopt;
......@@ -413,11 +405,27 @@ DisplayItemList::GetDirectlyCompositedImageResult(
!concat_op->matrix.preservesAxisAlignment())
return base::nullopt;
// If the rotation is not an axis flip, we'll need to transpose the
// width and height dimensions to account for the same transform
// applying when the layer bounds were calculated.
transpose_image_size =
RotationEquivalentToAxisFlip(concat_op->matrix);
// If the image has been rotated +/-90 degrees we'll need to transpose
// the width and height dimensions to account for the same transform
// applying when the layer bounds were calculated. Since we already
// know that the transformation preserves axis alignment, we only
// need to test the main diagonal
transpose_image_size = (concat_op->matrix.getScaleX() == 0 &&
concat_op->matrix.getScaleY() == 0);
break;
}
case PaintOpType::Concat44: {
// TODO(aaronhk) this replace Concact with Concat44 everywhere
// This function only needs to exist temporarily
if (transpose_image_size)
return base::nullopt;
const Concat44Op* concat_op = static_cast<const Concat44Op*>(op);
if (!MathUtil::SkM44Preserves2DAxisAlignment(concat_op->matrix))
return base::nullopt;
transpose_image_size = (concat_op->matrix.rc(0, 0) == 0 &&
concat_op->matrix.rc(1, 1) == 0);
break;
}
case PaintOpType::DrawImageRect:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment