Bug 996796 patch 24 - Use a RestyleTracker for the coalescing in the animation-only style flush (miniflush). r=heycam

This changes the coalescing behavior during the animation-only style
flush by doing tree-based coalescing between the style updates required
by animations and those required by transitions, rather than doing
animations and transitions separately.

Note that both the old and the new code update all
animating/transitioning styles rather than only the throttled styles,
though we should fix that eventually as noted in the FIXME comment in
the code (but only for the existing caller, and not for the new one to
be introduced in bug 960465).

Note that this depends for its correctness on the previous patches to
make the restyling process exact.

The test changes are because the effects of bug 1031688 are changed by
the change in coalescing.  In the old code, we updated transition styles
before animation styles; in the new code we do a single pass over the
tree, which for the relevant test means updating animations on the
parent before transitions on the child, which changes the effects of the
bug.
This commit is contained in:
L. David Baron 2014-08-02 19:37:49 -07:00
parent c802140c48
commit bdab5a4920
3 changed files with 52 additions and 2 deletions

View File

@ -1579,8 +1579,18 @@ RestyleManager::UpdateOnlyAnimationStyles()
transitionManager->SetInAnimationOnlyStyleUpdate(true);
transitionManager->UpdateAllThrottledStyles();
animationManager->UpdateAllThrottledStyles();
RestyleTracker tracker(ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE |
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);
tracker.ProcessRestyles();
transitionManager->SetInAnimationOnlyStyleUpdate(false);
}

View File

@ -166,6 +166,28 @@ CommonAnimationManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
void
CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker)
{
PRCList* next = PR_LIST_HEAD(&mElementCollections);
while (next != &mElementCollections) {
ElementAnimationCollection* collection = static_cast<ElementAnimationCollection*>(next);
next = PR_NEXT_LINK(next);
if (!collection->IsForElement()) {
// We don't support compositor-driven animation of :before/:after
// transitions or animations, so at least skip those.
// FIXME: We'll need to handle this before using this for the
// transitions redesign.
continue;
}
nsRestyleHint rshint = collection->IsForTransitions()
? eRestyle_CSSTransitions : eRestyle_CSSAnimations;
aTracker.AddPendingRestyle(collection->mElement, rshint, nsChangeHint(0));
}
}
/* static */ bool
CommonAnimationManager::ExtractComputedValueForTransition(
nsCSSProperty aProperty,

View File

@ -34,6 +34,7 @@ class nsStyleChangeList;
namespace mozilla {
class RestyleTracker;
class StyleAnimationValue;
struct ElementPropertyTransition;
struct ElementAnimationCollection;
@ -67,6 +68,11 @@ public:
*/
void Disconnect();
// Tell the restyle tracker about all the styles that we're currently
// animating, so that it can update the animation rule for these
// elements.
void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker);
enum FlushFlags {
Can_Throttle,
Cannot_Throttle
@ -529,6 +535,18 @@ struct ElementAnimationCollection : public PRCList
mElementProperty == nsGkAtoms::transitionsProperty;
}
bool IsForTransitions() const {
return mElementProperty == nsGkAtoms::transitionsProperty ||
mElementProperty == nsGkAtoms::transitionsOfBeforeProperty ||
mElementProperty == nsGkAtoms::transitionsOfAfterProperty;
}
bool IsForAnimations() const {
return mElementProperty == nsGkAtoms::animationsProperty ||
mElementProperty == nsGkAtoms::animationsOfBeforeProperty ||
mElementProperty == nsGkAtoms::animationsOfAfterProperty;
}
nsString PseudoElement()
{
if (IsForElement()) {