Bug 1334036 - Part 2: Implement FFI for finding properties overriding animations. draft
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 13 Feb 2017 15:42:09 +0800
changeset 487073 deeff64faa46daa2397d916fe65ec81b785cf653
parent 487072 db1656a7038127a3d5fd7742b4001d636b82609f
child 487074 ee8d3b43a5bee157209daeac062a173852d6b4f3
push id46122
push userbmo:boris.chiou@gmail.com
push dateMon, 20 Feb 2017 16:08:18 +0000
bugs1334036
milestone54.0a1
Bug 1334036 - Part 2: Implement FFI for finding properties overriding animations. MozReview-Commit-ID: 67NO2nIcUfq
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
servo/components/style/build_gecko.rs
servo/components/style/gecko_bindings/bindings.rs
servo/components/style/gecko_bindings/structs_debug.rs
servo/components/style/gecko_bindings/structs_release.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/rule_tree/mod.rs
servo/ports/geckolib/glue.rs
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -121,23 +121,16 @@ FindAnimationsForCompositor(const nsIFra
   MOZ_ASSERT(!aMatches || aMatches->IsEmpty(),
              "Matches array, if provided, should be empty");
 
   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
   if (!effects || effects->IsEmpty()) {
     return false;
   }
 
-  // FIXME: Bug 1334036: stylo: Implement off-main-thread animations.
-  if (aFrame->StyleContext()->StyleSource().IsServoComputedValues()) {
-    NS_WARNING("stylo: return false in FindAnimationsForCompositor because "
-               "haven't supported compositor-driven animations yet");
-    return false;
-  }
-
   // First check for newly-started transform animations that should be
   // synchronized with geometric animations. We need to do this before any
   // other early returns (the one above is ok) since we can only check this
   // state when the animation is newly-started.
   if (aProperty == eCSSProperty_transform) {
     PendingAnimationTracker* tracker =
       aFrame->PresContext()->Document()->GetPendingAnimationTracker();
     if (tracker) {
@@ -764,17 +757,18 @@ EffectCompositor::ComposeAnimationRule(d
 
   MOZ_ASSERT(effects == EffectSet::GetEffectSet(aElement, aPseudoType),
              "EffectSet should not change while composing style");
 
   effects->UpdateAnimationRuleRefreshTime(aCascadeLevel, aRefreshTime);
 }
 
 /* static */ void
-EffectCompositor::GetOverriddenProperties(nsStyleContext* aStyleContext,
+EffectCompositor::GetOverriddenProperties(const Element* aElement,
+                                          nsStyleContext* aStyleContext,
                                           EffectSet& aEffectSet,
                                           nsCSSPropertyIDSet&
                                             aPropertiesOverridden)
 {
   AutoTArray<nsCSSPropertyID, LayerAnimationInfo::kRecords> propertiesToTrack;
   {
     nsCSSPropertyIDSet propertiesToTrackAsSet;
     for (KeyframeEffectReadOnly* effect : aEffectSet) {
@@ -793,19 +787,26 @@ EffectCompositor::GetOverriddenPropertie
       }
     }
   }
 
   if (propertiesToTrack.IsEmpty()) {
     return;
   }
 
-  nsRuleNode::ComputePropertiesOverridingAnimation(propertiesToTrack,
-                                                   aStyleContext,
-                                                   aPropertiesOverridden);
+  if (aStyleContext->PresContext()->RestyleManager()->IsGecko()) {
+    nsRuleNode::ComputePropertiesOverridingAnimation(propertiesToTrack,
+                                                     aStyleContext,
+                                                     aPropertiesOverridden);
+  } else {
+    MOZ_ASSERT(aElement);
+    Servo_GetProperties_Overriding_Animation(aElement,
+                                             &propertiesToTrack,
+                                             &aPropertiesOverridden);
+  }
 }
 
 /* static */ void
 EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
                                        Element* aElement,
                                        CSSPseudoElementType aPseudoType,
                                        nsStyleContext* aStyleContext)
 {
@@ -823,19 +824,28 @@ EffectCompositor::UpdateCascadeResults(E
   }
   sortedEffectList.Sort(EffectCompositeOrderComparator());
 
   // Get properties that override the *animations* level of the cascade.
   //
   // We only do this for properties that we can animate on the compositor
   // since we will apply other properties on the main thread where the usual
   // cascade applies.
+  // FIXME: Bug 1302946: stylo don't use |aStyleContext| to get the RuleNode,
+  // instead, we traverse the (Servo) Rule tree by the RuleNode got from
+  // |aElement|. However, we pass nullptr as |aStyleContext| in
+  // AddStyleUpdatesTo(), which means we don't need to re-walk the Rule tree,
+  // so I still keep the condition here.
+  // If stylo also need to call AddStyleUpdatesTo() (for ensuring that style
+  // resulting from any animation is up-to-date before starting transitions),
+  // please double-check the function signature is also suitable for stylo.
   nsCSSPropertyIDSet overriddenProperties;
   if (aStyleContext) {
-    GetOverriddenProperties(aStyleContext, aEffectSet, overriddenProperties);
+    GetOverriddenProperties(aElement, aStyleContext, aEffectSet,
+                            overriddenProperties);
   }
 
   // Returns a bitset the represents which properties from
   // LayerAnimationInfo::sRecords are present in |aPropertySet|.
   auto compositorPropertiesInSet =
     [](nsCSSPropertyIDSet& aPropertySet) ->
       std::bitset<LayerAnimationInfo::kRecords> {
         std::bitset<LayerAnimationInfo::kRecords> result;
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -244,19 +244,21 @@ private:
                                    TimeStamp aRefreshTime);
 
   static dom::Element* GetElementToRestyle(dom::Element* aElement,
                                            CSSPseudoElementType
                                              aPseudoType);
 
   // Get the properties in |aEffectSet| that we are able to animate on the
   // compositor but which are also specified at a higher level in the cascade
-  // than the animations level in |aStyleContext|.
+  // than the animations level in |aStyleContext| on Gecko.
+  // stylo: Servo-backend stores the RuleNode in |aElement| (i.e. GeckoElement).
   static void
-  GetOverriddenProperties(nsStyleContext* aStyleContext,
+  GetOverriddenProperties(const dom::Element* aElement,
+                          nsStyleContext* aStyleContext,
                           EffectSet& aEffectSet,
                           nsCSSPropertyIDSet& aPropertiesOverridden);
 
   static void
   UpdateCascadeResults(EffectSet& aEffectSet,
                        dom::Element* aElement,
                        CSSPseudoElementType aPseudoType,
                        nsStyleContext* aStyleContext);
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -100,16 +100,20 @@ SERVO_BINDING_FUNC(Servo_StyleRule_GetSe
 
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    RawServoDeclarationBlockStrong,
                    const nsACString* property, const nsACString* value,
                    const nsACString* base_url, ThreadSafeURIHolder* base,
                    ThreadSafeURIHolder* referrer,
                    ThreadSafePrincipalHolder* principal)
+SERVO_BINDING_FUNC(Servo_GetProperties_Overriding_Animation, void,
+                   RawGeckoElementBorrowed,
+                   nsTArrayBorrowed_nsCSSPropertyID,
+                   nsCSSPropertyIDSetBorrowedMut)
 
 // AnimationValues handling
 SERVO_BINDING_FUNC(Servo_AnimationValues_Populate, void,
                    RawGeckoAnimationValueListBorrowedMut,
                    RawServoDeclarationBlockBorrowed,
                    ServoComputedValuesBorrowed,
                    ServoComputedValuesBorrowedOrNull,
                    RawGeckoPresContextBorrowed)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -24,16 +24,17 @@ namespace mozilla {
 namespace dom {
 class Element;
 class StyleChildrenIterator;
 } // namespace dom
 struct Keyframe;
 struct PropertyStyleAnimationValuePair;
 } // namespace mozilla
 
+class nsCSSPropertyIDSet;
 class nsCSSValue;
 class nsIDocument;
 class nsINode;
 class nsPresContext;
 
 using mozilla::dom::StyleChildrenIterator;
 using mozilla::ServoElementSnapshot;
 
@@ -111,16 +112,17 @@ DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChil
 DECL_BORROWED_MUT_REF_TYPE_FOR(ServoElementSnapshot)
 DECL_BORROWED_REF_TYPE_FOR(nsCSSValue)
 DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue)
 DECL_OWNED_REF_TYPE_FOR(RawGeckoPresContext)
 DECL_BORROWED_REF_TYPE_FOR(RawGeckoPresContext)
 DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoAnimationValueList)
 DECL_BORROWED_REF_TYPE_FOR(RawServoAnimationValueBorrowedList)
 DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoKeyframeList)
+DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSPropertyIDSet)
 
 #undef DECL_ARC_REF_TYPE_FOR
 #undef DECL_OWNED_REF_TYPE_FOR
 #undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
 #undef DECL_BORROWED_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
 #undef DECL_BORROWED_MUT_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1320,16 +1320,23 @@ Gecko_LoadStyleSheet(css::Loader* aLoade
 }
 
 const nsMediaFeature*
 Gecko_GetMediaFeatures()
 {
   return nsMediaFeatures::features;
 }
 
