Skip to content

Commit

Permalink
Optimize some 2d full matrix operations in gfx::Transform
Browse files Browse the repository at this point in the history
There are two purposes:
1. To improve performance of 2d full matrix operations. Though full
   matrices are rare, some special apps (e.g. motionmark) use full
   2d matrices heavily. This CL can improve motionmark CanvasLine
   Leaves and Multiply by about 1%
   (https://pinpoint-dot-chromeperf.appspot.com/job/112ba12e5a0000).
2. To ensure 2d preservation in Inverse and Concat operations.

Bug: 1359528
Change-Id: Iab03df64166d8105e18652e2872fa1b34837f284
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4017954
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1069953}
  • Loading branch information
wangxianzhu authored and Chromium LUCI CQ committed Nov 10, 2022
1 parent 2057a46 commit f7c4f08
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 67 deletions.
14 changes: 4 additions & 10 deletions third_party/blink/renderer/core/geometry/dom_matrix.cc
Expand Up @@ -7,7 +7,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_unrestricteddoublesequence.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"

namespace blink {
Expand Down Expand Up @@ -277,15 +276,10 @@ DOMMatrix* DOMMatrix::perspectiveSelf(double p) {
}

DOMMatrix* DOMMatrix::invertSelf() {
// TODO(crbug.com/1359528): Let gfx::Transform::GetInverse() preserve
// 2d status and avoid the following block.
if (is2d_) {
AffineTransform affine_transform = AffineTransform::FromTransform(matrix_);
if (affine_transform.IsInvertible()) {
matrix_ = affine_transform.Inverse().ToTransform();
return this;
}
} else if (matrix_.GetInverse(&matrix_)) {
if (matrix_.GetInverse(&matrix_)) {
// We rely on gfx::Transform::GetInverse() to produce a 2d inverse for any
// 2d matrix.
DCHECK(!is2d_ || matrix_.Is2dTransform());
return this;
}

Expand Down
Expand Up @@ -30,7 +30,9 @@
assert_not_equals(poseMatrix, null);

for(let i = 0; i < poseMatrix.length; i++) {
assert_equals(poseMatrix[i], IDENTITY_MATRIX[i]);
// "0 +" is to accept -0 which is equivalent to 0 in the
// matrix.
assert_equals(0 + poseMatrix[i], IDENTITY_MATRIX[i]);
}

fakeDeviceController.setViewerOrigin(VALID_POSE_TRANSFORM);
Expand All @@ -46,7 +48,9 @@
assert_not_equals(poseMatrix, null);

for(let i = 0; i < poseMatrix.length; i++) {
assert_equals(poseMatrix[i], IDENTITY_MATRIX[i]);
// "0 +" is to accept -0 which is equivalent to 0 in the
// matrix.
assert_equals(0 + poseMatrix[i], IDENTITY_MATRIX[i]);
}
});

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
140 changes: 119 additions & 21 deletions ui/gfx/geometry/matrix44.cc
Expand Up @@ -111,27 +111,56 @@ void Matrix44::GetColMajorF(float dst[16]) const {
std::copy(src, src + 16, dst);
}

void Matrix44::PreTranslate(double dx, double dy, double dz) {
void Matrix44::PreTranslate(double dx, double dy) {
SetCol(3, Col(0) * dx + Col(1) * dy + Col(3));
}

void Matrix44::PreTranslate3d(double dx, double dy, double dz) {
if (AllTrue(Double4{dx, dy, dz, 0} == Double4{0, 0, 0, 0}))
return;

SetCol(3, Col(0) * dx + Col(1) * dy + Col(2) * dz + Col(3));
}

void Matrix44::PostTranslate(double dx, double dy, double dz) {
void Matrix44::PostTranslate(double dx, double dy) {
if (LIKELY(!HasPerspective())) {
matrix_[3][0] += dx;
matrix_[3][1] += dy;
} else {
if (dx != 0) {
matrix_[0][0] += matrix_[0][3] * dx;
matrix_[1][0] += matrix_[1][3] * dx;
matrix_[2][0] += matrix_[2][3] * dx;
matrix_[3][0] += matrix_[3][3] * dx;
}
if (dy != 0) {
matrix_[0][1] += matrix_[0][3] * dy;
matrix_[1][1] += matrix_[1][3] * dy;
matrix_[2][1] += matrix_[2][3] * dy;
matrix_[3][1] += matrix_[3][3] * dy;
}
}
}

void Matrix44::PostTranslate3d(double dx, double dy, double dz) {
Double4 t{dx, dy, dz, 0};
if (AllTrue(t == Double4{0, 0, 0, 0}))
return;

if (HasPerspective()) {
if (LIKELY(!HasPerspective())) {
SetCol(3, Col(3) + t);
} else {
for (int i = 0; i < 4; ++i)
SetCol(i, Col(i) + t * matrix_[i][3]);
} else {
SetCol(3, Col(3) + t);
}
}

void Matrix44::PreScale(double sx, double sy, double sz) {
void Matrix44::PreScale(double sx, double sy) {
SetCol(0, Col(0) * sx);
SetCol(1, Col(1) * sy);
}

void Matrix44::PreScale3d(double sx, double sy, double sz) {
if (AllTrue(Double4{sx, sy, sz, 1} == Double4{1, 1, 1, 1}))
return;

Expand All @@ -140,7 +169,22 @@ void Matrix44::PreScale(double sx, double sy, double sz) {
SetCol(2, Col(2) * sz);
}

void Matrix44::PostScale(double sx, double sy, double sz) {
void Matrix44::PostScale(double sx, double sy) {
if (sx != 1) {
matrix_[0][0] *= sx;
matrix_[1][0] *= sx;
matrix_[2][0] *= sx;
matrix_[3][0] *= sx;
}
if (sy != 1) {
matrix_[0][1] *= sy;
matrix_[1][1] *= sy;
matrix_[2][1] *= sy;
matrix_[3][1] *= sy;
}
}

void Matrix44::PostScale3d(double sx, double sy, double sz) {
if (AllTrue(Double4{sx, sy, sz, 1} == Double4{1, 1, 1, 1}))
return;

Expand All @@ -157,16 +201,16 @@ void Matrix44::RotateUnitSinCos(double x,
// Optimize cases where the axis is along a major axis. Since we've already
// normalized the vector we don't need to check that the other two dimensions
// are zero. Tiny errors of the other two dimensions are ignored.
if (x == 1.0) {
RotateAboutXAxisSinCos(sin_angle, cos_angle);
if (z == 1.0) {
RotateAboutZAxisSinCos(sin_angle, cos_angle);
return;
}
if (y == 1.0) {
RotateAboutYAxisSinCos(sin_angle, cos_angle);
return;
}
if (z == 1.0) {
RotateAboutZAxisSinCos(sin_angle, cos_angle);
if (x == 1.0) {
RotateAboutXAxisSinCos(sin_angle, cos_angle);
return;
}

Expand Down Expand Up @@ -234,16 +278,36 @@ void Matrix44::ApplyPerspectiveDepth(double perspective) {
SetCol(2, Col(2) + Col(3) * (-1.0 / perspective));
}

void Matrix44::SetConcat(const Matrix44& a, const Matrix44& b) {
auto c0 = a.Col(0);
auto c1 = a.Col(1);
auto c2 = a.Col(2);
auto c3 = a.Col(3);
void Matrix44::SetConcat(const Matrix44& x, const Matrix44& y) {
if (x.Is2dTransform() && y.Is2dTransform()) {
double a = x.matrix_[0][0];
double b = x.matrix_[0][1];
double c = x.matrix_[1][0];
double d = x.matrix_[1][1];
double e = x.matrix_[3][0];
double f = x.matrix_[3][1];
double ya = y.matrix_[0][0];
double yb = y.matrix_[0][1];
double yc = y.matrix_[1][0];
double yd = y.matrix_[1][1];
double ye = y.matrix_[3][0];
double yf = y.matrix_[3][1];
*this = Matrix44(a * ya + c * yb, b * ya + d * yb, 0, 0, // col 0
a * yc + c * yd, b * yc + d * yd, 0, 0, // col 1
0, 0, 1, 0, // col 2
a * ye + c * yf + e, b * ye + d * yf + f, 0, 1); // col 3
return;
}

auto c0 = x.Col(0);
auto c1 = x.Col(1);
auto c2 = x.Col(2);
auto c3 = x.Col(3);

auto mc0 = b.Col(0);
auto mc1 = b.Col(1);
auto mc2 = b.Col(2);
auto mc3 = b.Col(3);
auto mc0 = y.Col(0);
auto mc1 = y.Col(1);
auto mc2 = y.Col(2);
auto mc3 = y.Col(3);

SetCol(0, c0 * mc0[0] + c1 * mc0[1] + c2 * mc0[2] + c3 * mc0[3]);
SetCol(1, c0 * mc1[0] + c1 * mc1[1] + c2 * mc1[2] + c3 * mc1[3]);
Expand All @@ -252,6 +316,26 @@ void Matrix44::SetConcat(const Matrix44& a, const Matrix44& b) {
}

bool Matrix44::GetInverse(Matrix44& result) const {
if (Is2dTransform()) {
double determinant = Determinant();
if (!std::isnormal(static_cast<float>(determinant)))
return false;

double inv_det = 1.0 / determinant;
double a = matrix_[0][0];
double b = matrix_[0][1];
double c = matrix_[1][0];
double d = matrix_[1][1];
double e = matrix_[3][0];
double f = matrix_[3][1];
result = Matrix44(d * inv_det, -b * inv_det, 0, 0, // col 0
-c * inv_det, a * inv_det, 0, 0, // col 1
0, 0, 1, 0, // col 2
(c * f - d * e) * inv_det, (b * e - a * f) * inv_det, 0,
1); // col 3
return true;
}

Double4 c0 = Col(0);
Double4 c1 = Col(1);
Double4 c2 = Col(2);
Expand All @@ -273,6 +357,9 @@ bool Matrix44::IsInvertible() const {

// This is a simplified version of InverseWithDouble4Cols().
double Matrix44::Determinant() const {
if (Is2dTransform())
return matrix_[0][0] * matrix_[1][1] - matrix_[0][1] * matrix_[1][0];

Double4 c0 = Col(0);
Double4 c1 = Col(1);
Double4 c2 = Col(2);
Expand Down Expand Up @@ -320,7 +407,18 @@ void Matrix44::Zoom(double zoom_factor) {
matrix_[3][2] *= zoom_factor;
}

void Matrix44::MapScalars(double vec[4]) const {
double Matrix44::MapVector2(double vec[2]) const {
double v0 = vec[0];
double v1 = vec[1];
double x = v0 * matrix_[0][0] + v1 * matrix_[1][0] + matrix_[3][0];
double y = v0 * matrix_[0][1] + v1 * matrix_[1][1] + matrix_[3][1];
double w = v0 * matrix_[0][3] + v1 * matrix_[1][3] + matrix_[3][3];
vec[0] = x;
vec[1] = y;
return w;
}

void Matrix44::MapVector4(double vec[4]) const {
Double4 v = LoadDouble4(vec);
Double4 r0{matrix_[0][0], matrix_[1][0], matrix_[2][0], matrix_[3][0]};
Double4 r1{matrix_[0][1], matrix_[1][1], matrix_[2][1], matrix_[3][1]};
Expand Down
21 changes: 15 additions & 6 deletions ui/gfx/geometry/matrix44.h
Expand Up @@ -126,14 +126,18 @@ class GEOMETRY_SKIA_EXPORT Matrix44 {
void GetColMajorF(float[16]) const;

// this = this * translation.
void PreTranslate(double dx, double dy, double dz);
void PreTranslate(double dx, double dy);
void PreTranslate3d(double dx, double dy, double dz);
// this = translation * this.
void PostTranslate(double dx, double dy, double dz);
void PostTranslate(double dx, double dy);
void PostTranslate3d(double dx, double dy, double dz);

// this = this * scale.
void PreScale(double sx, double sy, double sz);
void PreScale(double sx, double sy);
void PreScale3d(double sx, double sy, double sz);
// this = scale * this.
void PostScale(double sx, double sy, double sz);
void PostScale(double sx, double sy);
void PostScale3d(double sx, double sy, double sz);

// Rotates this matrix about the specified unit-length axis vector,
// by an angle specified by its sin() and cos(). This does not attempt to
Expand Down Expand Up @@ -166,6 +170,8 @@ class GEOMETRY_SKIA_EXPORT Matrix44 {
void PreConcat(const Matrix44& m) { SetConcat(*this, m); }
// this = m * this.
void PostConcat(const Matrix44& m) { SetConcat(m, *this); }
// this = a * b.
void SetConcat(const Matrix44& a, const Matrix44& b);

// Returns true and set |inverse| to the inverted matrix if this matrix
// is invertible. Otherwise return false and leave the |inverse| parameter
Expand All @@ -182,14 +188,17 @@ class GEOMETRY_SKIA_EXPORT Matrix44 {
void Zoom(double zoom_factor);

// Applies the matrix to the vector in place.
void MapScalars(double vec[4]) const;
void MapVector4(double vec[4]) const;

// Same as above, but assumes the vec[2] is 0 and vec[3] is 1, discards
// vec[2], and returns vec[3].
double MapVector2(double vec[2]) const;

void Flatten();

absl::optional<DecomposedTransform> Decompose() const;

private:
void SetConcat(const Matrix44& a, const Matrix44& b);
absl::optional<DecomposedTransform> Decompose2d() const;

ALWAYS_INLINE Double4 Col(int i) const { return LoadDouble4(matrix_[i]); }
Expand Down

0 comments on commit f7c4f08

Please sign in to comment.