зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1228229 part 8 - Add EffectCompositor::(Maybe)UpdateCascadeResults; r=dbaron
--HG-- extra : rebase_source : 7f87c5a33e153e0815d39b7eb21917f3c034c0d3
This commit is contained in:
Родитель
144a09f431
Коммит
f14f3a2be8
|
@ -12,10 +12,15 @@
|
|||
#include "mozilla/AnimationUtils.h"
|
||||
#include "mozilla/EffectSet.h"
|
||||
#include "mozilla/LayerAnimationInfo.h"
|
||||
#include "AnimationCommon.h" // For AnimationCollection
|
||||
#include "nsAnimationManager.h"
|
||||
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsRuleNode.h" // For nsRuleNode::ComputePropertiesOverridingAnimation
|
||||
#include "nsTArray.h"
|
||||
#include "nsTransitionManager.h"
|
||||
|
||||
using mozilla::dom::Animation;
|
||||
using mozilla::dom::Element;
|
||||
|
@ -110,6 +115,57 @@ EffectCompositor::GetAnimationsForCompositor(const nsIFrame* aFrame,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
|
||||
nsCSSPseudoElements::Type
|
||||
aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||
if (!effects || !effects->CascadeNeedsUpdate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext);
|
||||
|
||||
MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
|
||||
}
|
||||
|
||||
namespace {
|
||||
class EffectCompositeOrderComparator {
|
||||
public:
|
||||
bool Equals(const KeyframeEffectReadOnly* a,
|
||||
const KeyframeEffectReadOnly* b) const
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
bool LessThan(const KeyframeEffectReadOnly* a,
|
||||
const KeyframeEffectReadOnly* b) const
|
||||
{
|
||||
MOZ_ASSERT(a->GetAnimation() && b->GetAnimation());
|
||||
MOZ_ASSERT(
|
||||
Equals(a, b) ||
|
||||
a->GetAnimation()->HasLowerCompositeOrderThan(*b->GetAnimation()) !=
|
||||
b->GetAnimation()->HasLowerCompositeOrderThan(*a->GetAnimation()));
|
||||
return a->GetAnimation()->HasLowerCompositeOrderThan(*b->GetAnimation());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
EffectCompositor::UpdateCascadeResults(Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||
if (!effects) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext);
|
||||
}
|
||||
|
||||
/* static */ Maybe<Pair<Element*, nsCSSPseudoElements::Type>>
|
||||
EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -167,4 +223,116 @@ EffectCompositor::GetOverriddenProperties(nsStyleContext* aStyleContext,
|
|||
aPropertiesOverridden);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
|
||||
Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
MOZ_ASSERT(EffectSet::GetEffectSet(aElement, aPseudoType) == &aEffectSet,
|
||||
"Effect set should correspond to the specified (pseudo-)element");
|
||||
if (aEffectSet.IsEmpty()) {
|
||||
aEffectSet.MarkCascadeUpdated();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a list of effects sorted by composite order.
|
||||
nsTArray<KeyframeEffectReadOnly*> sortedEffectList;
|
||||
for (KeyframeEffectReadOnly* effect : aEffectSet) {
|
||||
sortedEffectList.AppendElement(effect);
|
||||
}
|
||||
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.
|
||||
nsCSSPropertySet overriddenProperties;
|
||||
if (aStyleContext) {
|
||||
GetOverriddenProperties(aStyleContext, overriddenProperties);
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
nsCSSPropertySet animatedProperties;
|
||||
|
||||
// Iterate from highest to lowest composite order.
|
||||
for (KeyframeEffectReadOnly* effect : Reversed(sortedEffectList)) {
|
||||
MOZ_ASSERT(effect->GetAnimation(),
|
||||
"Effects on a target element should have an Animation");
|
||||
bool inEffect = effect->IsInEffect();
|
||||
for (AnimationProperty& prop : effect->Properties()) {
|
||||
|
||||
bool winsInCascade = !animatedProperties.HasProperty(prop.mProperty) &&
|
||||
inEffect;
|
||||
|
||||
// If this property wins in the cascade, add it to the set of animated
|
||||
// properties. We need to do this even if the property is overridden
|
||||
// (in which case we set winsInCascade to false below) since we don't
|
||||
// want to fire transitions on these properties.
|
||||
if (winsInCascade) {
|
||||
animatedProperties.AddProperty(prop.mProperty);
|
||||
}
|
||||
|
||||
// For effects that will be applied to the animations level of the
|
||||
// cascade, we need to check that the property isn't being set by
|
||||
// something with higher priority in the cascade.
|
||||
//
|
||||
// We only do this, however, for properties that can be animated on
|
||||
// the compositor. For properties animated on the main thread the usual
|
||||
// cascade ensures these animations will be correctly overridden.
|
||||
if (winsInCascade &&
|
||||
!effect->GetAnimation()->AppliesToTransitionsLevel() &&
|
||||
overriddenProperties.HasProperty(prop.mProperty)) {
|
||||
winsInCascade = false;
|
||||
}
|
||||
|
||||
if (winsInCascade != prop.mWinsInCascade) {
|
||||
changed = true;
|
||||
}
|
||||
prop.mWinsInCascade = winsInCascade;
|
||||
}
|
||||
}
|
||||
|
||||
aEffectSet.MarkCascadeUpdated();
|
||||
|
||||
// If there is any change in the cascade result, update animations on
|
||||
// layers with the winning animations.
|
||||
nsPresContext* presContext = GetPresContext(aElement);
|
||||
if (changed && presContext) {
|
||||
// We currently unconditionally update both animations and transitions
|
||||
// even if we could, for example, get away with only updating animations.
|
||||
// This is a temporary measure until we unify all animation style updating
|
||||
// under EffectCompositor.
|
||||
AnimationCollection* animations =
|
||||
presContext->AnimationManager()->GetAnimationCollection(aElement,
|
||||
aPseudoType,
|
||||
false);
|
||||
/* don't create */
|
||||
if (animations) {
|
||||
animations->RequestRestyle(AnimationCollection::RestyleType::Layer);
|
||||
}
|
||||
|
||||
AnimationCollection* transitions =
|
||||
presContext->TransitionManager()->GetAnimationCollection(aElement,
|
||||
aPseudoType,
|
||||
false);
|
||||
/* don't create */
|
||||
if (transitions) {
|
||||
transitions->RequestRestyle(AnimationCollection::RestyleType::Layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ nsPresContext*
|
||||
EffectCompositor::GetPresContext(Element* aElement)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
nsIPresShell* shell = nsComputedDOMStyle::GetPresShellForContent(aElement);
|
||||
if (!shell) {
|
||||
return nullptr;
|
||||
}
|
||||
return shell->GetPresContext();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -14,9 +14,13 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
class nsCSSPropertySet;
|
||||
class nsPresContext;
|
||||
class nsStyleContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EffectSet;
|
||||
|
||||
namespace dom {
|
||||
class Animation;
|
||||
class Element;
|
||||
|
@ -32,6 +36,30 @@ public:
|
|||
GetAnimationsForCompositor(const nsIFrame* aFrame,
|
||||
nsCSSProperty aProperty);
|
||||
|
||||
|
||||
// Update animation cascade results for the specified (pseudo-)element
|
||||
// but only if we have marked the cascade as needing an update due a
|
||||
// the change in the set of effects or a change in one of the effects'
|
||||
// "in effect" state.
|
||||
//
|
||||
// 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,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// Update the mWinsInCascade member for each property in effects targetting
|
||||
// the specified (pseudo-)element.
|
||||
//
|
||||
// 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,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// Helper to fetch the corresponding element and pseudo-type from a frame.
|
||||
//
|
||||
// For frames corresponding to pseudo-elements, the returned element is the
|
||||
|
@ -50,6 +78,15 @@ public:
|
|||
static void
|
||||
GetOverriddenProperties(nsStyleContext* aStyleContext,
|
||||
nsCSSPropertySet& aPropertiesOverridden);
|
||||
|
||||
private:
|
||||
static void
|
||||
UpdateCascadeResults(EffectSet& aEffectSet,
|
||||
dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
static nsPresContext* GetPresContext(dom::Element* aElement);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -131,10 +131,7 @@ struct AnimationProperty
|
|||
// For CSS Animations, which are overridden by !important rules in the
|
||||
// cascade, we actually determine this from the CSS cascade
|
||||
// computations, and then use it for OMTA.
|
||||
// **NOTE**: For CSS animations, we only bother setting mWinsInCascade
|
||||
// accurately for properties that we can animate on the compositor.
|
||||
// For other properties, we make it always be true.
|
||||
// **NOTE 2**: This member is not included when comparing AnimationProperty
|
||||
// **NOTE**: This member is not included when comparing AnimationProperty
|
||||
// objects for equality.
|
||||
bool mWinsInCascade = true;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ UNIFIED_SOURCES += [
|
|||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/layout/style',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
Загрузка…
Ссылка в новой задаче