Bug 1335998 - Part 2: Delegate matrix decomposition/interpolation/recomposition to Servo. r=birtles,manishearth
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 07 Jun 2017 11:25:14 +0800
changeset 410905 ab49fc64a4bf9271d2b33575907f7d5e6827a1f7
parent 410904 86c0fdac3bc28395b0f5795182a1ceadd4dc5fd9
child 410906 1df01865d1002d084da22266ab74827aa1298759
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles, manishearth
bugs1335998
milestone55.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 1335998 - Part 2: Delegate matrix decomposition/interpolation/recomposition to Servo. r=birtles,manishearth Use Servo backend to decompose/interpolate/recompose matrices on both main thread and compositor thread. Note: Due there may be differences in precision used to represent the components, and the computation of matrix interpolation are not exactly same (still following the formulas in spec). There are some tiny differences between the interpolation results of 2d/3d matrices on Gecko and Servo, especially if there is skew() or any 3d transform function. MozReview-Commit-ID: 6T8vlR4MJGr
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.toml
layout/style/nsStyleTransformMatrix.cpp
layout/style/nsStyleTransformMatrix.h
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -223,16 +223,23 @@ SERVO_BINDING_FUNC(Servo_ComputedValues_
 SERVO_BINDING_FUNC(Servo_Property_IsAnimatable, bool,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_Property_IsDiscreteAnimatable, bool,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_GetProperties_Overriding_Animation, void,
                    RawGeckoElementBorrowed,
                    RawGeckoCSSPropertyIDListBorrowed,
                    nsCSSPropertyIDSetBorrowedMut)
+SERVO_BINDING_FUNC(Servo_MatrixTransform_Operate, void,
+                   nsStyleTransformMatrix::MatrixTransformOperator
+                     matrix_operator,
+                   const RawGeckoGfxMatrix4x4* from,
+                   const RawGeckoGfxMatrix4x4* to,
+                   double progress,
+                   RawGeckoGfxMatrix4x4* result)
 
 // AnimationValues handling
 SERVO_BINDING_FUNC(Servo_AnimationValues_Interpolate,
                    RawServoAnimationValueStrong,
                    RawServoAnimationValueBorrowed from,
                    RawServoAnimationValueBorrowed to,
                    double progress)
 SERVO_BINDING_FUNC(Servo_AnimationValues_IsInterpolable, bool,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ServoBindingTypes_h
 #define mozilla_ServoBindingTypes_h
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/ServoTypes.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/gfx/Types.h"
 #include "nsCSSPropertyID.h"
 #include "nsStyleAutoArray.h"
 #include "nsTArray.h"
 
 struct RawServoStyleSet;
 struct RawServoAnimationValueMap;
 
 #define SERVO_ARC_TYPE(name_, type_) struct type_;
@@ -30,16 +31,19 @@ class Element;
 class StyleChildrenIterator;
 } // namespace dom
 struct AnimationPropertySegment;
 struct ComputedTiming;
 struct Keyframe;
 struct PropertyStyleAnimationValuePair;
 using ComputedKeyframeValues = nsTArray<PropertyStyleAnimationValuePair>;
 } // namespace mozilla
+namespace nsStyleTransformMatrix {
+enum class MatrixTransformOperator: uint8_t;
+}
 
 class nsCSSPropertyIDSet;
 class nsCSSValue;
 struct nsFontFaceRuleContainer;
 class nsIDocument;
 class nsINode;
 class nsPresContext;
 struct nsTimingFunction;
@@ -56,16 +60,17 @@ typedef nsTArray<mozilla::Keyframe> RawG
 typedef nsTArray<mozilla::ComputedKeyframeValues> RawGeckoComputedKeyframeValuesList;
 typedef nsTArray<mozilla::PropertyStyleAnimationValuePair> RawGeckoAnimationValueList;
 typedef nsStyleAutoArray<mozilla::StyleAnimation> RawGeckoStyleAnimationList;
 typedef nsTArray<nsFontFaceRuleContainer> RawGeckoFontFaceRuleList;
 typedef mozilla::AnimationPropertySegment RawGeckoAnimationPropertySegment;
 typedef mozilla::ComputedTiming RawGeckoComputedTiming;
 typedef nsTArray<const RawServoStyleRule*> RawGeckoServoStyleRuleList;
 typedef nsTArray<nsCSSPropertyID> RawGeckoCSSPropertyIDList;
