Bug 1000266. Don't purge the canvas fixed background image cache if we are only scrolling. r=mattwoodrow

Also NotifyRenderingChanged was on the canvas background color item, not the background image item.

Bug 818643 was a problem where the cache didn't get purged enough, but the fix meant we basically always purged the cached and never got to use it, making it useless. It meant that we purged the cache anytime the item has any type of invalidation whatsoever, even if the item would be drawn the same but the layer contents needed to be invalidated so that it would be redrawn (ie due to staying at the same position on screen but a different position in the layer).

This is really hacky, but NotifyRenderingChanged is only observed on one type of display item. So we just isolate the case where the only thing that changed is the offset (due to scrolling) and skip the NotifyRenderingChanged in that case.
This commit is contained in:
Timothy Nikkel 2014-04-23 21:56:15 -05:00
parent a9c57d89e8
commit 58d05a6240
3 changed files with 33 additions and 7 deletions

View File

@ -2686,6 +2686,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
nsRect invalid;
nsRegion combined;
nsPoint shift = aTopLeft - data->mLastAnimatedGeometryRootOrigin;
bool notifyRenderingChanged = true;
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.
@ -2708,6 +2709,21 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
} else {
// Let the display item check for geometry changes and decide what needs to be
// repainted.
// We have an optimization to cache the drawing background-attachment: fixed canvas
// background images so we can scroll and just blit them when they are flattened into
// the same layer as scrolling content. NotifyRenderingChanged is only used to tell
// the canvas bg image item to purge this cache. We want to be careful not to accidentally
// purge the cache if we are just invalidating due to scrolling (ie the background image
// moves on the scrolling layer but it's rendering stays the same) so if
// AddOffsetAndComputeDifference is the only thing that will invalidate we skip the
// NotifyRenderingChanged call (ComputeInvalidationRegion for background images also calls
// NotifyRenderingChanged if anything changes).
if (oldGeometry->ComputeInvalidationRegion() == aGeometry->ComputeInvalidationRegion() &&
*oldClip == aClip && invalid.IsEmpty() && changedFrames.Length() == 0) {
notifyRenderingChanged = false;
}
oldGeometry->MoveBy(shift);
aItem->ComputeInvalidationRegion(mBuilder, oldGeometry, &combined);
oldClip->AddOffsetAndComputeDifference(shift, oldGeometry->ComputeInvalidationRegion(),
@ -2735,7 +2751,9 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
#endif
}
if (!combined.IsEmpty()) {
aItem->NotifyRenderingChanged();
if (notifyRenderingChanged) {
aItem->NotifyRenderingChanged();
}
InvalidatePostTransformRegion(newThebesLayer,
combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
GetTranslationForThebesLayer(newThebesLayer));

View File

@ -2325,18 +2325,26 @@ void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* a
// Positioning area changed in a way that could cause everything to change,
// so invalidate everything (both old and new painting areas).
aInvalidRegion->Or(bounds, geometry->mBounds);
if (positioningArea.Size() != geometry->mPositioningArea.Size()) {
NotifyRenderingChanged();
}
return;
}
if (aBuilder->ShouldSyncDecodeImages()) {
if (mBackgroundStyle &&
!nsCSSRendering::IsBackgroundImageDecodedForStyleContextAndLayer(mBackgroundStyle, mLayer)) {
aInvalidRegion->Or(*aInvalidRegion, bounds);
NotifyRenderingChanged();
}
}
if (!bounds.IsEqualInterior(geometry->mBounds)) {
// Positioning area is unchanged, so invalidate just the change in the
// painting area.
aInvalidRegion->Xor(bounds, geometry->mBounds);
NotifyRenderingChanged();
}
}

View File

@ -170,12 +170,6 @@ public:
ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
}
virtual void NotifyRenderingChanged() MOZ_OVERRIDE
{
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImageDT());
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
@ -199,6 +193,12 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual void NotifyRenderingChanged() MOZ_OVERRIDE
{
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());
mFrame->Properties().Delete(nsIFrame::CachedBackgroundImageDT());
}
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
{
// Put background-attachment:fixed canvas background images in their own