diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 0bd424cb25af..6b13922e50f7 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -177,8 +177,11 @@ FrameLayerBuilder::DisplayItemData::EndUpdate(nsAutoPtr a { MOZ_RELEASE_ASSERT(mLayer); MOZ_ASSERT(mItem); + MOZ_ASSERT(mGeometry || aGeometry); - mGeometry = aGeometry; + if (aGeometry) { + mGeometry = aGeometry; + } mClip = mItem->GetClip(); mFrameListChanges.Clear(); @@ -4356,7 +4359,7 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) PaintedLayerItemsEntry* entry = mPaintedLayerItems.GetEntry(paintedLayer); - nsAutoPtr geometry(item->AllocateGeometry(mDisplayListBuilder)); + nsAutoPtr geometry; PaintedDisplayItemLayerUserData* layerData = static_cast(aData->mLayer->GetUserData(&gPaintedDisplayItemLayerUserData)); @@ -4364,7 +4367,7 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) const DisplayItemClip& clip = item->GetClip(); - // If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to + // If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to // invalidate both the old and new bounds, otherwise we only want to invalidate the changed areas. // If we do get an invalid rect, then we want to add this on top of the change areas. nsRect invalid; @@ -4372,7 +4375,7 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) bool notifyRenderingChanged = true; if (!aData->mGeometry) { // This item is being added for the first time, invalidate its entire area. - //TODO: We call GetGeometry again in AddPaintedDisplayItem, we should reuse this. + geometry = item->AllocateGeometry(mDisplayListBuilder); combined = clip.ApplyNonRoundedIntersection(geometry->ComputeInvalidationRegion()); #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { @@ -4380,7 +4383,8 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) } #endif } else if (aData->mIsInvalid || (item->IsInvalid(invalid) && invalid.IsEmpty())) { - // Either layout marked item as needing repainting, invalidate the entire old and new areas. + // Layout marked item/frame as needing repainting (without an explicit rect), invalidate the entire old and new areas. + geometry = item->AllocateGeometry(mDisplayListBuilder); combined = aData->mClip.ApplyNonRoundedIntersection(aData->mGeometry->ComputeInvalidationRegion()); combined.MoveBy(shift); combined.Or(combined, clip.ApplyNonRoundedIntersection(geometry->ComputeInvalidationRegion())); @@ -4394,8 +4398,10 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) // repainted. const nsTArray& changedFrames = aData->GetFrameListChanges(); + aData->mGeometry->MoveBy(shift); + item->ComputeInvalidationRegion(mDisplayListBuilder, aData->mGeometry, &combined); - // We have an optimization to cache the drawing background-attachment: fixed canvas + // We have an optimization to cache the drawing of 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 @@ -4404,16 +4410,16 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) // AddOffsetAndComputeDifference is the only thing that will invalidate we skip the // NotifyRenderingChanged call (ComputeInvalidationRegion for background images also calls // NotifyRenderingChanged if anything changes). - if (aData->mGeometry->ComputeInvalidationRegion() == geometry->ComputeInvalidationRegion() && - aData->mClip == clip && invalid.IsEmpty() && changedFrames.Length() == 0) { + if (!combined.IsEmpty()) { + geometry = item->AllocateGeometry(mDisplayListBuilder); + } else if (aData->mClip == clip && invalid.IsEmpty() && changedFrames.Length() == 0) { notifyRenderingChanged = false; } - - aData->mGeometry->MoveBy(shift); - item->ComputeInvalidationRegion(mDisplayListBuilder, aData->mGeometry, &combined); aData->mClip.AddOffsetAndComputeDifference(entry->mCommonClipCount, shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, entry->mLastCommonClipCount, geometry->ComputeInvalidationRegion(), + clip, entry->mLastCommonClipCount, + geometry ? geometry->ComputeInvalidationRegion() : + aData->mGeometry->ComputeInvalidationRegion(), &combined); // Add in any rect that the frame specified