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
--- 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()) {