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 209256 1a860977f8c7c33f4d7b01d9b80606d990224d33
parent 209255 04c92cdfcde4efe80f94d70928c852c9e03b87d0
child 209257 c0e4ec5fc709907e9c6b004945f2998d936145be
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersBas
bugs1077961
milestone35.0a1
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;
   }