Bug 1335998 - Part 2: Delegate matrix decomposition/interpolation/recomposition to Servo. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 07 Jun 2017 11:25:14 +0800
changeset 590023 0a86978578a7db7050d4c8854b31780c579652a1
parent 590022 715fafe856f413f3e03214bd009e9581ec498af6
child 590024 37387e693eb1899fb648225fc34f01d50ffd132e
push id62578
push userbmo:boris.chiou@gmail.com
push dateWed, 07 Jun 2017 04:32:00 +0000
bugs1335998
milestone55.0a1
Bug 1335998 - Part 2: Delegate matrix decomposition/interpolation/recomposition to Servo. 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()) {