Bug 972713. Part 1: Make all callers of GetAnimatedGeometryRootFor pass a display item so we can stop searching when we reach the item's reference frame. r=mattwoodrow

This guarantees that the animated geometry root for an item is always in the
same display list coordinate system as the frame.

--HG--
extra : rebase_source : 974434342459b76d62d89fdc04c22c518bf0c58b
This commit is contained in:
Robert O'Callahan 2014-02-18 14:26:57 +13:00
Родитель e8ba1b680b
Коммит d34ff747ee
4 изменённых файлов: 42 добавлений и 63 удалений

Просмотреть файл

@ -3098,18 +3098,23 @@ void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
NS_ERROR("nsDisplayWrapList should have been flattened away for painting");
}
/**
* Returns true if all descendant display items can be placed in the same
* ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
* and they all have the expected animated geometry root.
*/
static LayerState
RequiredLayerStateForChildrenInternal(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters,
const nsDisplayList& aList,
nsIFrame* aAnimatedGeometryRoot)
RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters,
const nsDisplayList& aList,
nsIFrame* aExpectedAnimatedGeometryRootForChildren)
{
LayerState result = LAYER_INACTIVE;
for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
nsIFrame* f = i->Frame();
if (result == LAYER_INACTIVE &&
nsLayoutUtils::GetAnimatedGeometryRootFor(f) != aAnimatedGeometryRoot) {
nsLayoutUtils::GetAnimatedGeometryRootFor(i, aBuilder) !=
aExpectedAnimatedGeometryRootForChildren) {
result = LAYER_ACTIVE;
}
@ -3125,8 +3130,8 @@ RequiredLayerStateForChildrenInternal(nsDisplayListBuilder* aBuilder,
nsDisplayList* list = i->GetSameCoordinateSystemChildren();
if (list) {
LayerState childState =
RequiredLayerStateForChildrenInternal(aBuilder, aManager, aParameters, *list,
aAnimatedGeometryRoot);
RequiredLayerStateForChildren(aBuilder, aManager, aParameters, *list,
aExpectedAnimatedGeometryRootForChildren);
if (childState > result) {
result = childState;
}
@ -3136,18 +3141,6 @@ RequiredLayerStateForChildrenInternal(nsDisplayListBuilder* aBuilder,
return result;
}
LayerState
nsDisplayWrapList::RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters,
const nsDisplayList& aList,
nsIFrame* aItemFrame)
{
return RequiredLayerStateForChildrenInternal(
aBuilder, aManager, aParameters, aList,
nsLayoutUtils::GetAnimatedGeometryRootFor(aItemFrame));
}
nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
{
nsRect bounds;
@ -3324,7 +3317,8 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
if (NeedsActiveLayer())
return LAYER_ACTIVE;
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, mFrame);
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList,
nsLayoutUtils::GetAnimatedGeometryRootFor(this, aBuilder));
}
bool
@ -4793,11 +4787,12 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
return LAYER_ACTIVE;
}
return mStoredList.RequiredLayerStateForChildren(aBuilder,
aManager,
aParameters,
*mStoredList.GetChildren(),
mFrame);
// Expect the child display items to have this frame as their animated
// geometry root (since it will be their reference frame). If they have a
// different animated geometry root, we'll make this an active layer so the
// animation can be accelerated.
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
*mStoredList.GetChildren(), Frame());
}
bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,

Просмотреть файл

@ -2618,17 +2618,6 @@ public:
return nullptr;
}
/**
* Returns true if all descendant display items can be placed in the same
* ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
* and they all have the given aAnimatedGeometryRoot.
*/
static LayerState RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters,
const nsDisplayList& aList,
nsIFrame* aItemFrame);
protected:
nsDisplayWrapList() {}

Просмотреть файл