+void
+Gecko_AddPropertyToSet(nsCSSPropertyIDSetBorrowedMut aPropertySet,
+                       nsCSSPropertyID aProperty)
+{
+  aPropertySet->AddProperty(aProperty);
+}
+
 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 
 #define STYLE_STRUCT(name, checkdata_cb)                                      \
                                                                               \
 void                                                                          \
 Gecko_Construct_Default_nsStyle##name(nsStyle##name* ptr,                     \
                                       const nsPresContext* pres_context)      \
 {                                                                             \
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -75,16 +75,17 @@ struct nsStyleDisplay;
 
 #define DEFINE_ARRAY_TYPE_FOR(type_)                                \
   struct nsTArrayBorrowed_##type_ {                                 \
     nsTArray<type_>* mArray;                                        \
     MOZ_IMPLICIT nsTArrayBorrowed_##type_(nsTArray<type_>* aArray)  \
       : mArray(aArray) {}                                           \
   }
 DEFINE_ARRAY_TYPE_FOR(uintptr_t);
+DEFINE_ARRAY_TYPE_FOR(nsCSSPropertyID);
 #undef DEFINE_ARRAY_TYPE_FOR
 
 extern "C" {
 
 // Object refcounting.
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
 
@@ -339,16 +340,18 @@ void Gecko_CSSValue_Drop(nsCSSValueBorro
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 bool Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id);
 
 void Gecko_nsStyleFont_SetLang(nsStyleFont* font, nsIAtom* atom);
 void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource);
 
 const nsMediaFeature* Gecko_GetMediaFeatures();
 
