Bug 828173 patch 4: Expose AddAnimationsAndTransitionsToLayer and allow it to be called from style change handling. r=mattwoodrow

This commit is contained in:
L. David Baron 2014-03-04 20:13:21 -08:00
parent 1c6ed806fe
commit 143d4b266e
2 changed files with 70 additions and 26 deletions

View File

@ -314,7 +314,7 @@ ToTimingFunction(css::ComputedTimingFunction& aCTF)
static void
AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
ElementAnimation* ea, Layer* aLayer,
AnimationData& aData)
AnimationData& aData, bool aPending)
{
NS_ASSERTION(aLayer->AsContainerLayer(), "Should only animate ContainerLayer");
nsStyleContext* styleContext = aFrame->StyleContext();
@ -323,7 +323,8 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
// all data passed directly to the compositor should be in css pixels
float scale = nsDeviceContext::AppUnitsPerCSSPixel();
Animation* animation = aLayer->AddAnimation();
Animation* animation = aPending ? aLayer->AddAnimationForNextTransaction()
: aLayer->AddAnimation();
animation->startTime() = ea->mStartTime + ea->mDelay;
animation->duration() = ea->mIterationDuration;
@ -367,15 +368,31 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
}
}
static void
AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem, nsCSSProperty aProperty)
/* static */ void
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
nsIFrame* aFrame,
nsCSSProperty aProperty)
{
aLayer->ClearAnimations();
// This function can be called in two ways: from
// nsDisplay*::BuildLayer while constructing a layer (with all
// pointers non-null), or from RestyleManager's handling of
// UpdateOpacityLayer/UpdateTransformLayer hints.
MOZ_ASSERT(!aBuilder == !aItem,
"should only be called in two configurations, with both "
"aBuilder and aItem, or with neither");
MOZ_ASSERT(!aItem || aFrame == aItem->Frame(), "frame mismatch");
nsIFrame* frame = aItem->Frame();
bool pending = !aBuilder;
nsIContent* content = frame->GetContent();
if (pending) {
aLayer->ClearAnimationsForNextTransaction();
} else {
aLayer->ClearAnimations();
}
nsIContent* content = aFrame->GetContent();
if (!content) {
return;
}
@ -390,43 +407,54 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder
}
// If the frame is not prerendered, bail out.
if (!aItem->CanUseAsyncAnimations(aBuilder)) {
// Do this check only during layer construction; during updating the
// caller is required to check it appropriately.
if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) {
// AnimationManager or TransitionManager need to know that we refused to
// run this animation asynchronously so that they will not throttle the
// main thread animation.
frame->Properties().Set(nsIFrame::RefusedAsyncAnimation(),
aFrame->Properties().Set(nsIFrame::RefusedAsyncAnimation(),
reinterpret_cast<void*>(intptr_t(true)));
// We need to schedule another refresh driver run so that AnimationManager
// or TransitionManager get a chance to unthrottle the animation.
frame->SchedulePaint();
aFrame->SchedulePaint();
return;
}
mozilla::TimeStamp currentTime =
frame->PresContext()->RefreshDriver()->MostRecentRefresh();
aFrame->PresContext()->RefreshDriver()->MostRecentRefresh();
AnimationData data;
if (aProperty == eCSSProperty_transform) {
nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(frame);
nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
// all data passed directly to the compositor should be in css pixels
float scale = nsDeviceContext::AppUnitsPerCSSPixel();
gfxPoint3D offsetToTransformOrigin =
nsDisplayTransform::GetDeltaToTransformOrigin(frame, scale, &bounds);
nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds);
gfxPoint3D offsetToPerspectiveOrigin =
nsDisplayTransform::GetDeltaToPerspectiveOrigin(frame, scale);
nsDisplayTransform::GetDeltaToPerspectiveOrigin(aFrame, scale);
nscoord perspective = 0.0;
nsStyleContext* parentStyleContext = frame->StyleContext()->GetParent();
nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent();
if (parentStyleContext) {
const nsStyleDisplay* disp = parentStyleContext->StyleDisplay();
if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
perspective = disp->mChildPerspective.GetCoordValue();
}
}
nsPoint origin = aItem->ToReferenceFrame();
nsPoint origin;
if (aItem) {
origin = aItem->ToReferenceFrame();
} else {
// transform display items used a reference frame computed from
// their GetTransformRootFrame().
nsIFrame* referenceFrame =
nsLayoutUtils::GetReferenceFrame(GetTransformRootFrame(aFrame));
origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
}
data = TransformData(origin, offsetToTransformOrigin,
offsetToPerspectiveOrigin, bounds, perspective,
frame->PresContext()->AppUnitsPerDevPixel());
aFrame->PresContext()->AppUnitsPerDevPixel());
} else if (aProperty == eCSSProperty_opacity) {
data = null_t();
}
@ -458,8 +486,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder
segment.mToValue = pt->mEndValue;
segment.mTimingFunction = pt->mTimingFunction;
AddAnimationsForProperty(frame, aProperty, &anim,
aLayer, data);
AddAnimationsForProperty(aFrame, aProperty, &anim,
aLayer, data, pending);
pt->mIsRunningOnCompositor = true;
}
@ -473,8 +501,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder
anim->IsRunningAt(currentTime))) {
continue;
}
AddAnimationsForProperty(frame, aProperty, anim,
aLayer, data);
AddAnimationsForProperty(aFrame, aProperty, anim,
aLayer, data, pending);
}
aLayer->SetAnimationGeneration(ea->mAnimationGeneration);
}
@ -3195,8 +3223,9 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
return nullptr;
container->SetOpacity(mFrame->StyleDisplay()->mOpacity);
AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, eCSSProperty_opacity);
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, mFrame,
eCSSProperty_opacity);
return container.forget();
}
@ -4662,8 +4691,9 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D);
}
AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, eCSSProperty_transform);
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, mFrame,
eCSSProperty_transform);
if (ShouldPrerenderTransformedContent(aBuilder, mFrame, false)) {
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
/*the value is irrelevant*/nullptr);

View File

@ -39,6 +39,7 @@ class nsDisplayLayerEventRegions;
namespace mozilla {
namespace layers {
class Layer;
class ImageLayer;
class ImageContainer;
} //namepsace
@ -112,6 +113,7 @@ public:
typedef mozilla::DisplayItemClip DisplayItemClip;
typedef mozilla::DisplayListClipState DisplayListClipState;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
typedef mozilla::layers::Layer Layer;
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
@ -481,6 +483,18 @@ public:
*/
const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal);
/**
* Transfer off main thread animations to the layer. May be called
* with aBuilder and aItem both null, but only if the caller has
* already checked that off main thread animations should be sent to
* the layer. When they are both null, the animations are added to
* the layer as pending animations.
*/
static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
nsIFrame* aFrame,
nsCSSProperty aProperty);
/**
* A helper class to temporarily set the value of
* mIsAtRootOfPseudoStackingContext, and temporarily