Bug 1077961, part 1 - Add various methods to Moz2D Matrix4x4 to allow us to minimize multiplications. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Wed, 08 Oct 2014 04:40:44 +0100
changeset 232471 1a860977f8c7c33f4d7b01d9b80606d990224d33
parent 232470 04c92cdfcde4efe80f94d70928c852c9e03b87d0
child 232472 c0e4ec5fc709907e9c6b004945f2998d936145be
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1077961
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1077961, part 1 - Add various methods to Moz2D Matrix4x4 to allow us to minimize multiplications. r=Bas
gfx/2d/Matrix.h
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -78,18 +78,18 @@ public:
   /**
    * Apply a translation to this matrix.
    *
    * The "Pre" in this method's name means that the translation is applied
    * -before- this matrix's existing transformation. That is, any vector that
    * is multiplied by the resulting matrix will first be translated, then be
    * transformed by the original transform.
    *
-   * Thus calling this method will result in this matrix having the same value
-   * as the result of:
+   * Calling this method will result in this matrix having the same value as
+   * the result of:
    *
    *   Matrix::Translation(x, y) * this
    *
    * (Note that in performance critical code multiplying by the result of a
    * Translation()/Scaling() call is not recommended since that results in a
    * full matrix multiply involving 12 floating-point multiplications. Calling
    * this method would be preferred since it only involves four floating-point
    * multiplications.)
@@ -132,32 +132,32 @@ public:
   }
 
   static Matrix Scaling(Float aScaleX, Float aScaleY)
   {
     return Matrix(aScaleX, 0.0f, 0.0f, aScaleY, 0.0f, 0.0f);
   }
   
   /**
-   * Similar to PreTranslate, but applies a scale to this matrix.
+   * Similar to PreTranslate, but applies a scale instead of a translation.
    */
   Matrix &PreScale(Float aX, Float aY)
   {
     _11 *= aX;
     _12 *= aX;
     _21 *= aY;
     _22 *= aY;
 
     return *this;
   }
   
   GFX2D_API static Matrix Rotation(Float aAngle);
 
   /**
-   * Similar to PreTranslate, but applies a rotation to this matrix.
+   * Similar to PreTranslate, but applies a rotation instead of a translation.
    */
   Matrix &PreRotate(Float aAngle)
   {
     return *this = Matrix::Rotation(aAngle) * *this;
   }
 
   bool Invert()
   {
@@ -360,16 +360,26 @@ class Matrix4x4
 public:
   Matrix4x4()
     : _11(1.0f), _12(0.0f), _13(0.0f), _14(0.0f)
     , _21(0.0f), _22(1.0f), _23(0.0f), _24(0.0f)
     , _31(0.0f), _32(0.0f), _33(1.0f), _34(0.0f)
     , _41(0.0f), _42(0.0f), _43(0.0f), _44(1.0f)
   {}
 
+  Matrix4x4(Float a11, Float a12, Float a13, Float a14,
+            Float a21, Float a22, Float a23, Float a24,
+            Float a31, Float a32, Float a33, Float a34,
+            Float a41, Float a42, Float a43, Float a44)
+    : _11(a11), _12(a12), _13(a13), _14(a14)
+    , _21(a21), _22(a22), _23(a23), _24(a24)
+    , _31(a31), _32(a32), _33(a33), _34(a34)
+    , _41(a41), _42(a42), _43(a43), _44(a44)
+  {}
+
   Float _11, _12, _13, _14;
   Float _21, _22, _23, _24;
   Float _31, _32, _33, _34;
   Float _41, _42, _43, _44;
 
   Point4D& operator[](int aIndex)
   {
       MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
@@ -453,16 +463,18 @@ public:
 
     // Solving for z when z' = 0 gives us:
     float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
 
     // Compute the transformed point
     return *this * Point4D(aPoint.x, aPoint.y, z, 1);
   }
 
+  Rect ProjectRectBounds(const Rect& aRect) const;
+
   static Matrix4x4 From2D(const Matrix &aMatrix) {
     Matrix4x4 matrix;
     matrix._11 = aMatrix._11;
     matrix._12 = aMatrix._12;
     matrix._21 = aMatrix._21;
     matrix._22 = aMatrix._22;
     matrix._41 = aMatrix._31;
     matrix._42 = aMatrix._32;
@@ -513,59 +525,127 @@ public:
     temp = *this * temp;
     temp /= temp.w;
 
     return Point(temp.x, temp.y);
   }
 
   GFX2D_API Rect TransformBounds(const Rect& rect) const;
 
-  // Apply a scale to this matrix. This scale will be applied -before- the
-  // existing transformation of the matrix.
+
+  static Matrix4x4 Translation(Float aX, Float aY, Float aZ)
+  {
+    return Matrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+                     0.0f, 1.0f, 0.0f, 0.0f,
+                     0.0f, 0.0f, 1.0f, 0.0f,
+                       aX,   aY,   aZ, 1.0f);
+  }
+
+  /**
+   * Apply a translation to this matrix.
+   *
+   * The "Pre" in this method's name means that the translation is applied
+   * -before- this matrix's existing transformation. That is, any vector that
+   * is multiplied by the resulting matrix will first be translated, then be
+   * transformed by the original transform.
+   *
+   * Calling this method will result in this matrix having the same value as
+   * the result of:
+   *
+   *   Matrix4x4::Translation(x, y) * this
+   *
+   * (Note that in performance critical code multiplying by the result of a
+   * Translation()/Scaling() call is not recommended since that results in a
+   * full matrix multiply involving 64 floating-point multiplications. Calling
+   * this method would be preferred since it only involves 12 floating-point
+   * multiplications.)
+   */
+  Matrix4x4 &Translate(Float aX, Float aY, Float aZ)
+  {
+    _41 += aX * _11 + aY * _21 + aZ * _31;
+    _42 += aX * _12 + aY * _22 + aZ * _32;
+    _43 += aX * _13 + aY * _23 + aZ * _33;
+    _44 += aX * _14 + aY * _24 + aZ * _34;
+
+    return *this;
+  }
+
+  /**
+   * Similar to PreTranslate, but the translation is applied -after- this
+   * matrix's existing transformation instead of before it.
+   *
+   * This method is generally less used than PreTranslate since typically code
+   * wants to adjust an existing user space to device space matrix to create a
+   * transform to device space from a -new- user space (translated from the
+   * previous user space). In that case consumers will need to use the Pre*
+   * variants of the matrix methods rather than using the Post* methods, since
+   * the Post* methods add a transform to the device space end of the
+   * transformation.
+   */
+  Matrix4x4 &PostTranslate(Float aX, Float aY, Float aZ)
+  {
+    _11 += _14 * aX;
+    _21 += _24 * aX;
+    _31 += _34 * aX;
+    _41 += _44 * aX;
+    _12 += _14 * aY;
+    _22 += _24 * aY;
+    _32 += _34 * aY;
+    _42 += _44 * aY;
+    _13 += _14 * aZ;
+    _23 += _24 * aZ;
+    _33 += _34 * aZ;
+    _43 += _44 * aZ;
+
+    return *this;
+  }
+
+  static Matrix4x4 Scaling(Float aScaleX, Float aScaleY, float aScaleZ)
+  {
+    return Matrix4x4(aScaleX, 0.0f, 0.0f, 0.0f,
+                     0.0f, aScaleY, 0.0f, 0.0f,
+                     0.0f, 0.0f, aScaleZ, 0.0f,
+                     0.0f, 0.0f, 0.0f, 1.0f);
+  }
+
+  /**
+   * Similar to PreTranslate, but applies a scale instead of a translation.
+   */
   Matrix4x4 &Scale(Float aX, Float aY, Float aZ)
   {
     _11 *= aX;
     _12 *= aX;
     _13 *= aX;
     _21 *= aY;
     _22 *= aY;
     _23 *= aY;
     _31 *= aZ;
     _32 *= aZ;
     _33 *= aZ;
 
     return *this;
   }
 
