From 46448d452da70c72140df0d562b11ed0389906b2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 19 Nov 2012 23:54:41 +1300 Subject: [PATCH] Bug 812776. Reset InlineBackgroundData whenever there are no display lists extant. Frame trees can't change while there are display lists extant. r=mattwoodrow --- layout/base/nsCSSRendering.cpp | 18 ++++++++++++++++-- layout/base/nsCSSRendering.h | 12 +++++++++--- layout/base/nsDisplayList.cpp | 4 +++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 75d00ad2f5d5..dfb34ca04255 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -55,6 +55,8 @@ using namespace mozilla; using namespace mozilla::css; +static int gFrameTreeLockCount = 0; + // To avoid storing this data on nsInlineFrame (bloat) and to avoid // recalculating this for each frame in a continuation (perf), hold // a cache of various coordinate information that we need in order @@ -162,6 +164,8 @@ protected: void SetFrame(nsIFrame* aFrame) { NS_PRECONDITION(aFrame, "Need a frame"); + NS_ASSERTION(gFrameTreeLockCount > 0, + "Can't call this when frame tree is not locked"); if (aFrame == mFrame) { return; @@ -1149,9 +1153,19 @@ nsCSSRendering::FindBackground(nsPresContext* aPresContext, } void -nsCSSRendering::DidPaint() +nsCSSRendering::BeginFrameTreesLocked() { - gInlineBGData->Reset(); + ++gFrameTreeLockCount; +} + +void +nsCSSRendering::EndFrameTreesLocked() +{ + NS_ASSERTION(gFrameTreeLockCount > 0, "Unbalanced EndFrameTreeLocked"); + --gFrameTreeLockCount; + if (gFrameTreeLockCount == 0) { + gInlineBGData->Reset(); + } } void diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index a1f510982615..92ebe0137ad7 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -393,10 +393,16 @@ struct nsCSSRendering { const nsStyleBackground::Layer& aLayer); /** - * Called by the presShell when painting is finished, so we can clear our - * inline background data cache. + * Called when we start creating a display list. The frame tree will not + * change until a matching EndFrameTreeLocked is called. */ - static void DidPaint(); + static void BeginFrameTreesLocked(); + /** + * Called when we've finished using a display list. When all + * BeginFrameTreeLocked calls have been balanced by an EndFrameTreeLocked, + * the frame tree may start changing again. + */ + static void EndFrameTreesLocked(); // Draw a border segment in the table collapsing border model without // beveling corners diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 28c27d16e439..b2200dde8eee 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -472,6 +472,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, } } + nsCSSRendering::BeginFrameTreesLocked(); PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS)); } @@ -654,6 +655,8 @@ nsDisplayListBuilder::~nsDisplayListBuilder() { "All presshells should have been exited"); NS_ASSERTION(!mCurrentTableItem, "No table item should be active"); + nsCSSRendering::EndFrameTreesLocked(); + PL_FreeArenaPool(&mPool); PL_FinishArenaPool(&mPool); MOZ_COUNT_DTOR(nsDisplayListBuilder); @@ -1155,7 +1158,6 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, FrameLayerBuilder::InvalidateAllLayers(layerManager); } - nsCSSRendering::DidPaint(); layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder); }