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
--- 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