Bug 1339704 - Part 2 - Filter out unwanted CascadeLevel::Transitions. draft
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 13 Mar 2017 21:09:50 +0800
changeset 499339 a64f1660c20dcc3c25ee52985269d272a2bb5888
parent 499338 e3b231c4f08cd0eb4a0cb94cf8f9d578707c9277
child 499340 74ad6dde55d37e8c6e0197fac518d648d6d7dfd2
push id49366
push userbmo:boris.chiou@gmail.com
push dateWed, 15 Mar 2017 16:11:49 +0000
bugs1339704
milestone55.0a1
Bug 1339704 - Part 2 - Filter out unwanted CascadeLevel::Transitions. We always call TElement::get_animation_rules() for both cascade levels while there are animations or transitions, so we want to handle the following cases: 1. Have both CascadeLevel::Animations and CascadeLevel::Transitions: * We use EffectSet::mPropertiesForAnimationsLevel to filter out CascadeLevel::Transitions because transitions are suppressed when both are presented. 2. Have CascadeLevel::Animations, but don't have CascadeLevel::Transitions: * We also use EffectSet::mPropertiesForAnimationsLevel to filter out the unwanted CascadeLevel::Transitions. 3. Don't Have CascadeLevel::Animations, but have CascadeLevel::Transitions: * EffectSet::mPropertiesForAnimationsLevel doesn't work for this case. In Gecko, mElementsToRestyle can help us to filter out the unwanted CascadeLevel::Animations, However, mElementsToRestyle is cleared in Pre-Traversal, so now we rely on the cascade ordering of transitions to override animations. I think we still need to optimize this eventually. 4. No animations: * EffectSet helps us to check if there is any animations/transitions. Therefore, we need to call MaybeUpdateCascadeResults(), which updates mPropertiesForAnimationsLevel, in Pre-Traversal. MozReview-Commit-ID: IHYw56EX7Ta
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
dom/animation/EffectSet.h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -500,19 +500,20 @@ EffectCompositor::GetServoAnimationRule(
   sortedEffectList.Sort(EffectCompositeOrderComparator());
 
   AnimationRule& animRule = effectSet->AnimationRule(aCascadeLevel);
   animRule.mServo = nullptr;
 
   // If multiple animations affect the same property, animations with higher
   // composite order (priority) override or add or animations with lower
   // priority.
-  // stylo: we don't support animations on compositor now, so propertiesToSkip
-  // is an empty set.
-  const nsCSSPropertyIDSet propertiesToSkip;
+  const nsCSSPropertyIDSet propertiesToSkip =
+    aCascadeLevel == CascadeLevel::Animations
+      ? effectSet->PropertiesForAnimationsLevel().Inverse()
+      : effectSet->PropertiesForAnimationsLevel();
   for (KeyframeEffectReadOnly* effect : sortedEffectList) {
     effect->GetAnimation()->ComposeStyle(animRule, propertiesToSkip);
   }
 
   MOZ_ASSERT(effectSet == EffectSet::GetEffectSet(aElement, aPseudoType),
              "EffectSet should not change while composing style");
 
   return animRule.mServo;
@@ -681,16 +682,32 @@ EffectCompositor::MaybeUpdateCascadeResu
     }
   }
   UpdateCascadeResults(*effects, aElement, aPseudoType, styleContext);
 
   MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
 }
 
 /* static */ void
+EffectCompositor::MaybeUpdateCascadeResults(dom::Element* aElement,
+                                            CSSPseudoElementType aPseudoType)
+{
+  EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
+  MOZ_ASSERT(effects);
+  if (!effects->CascadeNeedsUpdate()) {
+    return;
+  }
+
+  // FIXME: Implement the rule node traversal for stylo in Bug 1334036.
+  UpdateCascadeResults(*effects, aElement, aPseudoType, nullptr);
+
+  MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
+}
+
+/* static */ void
 EffectCompositor::UpdateCascadeResults(Element* aElement,
                                        CSSPseudoElementType aPseudoType,
                                        nsStyleContext* aStyleContext)
 {
   EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
   if (!effects) {
     return;
   }
@@ -832,16 +849,20 @@ EffectCompositor::UpdateCascadeResults(E
 
   // 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.
   nsCSSPropertyIDSet overriddenProperties;
   if (aStyleContext) {
+    // FIXME: Bug 1334036 (OMTA) will implement a FFI to get the properties
+    // overriding animation.
+    MOZ_ASSERT(!aStyleContext->StyleSource().IsServoComputedValues(),
+               "stylo: Not support get properties overriding animation yet.");
     GetOverriddenProperties(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> {
@@ -971,16 +992,18 @@ EffectCompositor::PreTraverse()
       EffectSet* effects =
         EffectSet::GetEffectSet(target.mElement, target.mPseudoType);
       if (!effects) {
         // Drop EffectSets that have been destroyed.
         iter.Remove();
         continue;
       }
 
+      MaybeUpdateCascadeResults(target.mElement, target.mPseudoType);
+
       for (KeyframeEffectReadOnly* effect : *effects) {
         effect->GetAnimation()->WillComposeStyle();
       }
 
       // Remove the element from the list of elements to restyle since we are
       // about to restyle it.
       iter.Remove();
     }
@@ -1013,16 +1036,18 @@ EffectCompositor::PreTraverse(dom::Eleme
       continue;
     }
 
     mPresContext->RestyleManager()->AsServo()->
       PostRestyleEventForAnimations(aElement, eRestyle_Self);
 
     EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
     if (effects) {
+      MaybeUpdateCascadeResults(aElement, pseudoType);
+
       for (KeyframeEffectReadOnly* effect : *effects) {
         effect->GetAnimation()->WillComposeStyle();
       }
     }
 
     elementsToRestyle.Remove(key);
     found = true;
   }
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -191,16 +191,24 @@ public:
   //
   // This method does NOT detect if other styles that apply above the
   // animation level of the cascade have changed.
   static void
   MaybeUpdateCascadeResults(dom::Element* aElement,
                             CSSPseudoElementType aPseudoType,
                             nsStyleContext* aStyleContext);
 
+  // Variant of MaybeUpdateCascadeResults for the Servo backend.
+  // The Servo backend doesn't use an nsStyleContext to get the rule node
+  // to traverse the style tree to find !important rules and instead
+  // gets the rule node from |aElement|.
+  static void
+  MaybeUpdateCascadeResults(dom::Element* aElement,
+                            CSSPseudoElementType aPseudoType);
+
   // Update the mPropertiesWithImportantRules and
   // mPropertiesForAnimationsLevel members of the corresponding EffectSet.
   //
   // This can be expensive so we should only call it if styles that apply
   // above the animation level of the cascade might have changed. For all
   // other cases we should call MaybeUpdateCascadeResults.
   static void
   UpdateCascadeResults(dom::Element* aElement,
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -190,16 +190,20 @@ public:
   nsCSSPropertyIDSet& PropertiesWithImportantRules()
   {
     return mPropertiesWithImportantRules;
   }
   nsCSSPropertyIDSet& PropertiesForAnimationsLevel()
   {
     return mPropertiesForAnimationsLevel;
   }
+  nsCSSPropertyIDSet PropertiesForAnimationsLevel() const
+  {
+    return mPropertiesForAnimationsLevel;
+  }
 
 private:
   static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType);
 
   OwningEffectSet mEffects;
 
   // These style rules contain the style data for currently animating
   // values.  They only match when styling with animation.  When we