Bug 1240073 - Use the transformed frame as the AGR for active transform so that FrameLayerBuilder knows that they can move independently. r=tnikkel

This commit is contained in:
Matt Woodrow 2016-01-21 17:02:31 +13:00
parent e89c657a60
commit 48fb25be6f
2 changed files with 47 additions and 11 deletions

View File

@ -5050,6 +5050,8 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(aTransformGetter)
, mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
, mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
@ -5064,7 +5066,6 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
void
nsDisplayTransform::SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder)
{
mAnimatedGeometryRootForChildren = mAnimatedGeometryRoot;
if (mFrame == aBuilder->RootReferenceFrame()) {
return;
}
@ -5086,7 +5087,15 @@ nsDisplayTransform::SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder)
// frame, which is our AGR, not the parent AGR.
mAnimatedGeometryRoot = mAnimatedGeometryRootForChildren;
} else if (mAnimatedGeometryRoot->mParentAGR) {
mAnimatedGeometryRoot = mAnimatedGeometryRoot->mParentAGR;
mAnimatedGeometryRootForScrollMetadata = mAnimatedGeometryRoot->mParentAGR;
if (!MayBeAnimated(aBuilder)) {
// If we're an animated transform then we want the same AGR as our children
// so that FrameLayerBuilder knows that this layer moves with the transform
// and won't compute occlusions. If we're not animated then use our parent
// AGR so that inactive transform layers can go in the same PaintedLayer as
// surrounding content.
mAnimatedGeometryRoot = mAnimatedGeometryRoot->mParentAGR;
}
}
mVisibleRect = aBuilder->GetDirtyRect() + mToReferenceFrame;
}
@ -5118,6 +5127,8 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(nullptr)
, mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
, mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
@ -5138,6 +5149,8 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aItem)
, mTransformGetter(nullptr)
, mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
, mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
@ -5159,6 +5172,8 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
, mStoredList(aBuilder, aFrame, aList)
, mTransform(aTransform)
, mTransformGetter(nullptr)
, mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
, mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
@ -5777,8 +5792,13 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
this, mFrame,
eCSSProperty_transform);
if (ShouldPrerender(aBuilder)) {
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
/*the value is irrelevant*/nullptr);
if (MayBeAnimated(aBuilder)) {
// Only allow async updates to the transform if we're an animated layer, since that's what
// triggers us to set the correct AGR in the constructor and makes sure FrameLayerBuilder
// won't compute occlusions for this layer.
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
/*the value is irrelevant*/nullptr);
}
container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_MAY_CHANGE_TRANSFORM);
} else {
container->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
@ -5787,6 +5807,21 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
return container.forget();
}
bool
nsDisplayTransform::MayBeAnimated(nsDisplayListBuilder* aBuilder)
{
// Here we check if the *post-transform* bounds of this item are big enough
// to justify an active layer.
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_transform) &&
!IsItemTooSmallForActiveLayer(this))
return true;
if (EffectCompositor::HasAnimationsForCompositor(mFrame,
eCSSProperty_transform)) {
return true;
}
return false;
}
nsDisplayItem::LayerState
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@ -5798,13 +5833,7 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
mIsTransformSeparator) {
return LAYER_ACTIVE_FORCE;
}
// Here we check if the *post-transform* bounds of this item are big enough
// to justify an active layer.
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_transform) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (EffectCompositor::HasAnimationsForCompositor(mFrame,
eCSSProperty_transform)) {
if (MayBeAnimated(aBuilder)) {
return LAYER_ACTIVE;
}

View File

@ -3956,6 +3956,10 @@ public:
return nsDisplayItem::ReferenceFrameForChildren();
}
AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
return mAnimatedGeometryRootForScrollMetadata;
}
virtual const nsRect& GetVisibleRectForChildren() const override
{
return mChildrenVisibleRect;
@ -4103,6 +4107,8 @@ public:
bool aLogAnimations = false);
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
bool MayBeAnimated(nsDisplayListBuilder* aBuilder);
/**
* This will return if it's possible for this element to be prerendered.
* This should never return false if we're going to prerender.
@ -4192,6 +4198,7 @@ private:
Matrix4x4 mTransformPreserves3D;
ComputeTransformFunction mTransformGetter;
AnimatedGeometryRoot* mAnimatedGeometryRootForChildren;
AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
nsRect mChildrenVisibleRect;
uint32_t mIndex;
nsRect mBounds;