@ -1529,23 +1529,24 @@ nsLayoutUtils::IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, nsRect* aDis
return ViewportHasDisplayPort(aFrame->PresContext(), aDisplayPort);
}
nsIFrame*
nsLayoutUtils::GetAnimatedGeometryRootFor(nsIFrame* aFrame,
const nsIFrame* aStopAtAncestor)
static nsIFrame*
GetAnimatedGeometryRootForFrame(nsIFrame* aFrame,
const nsIFrame* aStopAtAncestor)
{
nsIFrame* f = aFrame;
nsIFrame* stickyFrame = nullptr;
while (f != aStopAtAncestor) {
if (IsPopup(f))
if (nsLayoutUtils::IsPopup(f))
break;
if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(f))
break;
if (!f->GetParent() && ViewportHasDisplayPort(f->PresContext())) {
if (!f->GetParent() &&
nsLayoutUtils::ViewportHasDisplayPort(f->PresContext())) {
// Viewport frames in a display port need to be animated geometry roots
// for background-attachment:fixed elements.
break;
}
nsIFrame* parent = GetCrossDocParentFrame(f);
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(f);
if (!parent)
break;
nsIAtom* parentType = parent->GetType();
@ -1576,7 +1577,7 @@ nsLayoutUtils::GetAnimatedGeometryRootFor(nsIFrame* aFrame,
}
}
// Fixed-pos frames are parented by the viewport frame, which has no parent
if (IsFixedPosFrameInDisplayPort(f)) {
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(f)) {
return f;
}
f = parent;
@ -1593,7 +1594,7 @@ nsLayoutUtils::GetAnimatedGeometryRootFor(nsDisplayItem* aItem,
nsDisplayScrollLayer* scrollLayerItem =
static_cast<nsDisplayScrollLayer*>(aItem);
nsIFrame* scrolledFrame = scrollLayerItem->GetScrolledFrame();
return nsLayoutUtils::GetAnimatedGeometryRootFor(scrolledFrame,
return GetAnimatedGeometryRootForFrame(scrolledFrame,
aBuilder->FindReferenceFrameFor(scrolledFrame));
}
if (aItem->ShouldFixToViewport(aBuilder)) {
@ -1604,10 +1605,10 @@ nsLayoutUtils::GetAnimatedGeometryRootFor(nsDisplayItem* aItem,
nsIFrame* viewportFrame =
nsLayoutUtils::GetClosestFrameOfType(f, nsGkAtoms::viewportFrame);
NS_ASSERTION(viewportFrame, "no viewport???");
return nsLayoutUtils::GetAnimatedGeometryRootFor(viewportFrame,
return GetAnimatedGeometryRootForFrame(viewportFrame,
aBuilder->FindReferenceFrameFor(viewportFrame));
}
return nsLayoutUtils::GetAnimatedGeometryRootFor(f, aItem->ReferenceFrame());
return GetAnimatedGeometryRootForFrame(f, aItem->ReferenceFrame());
}
// static

Просмотреть файл

@ -474,28 +474,22 @@ public:
nsRect* aDisplayPort = nullptr);
/**
* Finds the nearest ancestor frame that is considered to have (or will have)
* "animated geometry". For example the scrolled frames of scrollframes which
* are actively being scrolled fall into this category. Frames with certain
* CSS properties that are being animated (e.g. 'left'/'top' etc) are also
* placed in this category. Frames with animated CSS transforms are not
* put in this category because they can be handled directly by
* nsDisplayTransform.
* Stop searching at aStopAtAncestor if there is no such ancestor before it
* in the ancestor chain.
* Finds the nearest ancestor frame to aItem that is considered to have (or
* will have) "animated geometry". For example the scrolled frames of
* scrollframes which are actively being scrolled fall into this category.
* Frames with certain CSS properties that are being animated (e.g.
* 'left'/'top' etc) are also placed in this category.
* Frames with different active geometry roots are in different ThebesLayers,
* so that we can animate the geometry root by changing its transform (either
* on the main thread or in the compositor).
* This function is idempotent: a frame returned by GetAnimatedGeometryRootFor
* is always returned again if you pass it to GetAnimatedGeometryRootFor.
* The animated geometry root is required to be a descendant (or equal to)
* aItem's ReferenceFrame(), which means that we will fall back to
* returning aItem->ReferenceFrame() when we can't find another animated
* geometry root.
*/
static nsIFrame* GetAnimatedGeometryRootFor(nsIFrame* aFrame,
const nsIFrame* aStopAtAncestor = nullptr);
static nsIFrame* GetAnimatedGeometryRootFor(nsDisplayItem* aItem,
nsDisplayListBuilder* aBuilder);
/**
* GetScrollableFrameFor returns the scrollable frame for a scrolled frame
*/