-  Matrix4x4 &Translate(Float aX, Float aY, Float aZ)
+  /**
+   * Similar to PostTranslate, but applies a scale instead of a translation.
+   */
+  Matrix4x4 &PostScale(Float aScaleX, Float aScaleY, Float aScaleZ)
   {
-    _41 += aX * _11 + aY * _21 + aZ * _31;
-    _42 += aX * _12 + aY * _22 + aZ * _32;
-    _43 += aX * _13 + aY * _23 + aZ * _33;
-    _44 += aX * _14 + aY * _24 + aZ * _34;
-
-    return *this;
-  }
-
-  Rect ProjectRectBounds(const Rect& aRect) const;
-
-  Matrix4x4 &PostTranslate(Float aX, Float aY, Float aZ)
-  {
-    _11 += _14 * aX;
-    _21 += _24 * aX;
-    _31 += _34 * aX;
-    _41 += _44 * aX;
-    _12 += _14 * aY;
-    _22 += _24 * aY;
-    _32 += _34 * aY;
-    _42 += _44 * aY;
-    _13 += _14 * aZ;
-    _23 += _24 * aZ;
-    _33 += _34 * aZ;
-    _43 += _44 * aZ;
+    _11 *= aScaleX;
+    _21 *= aScaleX;
+    _31 *= aScaleX;
+    _41 *= aScaleX;
+    _12 *= aScaleY;
+    _22 *= aScaleY;
+    _32 *= aScaleY;
+    _42 *= aScaleY;
+    _13 *= aScaleZ;
+    _23 *= aScaleZ;
+    _33 *= aScaleZ;
+    _43 *= aScaleZ;
 
     return *this;
   }
 
   void SkewXY(Float aSkew)
   {
     (*this)[1] += (*this)[0] * aSkew;
   }