+void Gecko_AddPropertyToSet(nsCSSPropertyIDSetBorrowedMut, nsCSSPropertyID);
+
 // Style-struct management.
 #define STYLE_STRUCT(name, checkdata_cb)                                       \
   void Gecko_Construct_Default_nsStyle##name(                                  \
     nsStyle##name* ptr,                                                        \
     RawGeckoPresContextBorrowed pres_context);                                 \
   void Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr,                   \
                                          const nsStyle##name* other);          \
   void Gecko_Destroy_nsStyle##name(nsStyle##name* ptr);
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -308,16 +308,17 @@ mod bindings {
             "Keyframe",
             "nsAttrName",
             "nsAttrValue",
             "nsBorderColors",
             "nscolor",
             "nsChangeHint",
             "nsCSSKeyword",
             "nsCSSPropertyID",
+            "nsCSSPropertyIDSet",
             "nsCSSProps",
             "nsCSSRect",
             "nsCSSRect_heap",
             "nsCSSShadowArray",
             "nsCSSValue",
             "nsCSSValueFloatColor",
             "nsCSSValueGradient",
             "nsCSSValueGradientStop",
@@ -529,16 +530,17 @@ mod bindings {
             "ServoBundledURI",
             "ServoElementSnapshot",
             "SheetParsingMode",
             "StyleBasicShape",
             "StyleBasicShapeType",
             "StyleClipPath",
             "nsCSSKeyword",
             "nsCSSPropertyID",
+            "nsCSSPropertyIDSet",
             "nsCSSShadowArray",
             "nsCSSValue",
             "nsCSSValueSharedList",
             "nsChangeHint",
             "nsCursorImage",
             "nsFont",
             "nsIAtom",
             "nsMediaFeature",
@@ -593,16 +595,17 @@ mod bindings {
             "RawServoAnimationValueBorrowedListBorrowed",
         ];
         struct ArrayType {
             cpp_type: &'static str,
             rust_type: &'static str
         }
         let array_types = [
             ArrayType { cpp_type: "uintptr_t", rust_type: "usize" },
+            ArrayType { cpp_type: "nsCSSPropertyID", rust_type: "nsCSSPropertyID" },
         ];
         let servo_nullable_arc_types = [
             "ServoComputedValues",
             "ServoCssRules",
             "RawServoStyleSheet",
             "RawServoDeclarationBlock",
             "RawServoStyleRule",
             "RawServoImportRule",
@@ -623,16 +626,17 @@ mod bindings {
             "RawGeckoDocument",
             "RawServoDeclarationBlockStrong",
             "RawGeckoPresContext",
         ];
         let servo_borrow_types = [
             "nsCSSValue",
             "RawGeckoAnimationValueList",
             "RawGeckoKeyframeList",
+            "nsCSSPropertyIDSet",
         ];
         for &ty in structs_types.iter() {
             builder = builder.hide_type(ty)
                 .raw_line(format!("use gecko_bindings::structs::{};", ty));
             // TODO this is hacky, figure out a better way to do it without
             // hardcoding everything...
             if ty.starts_with("nsStyle") {
                 builder = builder
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -24,16 +24,17 @@ use gecko_bindings::structs::Keyframe;
 use gecko_bindings::structs::ServoBundledURI;
 use gecko_bindings::structs::ServoElementSnapshot;
 use gecko_bindings::structs::SheetParsingMode;
 use gecko_bindings::structs::StyleBasicShape;
 use gecko_bindings::structs::StyleBasicShapeType;
 use gecko_bindings::structs::StyleClipPath;
 use gecko_bindings::structs::nsCSSKeyword;
 use gecko_bindings::structs::nsCSSPropertyID;
+use gecko_bindings::structs::nsCSSPropertyIDSet;
 use gecko_bindings::structs::nsCSSShadowArray;
 use gecko_bindings::structs::nsCSSValue;
 use gecko_bindings::structs::nsCSSValueSharedList;
 use gecko_bindings::structs::nsChangeHint;
 use gecko_bindings::structs::nsCursorImage;
 use gecko_bindings::structs::nsFont;
 use gecko_bindings::structs::nsIAtom;
 use gecko_bindings::structs::nsMediaFeature;
@@ -162,16 +163,17 @@ use gecko_bindings::structs::nsTimingFun
 use gecko_bindings::structs::nscolor;
 use gecko_bindings::structs::nscoord;
 use gecko_bindings::structs::nsresult;
 use gecko_bindings::structs::Loader;
 use gecko_bindings::structs::ServoStyleSheet;
 use gecko_bindings::structs::EffectCompositor_CascadeLevel;
 use gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
 pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<usize>;
+pub type nsTArrayBorrowed_nsCSSPropertyID<'a> = &'a mut ::gecko_bindings::structs::nsTArray<nsCSSPropertyID>;
 pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoComputedValues>;
 pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;
 pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;
 enum ServoComputedValuesVoid { }
 pub struct ServoComputedValues(ServoComputedValuesVoid);
 pub type ServoCssRulesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoCssRules>;
 pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;
 pub type ServoCssRulesBorrowedOrNull<'a> = Option<&'a ServoCssRules>;
@@ -237,16 +239,20 @@ pub type nsCSSValueBorrowedMutOrNull<'a>
 pub type RawGeckoAnimationValueListBorrowed<'a> = &'a RawGeckoAnimationValueList;
 pub type RawGeckoAnimationValueListBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationValueList>;
 pub type RawGeckoAnimationValueListBorrowedMut<'a> = &'a mut RawGeckoAnimationValueList;
 pub type RawGeckoAnimationValueListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationValueList>;
 pub type RawGeckoKeyframeListBorrowed<'a> = &'a RawGeckoKeyframeList;
 pub type RawGeckoKeyframeListBorrowedOrNull<'a> = Option<&'a RawGeckoKeyframeList>;
 pub type RawGeckoKeyframeListBorrowedMut<'a> = &'a mut RawGeckoKeyframeList;
 pub type RawGeckoKeyframeListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoKeyframeList>;
+pub type nsCSSPropertyIDSetBorrowed<'a> = &'a nsCSSPropertyIDSet;
+pub type nsCSSPropertyIDSetBorrowedOrNull<'a> = Option<&'a nsCSSPropertyIDSet>;
+pub type nsCSSPropertyIDSetBorrowedMut<'a> = &'a mut nsCSSPropertyIDSet;
+pub type nsCSSPropertyIDSetBorrowedMutOrNull<'a> = Option<&'a mut nsCSSPropertyIDSet>;
 
 extern "C" {
     pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,
                                       aCapacity: usize, aElementSize: usize);
 }
 extern "C" {
     pub fn Gecko_ClearPODTArray(aArray: *mut ::std::os::raw::c_void,
                                 aElementSize: usize, aElementAlign: usize);
@@ -861,16 +867,20 @@ extern "C" {
 extern "C" {
     pub fn Gecko_nsStyleFont_CopyLangFrom(aFont: *mut nsStyleFont,
                                           aSource: *const nsStyleFont);
 }
 extern "C" {
     pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
 }
 extern "C" {
+    pub fn Gecko_AddPropertyToSet(arg1: nsCSSPropertyIDSetBorrowedMut,
+                                  arg2: nsCSSPropertyID);
+}
+extern "C" {
     pub fn Gecko_Construct_Default_nsStyleFont(ptr: *mut nsStyleFont,
                                                pres_context:
                                                    RawGeckoPresContextBorrowed);
 }
 extern "C" {
     pub fn Gecko_CopyConstruct_nsStyleFont(ptr: *mut nsStyleFont,
                                            other: *const nsStyleFont);
 }
@@ -1311,16 +1321,24 @@ extern "C" {
                                value: *const nsACString_internal,
                                base_url: *const nsACString_internal,
                                base: *mut ThreadSafeURIHolder,
                                referrer: *mut ThreadSafeURIHolder,
                                principal: *mut ThreadSafePrincipalHolder)
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
+    pub fn Servo_GetProperties_Overriding_Animation(arg1:
+                                                        RawGeckoElementBorrowed,
+                                                    arg2:
+                                                        nsTArrayBorrowed_nsCSSPropertyID,
+                                                    arg3:
+                                                        nsCSSPropertyIDSetBorrowedMut);
+}
+extern "C" {
     pub fn Servo_AnimationValues_Populate(arg1:
                                               RawGeckoAnimationValueListBorrowedMut,
                                           arg2:
                                               RawServoDeclarationBlockBorrowed,
                                           arg3: ServoComputedValuesBorrowed,
                                           arg4:
                                               ServoComputedValuesBorrowedOrNull,
                                           arg5: RawGeckoPresContextBorrowed);
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -25159,16 +25159,19 @@ pub mod root {
     #[derive(Debug, Copy, Clone)]
     pub struct nsAttrValueOrString([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct RawServoAnimationValue([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct RawServoStyleSet([u8; 0]);
+    #[repr(C)]
+    #[derive(Debug, Copy, Clone)]
+    pub struct nsCSSPropertyIDSet([u8; 0]);
     pub type RawGeckoNode = root::nsINode;
     pub type RawGeckoElement = root::mozilla::dom::Element;
     pub type RawGeckoDocument = root::nsIDocument;
     pub type RawGeckoPresContext = root::nsPresContext;
     pub type RawGeckoKeyframeList = root::nsTArray<root::mozilla::Keyframe>;
     pub type RawGeckoAnimationValueList =
         root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>;
     pub type RawServoAnimationValueBorrowedList =
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -24515,16 +24515,19 @@ pub mod root {
     #[derive(Debug, Copy, Clone)]
     pub struct nsAttrValueOrString([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct RawServoAnimationValue([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct RawServoStyleSet([u8; 0]);
+    #[repr(C)]
+    #[derive(Debug, Copy, Clone)]
+    pub struct nsCSSPropertyIDSet([u8; 0]);
     pub type RawGeckoNode = root::nsINode;
     pub type RawGeckoElement = root::mozilla::dom::Element;
     pub type RawGeckoDocument = root::nsIDocument;
     pub type RawGeckoPresContext = root::nsPresContext;
     pub type RawGeckoKeyframeList = root::nsTArray<root::mozilla::Keyframe>;
     pub type RawGeckoAnimationValueList =
         root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>;
     pub type RawServoAnimationValueBorrowedList =
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -715,16 +715,27 @@ impl<'a> PropertyDeclarationId<'a> {
     /// Whether a given declaration id is a longhand belonging to this
     /// shorthand.
     pub fn is_longhand_of(&self, shorthand: ShorthandId) -> bool {
         match *self {
             PropertyDeclarationId::Longhand(ref id) => shorthand.longhands().contains(id),
             _ => false,
         }
     }
+
+    /// Returns a nsCSSPropertyID.
+    #[cfg(feature = "gecko")]
+    pub fn to_nscsspropertyid(&self) -> Result<nsCSSPropertyID, ()> {
+        match *self {
+            PropertyDeclarationId::Longhand(id) => {
+                PropertyId::Longhand(id).to_nscsspropertyid()
+            },
+            _ => Err(()),
+        }
+    }
 }
 
 /// Servo's representation of a CSS property, that is, either a longhand, a
 /// shorthand, or a custom property.
 #[derive(Eq, PartialEq, Clone)]
 pub enum PropertyId {
     /// A longhand property.
     Longhand(LonghandId),
@@ -801,17 +812,17 @@ impl PropertyId {
                         Ok(PropertyId::Shorthand(ShorthandId::${property.camel_case}))
                     }
                 % endfor
             % endfor
             _ => Err(())
         }
     }
 
-    /// Returns a property id from Gecko's nsCSSPropertyID.
+    /// Returns a nsCSSPropertyID.
     #[cfg(feature = "gecko")]
     #[allow(non_upper_case_globals)]
     pub fn to_nscsspropertyid(&self) -> Result<nsCSSPropertyID, ()> {
         use gecko_bindings::structs::*;
 
         match *self {
             PropertyId::Longhand(id) => match id {
                 % for property in data.longhands:
--- a/servo/components/style/rule_tree/mod.rs
+++ b/servo/components/style/rule_tree/mod.rs
@@ -3,21 +3,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![allow(unsafe_code)]
 #![deny(missing_docs)]
 
 //! The rule tree.
 
 use arc_ptr_eq;
+#[cfg(feature = "gecko")]
+use gecko_bindings::structs::nsCSSPropertyID;
 #[cfg(feature = "servo")]
 use heapsize::HeapSizeOf;
 use owning_handle::OwningHandle;
 use parking_lot::{RwLock, RwLockReadGuard};
 use properties::{Importance, PropertyDeclarationBlock};
+#[cfg(feature = "gecko")]
+use std::collections::HashSet;
 use std::io::{self, Write};
 use std::ptr;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 use stylesheets::StyleRule;
 use thread_state;
 
 /// The rule tree, the structure servo uses to preserve the results of selector
@@ -622,16 +626,53 @@ impl StrongRuleNode {
 
     /// Get the style source corresponding to this rule node. May return `None`
     /// if it's the root node, which means that the node hasn't matched any
     /// rules.
     pub fn style_source(&self) -> Option<&StyleSource> {
         self.get().source.as_ref()
     }
 
+    /// Get the properties whose CascadeLevel is higher than Animations. We need to to avoid
+    /// overriding those properties by stylo OMTA.
+    #[cfg(feature = "gecko")]
+    pub fn get_properties_overriding_animations(&self) -> HashSet<nsCSSPropertyID> {
+        let mut current = self;
+        let mut result = HashSet::new();
+
+        // Transitions are the only non-!important level overriding animations in the cascade
+        // ordering. They also don't actually override animations, since transitions are
+        // suppressed when both are present. We should skip them explicitly.
+        // Note: Transitions has the highest CascadeLevel, so check it first.
+        if current.get().level == CascadeLevel::Transitions {
+            if current.parent().is_none() {
+                return result;
+            }
+            current = current.parent().unwrap();
+        }
+
+        // walk up until the first less-or-equally specific rule.
+        while current.get().level > CascadeLevel::Animations {
+            if let Some(style_source) = current.style_source() {
+                let guard = style_source.read();
+                for &(ref decl, imp) in &*guard.declarations {
+                    if imp == Importance::Important {
+                        result.insert(decl.id().to_nscsspropertyid().unwrap());
+                    }
+                }
+            }
+
+            if current.parent().is_none() {
+                break;
+            }
+            current = current.parent().unwrap();
+        }
+        result
+    }
+
     /// Get the importance that this rule node represents.
     pub fn importance(&self) -> Importance {
         self.get().level.importance()
     }
 
     /// Get an iterator for this rule node and its ancestors.
     pub fn self_and_ancestors(&self) -> SelfAndAncestors {
         SelfAndAncestors {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -32,26 +32,29 @@ use style::gecko::wrapper::GeckoElement;
 use style::gecko_bindings::bindings;
 use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
 use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
 use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
 use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
 use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
 use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
 use style::gecko_bindings::bindings::{nsACString, nsAString};
+use style::gecko_bindings::bindings::nsCSSPropertyIDSetBorrowedMut;
 use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
+use style::gecko_bindings::bindings::Gecko_AddPropertyToSet;
 use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
 use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
 use style::gecko_bindings::bindings::RawGeckoKeyframeListBorrowedMut;
 use style::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
 use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
 use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
 use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
 use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
 use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
+use style::gecko_bindings::bindings::nsTArrayBorrowed_nsCSSPropertyID;
 use style::gecko_bindings::structs;
 use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
 use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
 use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
 use style::gecko_bindings::structs::Loader;
 use style::gecko_bindings::structs::RawGeckoPresContextOwned;
 use style::gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
 use style::gecko_bindings::structs::ServoStyleSheet;
@@ -792,16 +795,31 @@ pub extern "C" fn Servo_ParseProperty(pr
 
     Arc::new(RwLock::new(PropertyDeclarationBlock {
         declarations: results,
         important_count: 0,
     })).into_strong()
 }
 
 #[no_mangle]
+pub extern "C" fn Servo_GetProperties_Overriding_Animation(element: RawGeckoElementBorrowed,
+                                                           list: nsTArrayBorrowed_nsCSSPropertyID,
+                                                           set: nsCSSPropertyIDSetBorrowedMut) {
+    let element = GeckoElement(element);
+    let elementData = element.borrow_data().unwrap();
+    let overridden = elementData.styles().primary.rules.get_properties_overriding_animations();
+
+    for p in list.iter() {
+        if overridden.contains(p) {
+            unsafe { Gecko_AddPropertyToSet(set, *p) };
+        }
+    }
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_ParseStyleAttribute(data: *const nsACString) -> RawServoDeclarationBlockStrong {
     let value = unsafe { data.as_ref().unwrap().as_str_unchecked() };
     Arc::new(RwLock::new(GeckoElement::parse_style_attribute(value))).into_strong()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_CreateEmpty() -> RawServoDeclarationBlockStrong {
     Arc::new(RwLock::new(PropertyDeclarationBlock { declarations: vec![], important_count: 0 })).into_strong()