Bug 785333 - Store container layers against merged frames. r=roc

As well as storing the container layer against the underlying frame of the
container item, store it against its merged frames as well. In addition, check
for old container layers against merged frames when building a container layer.

This protects against losing the layer when the underlying frame of a container
item changes to either a new frame or an existing, merged frame.
This commit is contained in:
Chris Lord 2012-08-24 16:17:22 +01:00
parent 5e93fa3cb0
commit 30b4deab7a
2 changed files with 23 additions and 8 deletions

View File

@ -2286,6 +2286,22 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
nsRefPtr<ContainerLayer> containerLayer;
if (aManager == mRetainingManager) {
Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
// If a layer isn't found, see if we can find one for a merged frame. The
// underlying frame can change when a page scrolls, this avoids layer
// recreation in the situation that a new underlying frame is picked for
// a layer.
if (!oldLayer && aContainerItem) {
nsAutoTArray<nsIFrame*,4> mergedFrames;
aContainerItem->GetMergedFrames(&mergedFrames);
for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
oldLayer = GetOldLayerFor(mergedFrames[i], containerDisplayItemKey);
if (oldLayer) {
break;
}
}
}
if (oldLayer) {
NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
@ -2379,6 +2395,13 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
nsIFrame* mergedFrame = mergedFrames[i];
DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(mergedFrame);
if (entry) {
// Append the container layer so we don't regenerate layers when
// the underlying frame of an item changes to one of the existing
// merged frames.
entry->mData.AppendElement(
DisplayItemData(containerLayer, containerDisplayItemKey,
LAYER_ACTIVE, mContainerLayerGeneration));
// Ensure that UpdateDisplayItemDataForFrame recognizes that we
// still have a container layer associated with this frame.
entry->mIsSharingContainerLayer = true;

View File

@ -2701,14 +2701,6 @@ nsDisplayScrollLayer::TryMerge(nsDisplayListBuilder* aBuilder,
props.Set(nsIFrame::ScrollLayerCount(),
reinterpret_cast<void*>(GetScrollLayerCount() - 1));
// Swap frames with the other item before doing MergeFrom.
// XXX - This ensures that the frame associated with a scroll layer after
// merging is the first, rather than the last. This tends to change less,
// ensuring we're more likely to retain the associated gfx layer.
// See Bug 729534 and Bug 731641.
nsIFrame* tmp = mFrame;
mFrame = other->mFrame;
other->mFrame = tmp;
MergeFromTrackingMergedFrames(other);
return true;
}