diff --git a/dom/smil/moz.build b/dom/smil/moz.build index 5f999ae7e49..349ffed416e 100644 --- a/dom/smil/moz.build +++ b/dom/smil/moz.build @@ -67,6 +67,7 @@ FAIL_ON_WARNINGS = True LOCAL_INCLUDES += [ '/dom/base', '/dom/svg', + '/layout/base', '/layout/style', ] diff --git a/dom/smil/nsSMILAnimationController.cpp b/dom/smil/nsSMILAnimationController.cpp index 50b44d16aa1..3c6f9486282 100644 --- a/dom/smil/nsSMILAnimationController.cpp +++ b/dom/smil/nsSMILAnimationController.cpp @@ -14,6 +14,7 @@ #include "nsSMILTimedElement.h" #include #include "mozilla/AutoRestore.h" +#include "RestyleTracker.h" using namespace mozilla; using namespace mozilla::dom; @@ -814,6 +815,36 @@ nsSMILAnimationController::GetTargetIdentifierForAnimation( return true; } +/*static*/ PLDHashOperator +nsSMILAnimationController::AddStyleUpdate(AnimationElementPtrKey* aKey, + void* aData) +{ + SVGAnimationElement* animElement = aKey->GetKey(); + RestyleTracker* restyleTracker = static_cast(aData); + + nsSMILTargetIdentifier key; + if (!GetTargetIdentifierForAnimation(animElement, key)) { + // Something's wrong/missing about animation's target; skip this animation + return PL_DHASH_NEXT; + } + + // mIsCSS true means that the rules are the ones returned from + // Element::GetSMILOverrideStyleRule (via nsSMILCSSProperty objects), + // and mIsCSS false means the rules are nsSMILMappedAttribute objects + // returned from nsSVGElement::GetAnimatedContentStyleRule. + nsRestyleHint rshint = key.mIsCSS ? eRestyle_StyleAttribute + : eRestyle_SVGAttrAnimations; + restyleTracker->AddPendingRestyle(key.mElement, rshint, nsChangeHint(0)); + + return PL_DHASH_NEXT; +} + +void +nsSMILAnimationController::AddStyleUpdatesTo(RestyleTracker& aTracker) +{ + mAnimationElementTable.EnumerateEntries(AddStyleUpdate, &aTracker); +} + //---------------------------------------------------------------------- // Add/remove child time containers diff --git a/dom/smil/nsSMILAnimationController.h b/dom/smil/nsSMILAnimationController.h index 43f4063a698..9cff8a4fb7a 100644 --- a/dom/smil/nsSMILAnimationController.h +++ b/dom/smil/nsSMILAnimationController.h @@ -22,6 +22,7 @@ struct nsSMILTargetIdentifier; class nsIDocument; namespace mozilla { +class RestyleTracker; namespace dom { class SVGAnimationElement; } @@ -105,6 +106,8 @@ public: bool HasRegisteredAnimations() { return mAnimationElementTable.Count() != 0; } + void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker); + protected: ~nsSMILAnimationController(); @@ -175,6 +178,9 @@ protected: static bool GetTargetIdentifierForAnimation( mozilla::dom::SVGAnimationElement* aAnimElem, nsSMILTargetIdentifier& aResult); + static PLDHashOperator + AddStyleUpdate(AnimationElementPtrKey* aKey, void* aData); + // Methods for adding/removing time containers virtual nsresult AddChild(nsSMILTimeContainer& aChild) MOZ_OVERRIDE; virtual void RemoveChild(nsSMILTimeContainer& aChild) MOZ_OVERRIDE; diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index ceac88a34c5..ec9665a707f 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -40,6 +40,7 @@ #include "ActiveLayerTracker.h" #include "nsDisplayList.h" #include "RestyleTrackerInlines.h" +#include "nsSMILAnimationController.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" @@ -1744,10 +1745,25 @@ void RestyleManager::UpdateOnlyAnimationStyles() { TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); - if (mLastUpdateForThrottledAnimations == now) { + bool doCSS = mLastUpdateForThrottledAnimations != now; + mLastUpdateForThrottledAnimations = now; + + bool doSMIL = false; + nsIDocument* document = mPresContext->Document(); + nsSMILAnimationController* animationController = nullptr; + if (document->HasAnimationController()) { + animationController = document->GetAnimationController(); + // FIXME: Ideally, we only want to do this if animation timelines + // have advanced. However, different SMIL animations could be + // getting their time from different outermost SVG elements, so + // finding all of them might be a pain. So this could be optimized + // to set doSMIL to true in fewer cases. + doSMIL = true; + } + + if (!doCSS && !doSMIL) { return; } - mLastUpdateForThrottledAnimations = now; nsTransitionManager* transitionManager = mPresContext->TransitionManager(); nsAnimationManager* animationManager = mPresContext->AnimationManager(); @@ -1758,12 +1774,18 @@ RestyleManager::UpdateOnlyAnimationStyles() ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT); tracker.Init(this); - // FIXME: We should have the transition manager and animation manager - // add only the elements for which animations are currently throttled - // (i.e., animating on the compositor with main-thread style updates - // suppressed). - transitionManager->AddStyleUpdatesTo(tracker); - animationManager->AddStyleUpdatesTo(tracker); + if (doCSS) { + // FIXME: We should have the transition manager and animation manager + // add only the elements for which animations are currently throttled + // (i.e., animating on the compositor with main-thread style updates + // suppressed). + transitionManager->AddStyleUpdatesTo(tracker); + animationManager->AddStyleUpdatesTo(tracker); + } + + if (doSMIL) { + animationController->AddStyleUpdatesTo(tracker); + } ProcessRestyles(tracker);