Title: [267276] branches/safari-610-branch/Source/WebCore
- Revision
- 267276
- Author
- [email protected]
- Date
- 2020-09-18 12:36:39 -0700 (Fri, 18 Sep 2020)
Log Message
Cherry-pick r266619. rdar://problem/69101154
Add a fast path in TransformationMatrix::mapRect(const FloatRect&) for affine transformations
https://bugs.webkit.org/show_bug.cgi?id=216139
Reviewed by Tim Horton.
Add a fast path when mapping 2D points through affine transformation matrices that takes advantage of both:
1. The predetermined 0 and 1 values in affine transformation matrices.
2. The fact that points in the FloatRect are aligned with x and y axes (as opposed to a FloatQuad of 4 arbitrary
points), which allows us to avoid mapping all 4 corners of the rect through the matrix.
The current implementation of this method maps each of the 4 corners through the transformation matrix, creates
a FloatQuad using these 4 transformed points, and then asks the FloatQuad for its bounding box. This requires
a total of 26 floating point additions, 24 multiplications and 20 comparisons, as well as a small (but
measurable) amount of overhead when creating the FloatPoints and FloatQuad and asking for the bounding rect.
We can pare this down to just 8 additions, 8 multiplications, and 4 comparisons by using a different strategy
that instead branches on the 4 relevant matrix coefficients `a, b, c, d` (rather than the each of the final x
and y coordinates) to determine which of the min or max x and y values to multiply in order to compute the min
and max x and y coordinates in the final bounding rect.
In a quick microbenchmark that maps FloatRects through an affine TransformationMatrix, this roughly halves the
time spent in `TransformationMatrix::mapRect`; on the Multiply subtest of MotionMark (which invokes this method
~17 million times, almost entirely with affine transformation matrices), I measured a ~1% improvement.
* platform/graphics/transforms/TransformationMatrix.cpp:
(WebCore::TransformationMatrix::mapRect const):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Modified Paths
Diff
Modified: branches/safari-610-branch/Source/WebCore/ChangeLog (267275 => 267276)
--- branches/safari-610-branch/Source/WebCore/ChangeLog 2020-09-18 19:36:37 UTC (rev 267275)
+++ branches/safari-610-branch/Source/WebCore/ChangeLog 2020-09-18 19:36:39 UTC (rev 267276)
@@ -1,5 +1,68 @@
2020-09-18 Alan Coon <[email protected]>
+ Cherry-pick r266619. rdar://problem/69101154
+
+ Add a fast path in TransformationMatrix::mapRect(const FloatRect&) for affine transformations
+ https://bugs.webkit.org/show_bug.cgi?id=216139
+
+ Reviewed by Tim Horton.
+
+ Add a fast path when mapping 2D points through affine transformation matrices that takes advantage of both:
+ 1. The predetermined 0 and 1 values in affine transformation matrices.
+ 2. The fact that points in the FloatRect are aligned with x and y axes (as opposed to a FloatQuad of 4 arbitrary
+ points), which allows us to avoid mapping all 4 corners of the rect through the matrix.
+
+ The current implementation of this method maps each of the 4 corners through the transformation matrix, creates
+ a FloatQuad using these 4 transformed points, and then asks the FloatQuad for its bounding box. This requires
+ a total of 26 floating point additions, 24 multiplications and 20 comparisons, as well as a small (but
+ measurable) amount of overhead when creating the FloatPoints and FloatQuad and asking for the bounding rect.
+
+ We can pare this down to just 8 additions, 8 multiplications, and 4 comparisons by using a different strategy
+ that instead branches on the 4 relevant matrix coefficients `a, b, c, d` (rather than the each of the final x
+ and y coordinates) to determine which of the min or max x and y values to multiply in order to compute the min
+ and max x and y coordinates in the final bounding rect.
+
+ In a quick microbenchmark that maps FloatRects through an affine TransformationMatrix, this roughly halves the
+ time spent in `TransformationMatrix::mapRect`; on the Multiply subtest of MotionMark (which invokes this method
+ ~17 million times, almost entirely with affine transformation matrices), I measured a ~1% improvement.
+
+ * platform/graphics/transforms/TransformationMatrix.cpp:
+ (WebCore::TransformationMatrix::mapRect const):
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2020-09-04 Wenson Hsieh <[email protected]>
+
+ Add a fast path in TransformationMatrix::mapRect(const FloatRect&) for affine transformations
+ https://bugs.webkit.org/show_bug.cgi?id=216139
+
+ Reviewed by Tim Horton.
+
+ Add a fast path when mapping 2D points through affine transformation matrices that takes advantage of both:
+ 1. The predetermined 0 and 1 values in affine transformation matrices.
+ 2. The fact that points in the FloatRect are aligned with x and y axes (as opposed to a FloatQuad of 4 arbitrary
+ points), which allows us to avoid mapping all 4 corners of the rect through the matrix.
+
+ The current implementation of this method maps each of the 4 corners through the transformation matrix, creates
+ a FloatQuad using these 4 transformed points, and then asks the FloatQuad for its bounding box. This requires
+ a total of 26 floating point additions, 24 multiplications and 20 comparisons, as well as a small (but
+ measurable) amount of overhead when creating the FloatPoints and FloatQuad and asking for the bounding rect.
+
+ We can pare this down to just 8 additions, 8 multiplications, and 4 comparisons by using a different strategy
+ that instead branches on the 4 relevant matrix coefficients `a, b, c, d` (rather than the each of the final x
+ and y coordinates) to determine which of the min or max x and y values to multiply in order to compute the min
+ and max x and y coordinates in the final bounding rect.
+
+ In a quick microbenchmark that maps FloatRects through an affine TransformationMatrix, this roughly halves the
+ time spent in `TransformationMatrix::mapRect`; on the Multiply subtest of MotionMark (which invokes this method
+ ~17 million times, almost entirely with affine transformation matrices), I measured a ~1% improvement.
+
+ * platform/graphics/transforms/TransformationMatrix.cpp:
+ (WebCore::TransformationMatrix::mapRect const):
+
+2020-09-18 Alan Coon <[email protected]>
+
Cherry-pick r266513. rdar://problem/69153717
Make TransformationMatrix::inverse() faster in the case of affine transformation matrices
Modified: branches/safari-610-branch/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp (267275 => 267276)
--- branches/safari-610-branch/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp 2020-09-18 19:36:37 UTC (rev 267275)
+++ branches/safari-610-branch/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp 2020-09-18 19:36:39 UTC (rev 267276)
@@ -751,20 +751,70 @@
FloatRect TransformationMatrix::mapRect(const FloatRect& r) const
{
- if (isIdentityOrTranslation()) {
+ auto type = this->type();
+ if (type == Type::IdentityOrTranslation) {
FloatRect mappedRect(r);
mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
return mappedRect;
}
+ float minX = r.x();
+ float minY = r.y();
+ float maxX = r.maxX();
+ float maxY = r.maxY();
+
+ if (type == Type::Affine) {
+ double a = m11();
+ double b = m12();
+ double c = m21();
+ double d = m22();
+
+ double minResultX;
+ double minResultY;
+ double maxResultX;
+ double maxResultY;
+
+ if (a > 0) {
+ maxResultX = a * maxX;
+ minResultX = a * minX;
+ } else {
+ maxResultX = a * minX;
+ minResultX = a * maxX;
+ }
+
+ if (b > 0) {
+ maxResultY = b * maxX;
+ minResultY = b * minX;
+ } else {
+ maxResultY = b * minX;
+ minResultY = b * maxX;
+ }
+
+ if (c > 0) {
+ maxResultX += c * maxY;
+ minResultX += c * minY;
+ } else {
+ maxResultX += c * minY;
+ minResultX += c * maxY;
+ }
+
+ if (d > 0) {
+ maxResultY += d * maxY;
+ minResultY += d * minY;
+ } else {
+ maxResultY += d * minY;
+ minResultY += d * maxY;
+ }
+
+ return FloatRect(minResultX + m41(), minResultY + m42(), maxResultX - minResultX, maxResultY - minResultY);
+ }
+
FloatQuad result;
- float maxX = r.maxX();
- float maxY = r.maxY();
- result.setP1(internalMapPoint(FloatPoint(r.x(), r.y())));
- result.setP2(internalMapPoint(FloatPoint(maxX, r.y())));
+ result.setP1(internalMapPoint(FloatPoint(minX, minY)));
+ result.setP2(internalMapPoint(FloatPoint(maxX, minY)));
result.setP3(internalMapPoint(FloatPoint(maxX, maxY)));
- result.setP4(internalMapPoint(FloatPoint(r.x(), maxY)));
+ result.setP4(internalMapPoint(FloatPoint(minX, maxY)));
return result.boundingBox();
}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes