Bug 781516 - Fix invalidation caused by unprocessed merged frames. r=roc

As clip items aren't processed, they have no associated layer entries. This is
a problem when a clip item's underlying frame is the same as one that gets
merged into a container layer, as display-item data will be created, but no
layer entry will be added. This will cause it to be removed on the next
layer-build, and cause a full invalidation.

Fix this by adding an 'mIsMergedFrame' entry to DisplayItemDataEntry and setting
it on all merged frames in BuildContainerLayerFor. This property stops the
entry from being removed when it gets updated.
This commit is contained in:
Chris Lord 2012-08-23 09:30:53 +01:00
parent 3d18bb7445
commit 97efc4771c
2 changed files with 18 additions and 4 deletions

View File

@ -809,7 +809,8 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
FrameProperties props = f->Properties();
DisplayItemDataEntry* newDisplayItems =
builder ? builder->mNewDisplayItemData.GetEntry(f) : nullptr;
if (!newDisplayItems || newDisplayItems->mData.IsEmpty()) {
if (!newDisplayItems || (newDisplayItems->mData.IsEmpty() &&
!newDisplayItems->mIsMergedFrame)) {
// This frame was visible, but isn't anymore.
if (newDisplayItems) {
builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
@ -828,6 +829,7 @@ FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
// Steal the list of display item layers and invalid region
aEntry->mData.SwapElements(newDisplayItems->mData);
aEntry->mInvalidRegion.swap(newDisplayItems->mInvalidRegion);
aEntry->mIsMergedFrame = newDisplayItems->mIsMergedFrame;
// Clear and reset the invalid region now so we can start collecting new
// dirty areas.
SetAndClearInvalidRegion(aEntry);
@ -856,6 +858,7 @@ FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
"mFramesWithLayers out of sync");
newEntry->mData.SwapElements(aEntry->mData);
newEntry->mIsMergedFrame = aEntry->mIsMergedFrame;
props.Set(LayerManagerDataProperty(), data);
return PL_DHASH_REMOVE;
}
@ -2375,6 +2378,10 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
// by multiple container layers. This is cleared and set when iterating
// over the DisplayItemDataEntry's in WillEndTransaction.
entry->mInvalidRegion = thebesLayerInvalidRegion;
// Mark that this is a merged frame so that we retain the display
// item data when updating.
entry->mIsMergedFrame = true;
}
ApplyThebesLayerInvalidation(aBuilder, mergedFrame, nullptr, state,
&currentOffset, transformItem);

View File

@ -466,15 +466,21 @@ protected:
*/
class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
public:
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key), mIsSharingContainerLayer(false) {}
DisplayItemDataEntry(DisplayItemDataEntry &toCopy) :
nsPtrHashKey<nsIFrame>(toCopy.mKey), mIsSharingContainerLayer(toCopy.mIsSharingContainerLayer)
DisplayItemDataEntry(const nsIFrame *key)
: nsPtrHashKey<nsIFrame>(key)
, mIsSharingContainerLayer(false)
, mIsMergedFrame(false)
{}
DisplayItemDataEntry(DisplayItemDataEntry &toCopy)
: nsPtrHashKey<nsIFrame>(toCopy.mKey)
, mIsSharingContainerLayer(toCopy.mIsSharingContainerLayer)
{
// This isn't actually a copy-constructor; notice that it steals toCopy's
// array and invalid region. Be careful.
mData.SwapElements(toCopy.mData);
mInvalidRegion.swap(toCopy.mInvalidRegion);
mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
mIsMergedFrame = toCopy.mIsMergedFrame;
}
bool HasNonEmptyContainerLayer();
@ -483,6 +489,7 @@ protected:
nsRefPtr<RefCountedRegion> mInvalidRegion;
uint32_t mContainerLayerGeneration;
bool mIsSharingContainerLayer;
bool mIsMergedFrame;
enum { ALLOW_MEMMOVE = false };
};