Bug 539356 - Part 25 - Invalidate display items that have a changed clip. r=roc

This commit is contained in:
Matt Woodrow
2012-06-30 15:06:13 +12:00
parent af7876e875
commit 611bfb3dfe
2 changed files with 29 additions and 13 deletions

View File

@@ -333,7 +333,7 @@ protected:
* aItem in that layer. If aNewLayer is a ThebesLayer, invalidates the area of
* aItem in that layer.
*/
void InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer);
void InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer, const FrameLayerBuilder::Clip& aClip);
/**
* Try to determine whether the ThebesLayer at aThebesLayerIndex
* has a single opaque color behind it, over the entire bounds of its visible
@@ -950,7 +950,8 @@ FrameLayerBuilder::HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKe
}
Layer*
FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, nsDisplayItemGeometry** aOldGeometry)
FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey,
nsDisplayItemGeometry** aOldGeometry, Clip** aOldClip)
{
// If we need to build a new layer tree, then just refuse to recycle
// anything.
@@ -968,6 +969,9 @@ FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, ns
if (aOldGeometry) {
*aOldGeometry = array->ElementAt(i).mGeometry.get();
}
if (aOldClip) {
*aOldClip = &array->ElementAt(i).mClip;
}
return layer;
}
}
@@ -1866,14 +1870,14 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
// way, since their ThebesLayer may decide it wants to draw them
// into its buffer even if they're currently covered.
if (itemVisibleRect.IsEmpty() && layerState != LAYER_ACTIVE_EMPTY) {
InvalidateForLayerChange(item, nsnull);
InvalidateForLayerChange(item, nsnull, aClip);
continue;
}
// Just use its layer.
nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
if (!ownLayer) {
InvalidateForLayerChange(item, ownLayer);
InvalidateForLayerChange(item, ownLayer, aClip);
continue;
}
@@ -1932,10 +1936,10 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
NS_ASSERTION(!mNewChildLayers.Contains(ownLayer),
"Layer already in list???");
InvalidateForLayerChange(item, ownLayer);
InvalidateForLayerChange(item, ownLayer, aClip);
mNewChildLayers.AppendElement(ownLayer);
mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nsnull);
mLayerBuilder->AddLayerDisplayItem(ownLayer, item, aClip, layerState, nsnull);
} else {
ThebesLayerData* data =
FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
@@ -1945,7 +1949,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
!nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(
activeScrolledRoot, mBuilder));
InvalidateForLayerChange(item, data->mLayer);
InvalidateForLayerChange(item, data->mLayer, aClip);
mLayerBuilder->AddThebesDisplayItem(data->mLayer, item, aClip,
mContainerFrame,
@@ -1959,15 +1963,16 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
}
void
ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer, const FrameLayerBuilder::Clip& aClip)
{
nsIFrame* f = aItem->GetUnderlyingFrame();
NS_ASSERTION(f, "Display items that render using Thebes must have a frame");
PRUint32 key = aItem->GetPerFrameKey();
NS_ASSERTION(key, "Display items that render using Thebes must have a key");
nsDisplayItemGeometry *oldGeometry = NULL;
FrameLayerBuilder::Clip* oldClip = NULL;
nsAutoPtr<nsDisplayItemGeometry> geometry(aItem->AllocateGeometry(mBuilder));
Layer* oldLayer = mLayerBuilder->GetOldLayerFor(f, key, &oldGeometry);
Layer* oldLayer = mLayerBuilder->GetOldLayerFor(f, key, &oldGeometry, &oldClip);
if (aNewLayer != oldLayer && oldLayer) {
// The item has changed layers.
// Invalidate the bounds in the old layer and new layer.
@@ -2015,17 +2020,23 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
// otherwise we only want to invalidate the changed areas.
nsRegion combined;
if (!oldLayer) {
// This item is being added for the first time, invalidate its entire area.
//TODO: We call GetGeometry again in AddThebesDisplayItem, we should reuse this.
combined = geometry->ComputeInvalidationRegion();
#ifdef DEBUG_INVALIDATIONS
printf("Display item type %s(%p) added to layer %p!\n", aItem->Name(), f, aNewLayer);
#endif
} else if (aItem->IsInvalid()) {
} else if (aItem->IsInvalid() || *oldClip != aClip) {
// Either layout marked item as needing repainting, or the clip on it changed, invalidate
// the entire old and new areas.
// TODO: We could be smarter about handling clip changes here instead of repainting everything.
combined.Or(geometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
#ifdef DEBUG_INVALIDATIONS
printf("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", aItem->Name(), f, aNewLayer);
#endif
} else {
// No obvious differences, so let the display item check for geometry changes and decide what needs to be
// repainted.
ThebesDisplayItemLayerUserData* data =
static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
nsIntPoint paintOffset = GetTranslationForThebesLayer(newThebesLayer);
@@ -2091,7 +2102,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
}
}
AddLayerDisplayItem(aLayer, aItem, aLayerState, tempManager);
AddLayerDisplayItem(aLayer, aItem, aClip, aLayerState, tempManager);
ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
if (entry) {
@@ -2173,6 +2184,7 @@ FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
void
FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
const Clip& aClip,
LayerState aLayerState,
LayerManager* aManager)
{
@@ -2199,6 +2211,7 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
ThebesLayer *t = aLayer->AsThebesLayer();
if (t) {
data->mGeometry = aItem->AllocateGeometry(mDisplayListBuilder);
data->mClip = aClip;
data->mGeometry->mAppUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
ThebesDisplayItemLayerUserData* userData =
static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));