+typedef mozilla::gfx::Float RawGeckoGfxMatrix4x4[16];
 
 // We have these helper types so that we can directly generate
 // things like &T or Borrowed<T> on the Rust side in the function, providing
 // additional safety benefits.
 //
 // FFI has a problem with templated types, so we just use raw pointers here.
 //
 // The "Borrowed" types generate &T or Borrowed<T> in the nullable case.
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -125,16 +125,17 @@ whitelist-types = [
     "mozilla::HalfCorner",
     "mozilla::PropertyStyleAnimationValuePair",
     "mozilla::TraversalRestyleBehavior",
     "mozilla::TraversalRootBehavior",
     "mozilla::StyleShapeRadius",
     "mozilla::StyleGrid.*",
     "mozilla::UpdateAnimationsTasks",
     "mozilla::LookAndFeel",
+    "mozilla::gfx::Float",
     "mozilla::gfx::FontVariation",
     ".*ThreadSafe.*Holder",
     "AnonymousContent",
     "AudioContext",
     "CapturingContentInfo",
     "DefaultDelete",
     "DOMIntersectionObserverEntry",
     "Element",
@@ -250,24 +251,26 @@ whitelist-types = [
     "ThemeWidgetType",
     "mozilla::UniquePtr",
     "mozilla::DefaultDelete",
     "mozilla::Side",
     "mozilla::binding_danger::AssertAndSuppressCleanupPolicy",
     "mozilla::ParsingMode",
     "mozilla::InheritTarget",
     "mozilla::StyleRuleInclusion",
+    "nsStyleTransformMatrix::MatrixTransformOperator",
 ]
 opaque-types = [
     "std::pair__PCCP",
     "std::namespace::atomic___base", "std::atomic__My_base",
     "std::atomic",
     "std::atomic___base",
-    # We want everything but FontVariation to be opaque but we don't have negative regexes ;_;
-    "mozilla::gfx::(.{0,12}|.{14,}|([^F][^o][^n][^t][^V][^a][^r][^i][^a][^t][^i][^o][^n]))",
+    # We want everything but FontVariation and Float to be opaque but we don't
+    # have negative regexes.
+    "mozilla::gfx::(.{0,4}|.{6,12}|.{14,}|([^F][^o][^n][^t][^V][^a][^r][^i][^a][^t][^i][^o][^n])|([^F][^l][^o][^a][^t]))",
     "FallibleTArray",
     "mozilla::dom::Sequence",
     "mozilla::dom::Optional",
     "mozilla::dom::Nullable",
     "RefPtr_Proxy",
     "RefPtr_Proxy_member_function",
     "nsAutoPtr_Proxy",
     "nsAutoPtr_Proxy_member_function",
@@ -308,16 +311,17 @@ fixups = [
 [bindings]
 headers = ["mozilla/ServoBindings.h"]
 hide-types = [
     "nsACString_internal",
     "nsAString_internal",
 ]
 raw-lines = [
     "pub use nsstring::{nsACString, nsAString, nsString, nsStringRepr};",
+    "use gecko_bindings::structs::nsStyleTransformMatrix;",
     "use gecko_bindings::structs::nsTArray;",
     "type nsACString_internal = nsACString;",
     "type nsAString_internal = nsAString;",
 ]
 whitelist-functions = ["Servo_.*", "Gecko_.*"]
 structs-types = [
     "mozilla::css::GridTemplateAreasValue",
     "mozilla::css::ImageValue",
@@ -431,16 +435,18 @@ structs-types = [
     "LoaderReusableStyleSheets",
     "ServoStyleSheet",
     "EffectCompositor_CascadeLevel",
     "UpdateAnimationsTasks",
     "ParsingMode",
     "InheritTarget",
     "URLMatchingFunction",
     "StyleRuleInclusion",
+    "nsStyleTransformMatrix::MatrixTransformOperator",
+    "RawGeckoGfxMatrix4x4",
 ]
 array-types = [
     { cpp-type = "uintptr_t", rust-type = "usize" },
 ]
 servo-owned-types = [
     { name = "RawServoStyleSet", opaque = true },
     { name = "StyleChildrenIterator", opaque = true },
     { name = "ServoElementSnapshot", opaque = false },
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -9,16 +9,17 @@
 
 #include "nsStyleTransformMatrix.h"
 #include "nsCSSValue.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsRuleNode.h"
 #include "nsSVGUtils.h"
 #include "nsCSSKeywords.h"
+#include "mozilla/ServoBindings.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "gfxMatrix.h"
 #include "gfxQuaternion.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 namespace nsStyleTransformMatrix {
@@ -303,16 +304,29 @@ public:
     scale *= sin(theta);
 
     gfxQuaternion result = gfxQuaternion(scale * aTwo.x,
                                          scale * aTwo.y,
                                          scale * aTwo.z,
                                          cos(theta)) * aOne;
     return result.ToMatrix();
   }
+
+  static Matrix4x4 operateByServo(const Matrix4x4& aMatrix1,
+                                  const Matrix4x4& aMatrix2,
+                                  double aCount)
+  {
+    Matrix4x4 result;
+    Servo_MatrixTransform_Operate(MatrixTransformOperator::Accumulate,
+                                  &aMatrix1.components,
+                                  &aMatrix2.components,
+                                  aCount,
+                                  &result.components);
+    return result;
+  }
 };
 
 class Interpolate {
 public:
   template<typename T>
   static T operate(const T& aOne, const T& aTwo, double aCoeff)
   {
     return aOne + (aTwo - aOne) * aCoeff;
@@ -333,16 +347,29 @@ public:
   }
 
   static Matrix4x4 operateForRotate(const gfxQuaternion& aOne,
                                     const gfxQuaternion& aTwo,
                                     double aCoeff)
   {
     return aOne.Slerp(aTwo, aCoeff).ToMatrix();
   }
+
+  static Matrix4x4 operateByServo(const Matrix4x4& aMatrix1,
+                                  const Matrix4x4& aMatrix2,
+                                  double aProgress)
+  {
+    Matrix4x4 result;
+    Servo_MatrixTransform_Operate(MatrixTransformOperator::Interpolate,
+                                  &aMatrix1.components,
+                                  &aMatrix2.components,
+                                  aProgress,
+                                  &result.components);
+    return result;
+  }
 };
 
 /**
  * Calculate 2 matrices by decomposing them with Operator.
  *
  * @param aMatrix1   First matrix, using CSS pixel units.
  * @param aMatrix2   Second matrix, using CSS pixel units.
  * @param aProgress  Coefficient for the Operator.
@@ -424,16 +451,25 @@ OperateTransformMatrix(const Matrix4x4 &
   if (scale != Point3D(1.0, 1.0, 1.0)) {
     result.PreScale(scale.x, scale.y, scale.z);
   }
 
   return result;
 }
 
 template <typename Operator>
+static Matrix4x4
+OperateTransformMatrixByServo(const Matrix4x4 &aMatrix1,
+                              const Matrix4x4 &aMatrix2,
+                              double aProgress)
+{
+  return Operator::operateByServo(aMatrix1, aMatrix2, aProgress);
+}
+
+template <typename Operator>
 static void
 ProcessMatrixOperator(Matrix4x4& aMatrix,
                       const nsCSSValue::Array* aData,
                       nsStyleContext* aContext,
                       nsPresContext* aPresContext,
                       RuleNodeCacheConditions& aConditions,
                       TransformReferenceBox& aRefBox,
                       bool* aContains3dTransform)
@@ -472,16 +508,24 @@ ProcessMatrixOperator(Matrix4x4& aMatrix
                                                     appUnitPerCSSPixel,
                                                     aContains3dTransform);
     return matrix;
   };
 
   Matrix4x4 matrix1 = readTransform(aData->Item(1));
   Matrix4x4 matrix2 = readTransform(aData->Item(2));
   double progress = aData->Item(3).GetPercentValue();
+
+  if (aContext && aContext->StyleSource().IsServoComputedValues()) {
+    aMatrix =
+      OperateTransformMatrixByServo<Operator>(matrix1, matrix2, progress)
+        * aMatrix;
+    return;
+  }
+
   aMatrix =
     OperateTransformMatrix<Operator>(matrix1, matrix2, progress) * aMatrix;
 }
 
 /* Helper function to process two matrices that we need to interpolate between */
 void
 ProcessInterpolateMatrix(Matrix4x4& aMatrix,
                          const nsCSSValue::Array* aData,
--- a/layout/style/nsStyleTransformMatrix.h
+++ b/layout/style/nsStyleTransformMatrix.h
@@ -23,16 +23,21 @@ struct nsRect;
 namespace mozilla {
 class RuleNodeCacheConditions;
 } // namespace mozilla
 
 /**
  * A helper to generate gfxMatrixes from css transform functions.
  */
 namespace nsStyleTransformMatrix {
+  // The operator passed to Servo backend.
+  enum class MatrixTransformOperator: uint8_t {
+    Interpolate,
+    Accumulate
+  };
 
   // Function for applying perspective() transform function. We treat
   // any value smaller than epsilon as perspective(infinity), which
   // follows CSSWG's resolution on perspective(0). See bug 1316236.
   inline void ApplyPerspectiveToMatrix(mozilla::gfx::Matrix4x4& aMatrix,
                                        float aDepth)
   {
     if (aDepth >= std::numeric_limits<float>::epsilon()) {