Bug 1404181 - Part 8: Add refcounting for clip chains. r?mstange
MozReview-Commit-ID: 9CIwJZ7ssqC
--- a/layout/painting/DisplayItemClipChain.h
+++ b/layout/painting/DisplayItemClipChain.h
@@ -43,16 +43,33 @@ struct DisplayItemClipChain {
const ActiveScrolledRoot* aASR);
static bool Equal(const DisplayItemClipChain* aClip1, const DisplayItemClipChain* aClip2);
static nsCString ToString(const DisplayItemClipChain* aClipChain);
bool HasRoundedCorners() const;
+ void AddRef() {
+ mRefCount++;
+ }
+ void Release() {
+ MOZ_ASSERT(mRefCount > 0);
+ mRefCount--;
+ }
+
+ DisplayItemClipChain(const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aParent)
+ : mClip(aClip)
+ , mASR(aASR)
+ , mParent(aParent)
+ {}
+
+ DisplayItemClipChain() {}
+
DisplayItemClip mClip;
const ActiveScrolledRoot* mASR;
- const DisplayItemClipChain* mParent;
+ RefPtr<const DisplayItemClipChain> mParent;
+ mutable uint32_t mRefCount = 0;
};
} // namespace mozilla
#endif /* DISPLAYITEMCLIPCHAIN_H_ */
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -987,16 +987,17 @@ nsDisplayListBuilder::BeginFrame()
mSyncDecodeImages = false;
}
void
nsDisplayListBuilder::EndFrame()
{
mFrameToAnimatedGeometryRootMap.Clear();
mActiveScrolledRoots.Clear();
+ FreeClipChains();
nsCSSRendering::EndFrameTreesLocked();
}
void
nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
{
mFramesMarkedForDisplay.AppendElement(aFrame);
@@ -1344,16 +1345,37 @@ nsDisplayListBuilder::LeavePresShell(nsI
}
mIsInChromePresContext = pc->IsChrome();
} else {
mCurrentAGR = mRootAGR;
}
}
void
+nsDisplayListBuilder::FreeClipChains()
+{
+ // Iterate the clip chains from newest to oldest (forward
+ // iteration), so that we destroy descendants first which
+ // will drop the ref count on their ancestors.
+ auto it = mClipChainsToDestroy.begin();
+
+ while(it != mClipChainsToDestroy.end()) {
+ DisplayItemClipChain* clip = *it;
+
+ if (!clip->mRefCount) {
+ it = mClipChainsToDestroy.erase(it);
+ clip->DisplayItemClipChain::~DisplayItemClipChain();
+ Destroy(DisplayItemType::TYPE_ZERO, clip);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void
nsDisplayListBuilder::ResetMarkedFramesForDisplayList()
{
// Unmark and pop off the frames marked for display in this pres shell.
uint32_t firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
for (uint32_t i = firstFrameForShell;
i < mFramesMarkedForDisplay.Length(); ++i) {
UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
}
@@ -1442,18 +1464,18 @@ nsDisplayListBuilder::AllocateActiveScro
}
const DisplayItemClipChain*
nsDisplayListBuilder::AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
const ActiveScrolledRoot* aASR,
const DisplayItemClipChain* aParent)
{
void* p = Allocate(sizeof(DisplayItemClipChain), DisplayItemType::TYPE_ZERO);
- DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain{ aClip, aASR, aParent };
- mClipChainsToDestroy.AppendElement(c);
+ DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain(aClip, aASR, aParent);
+ mClipChainsToDestroy.emplace_front(c);
return c;
}
struct ClipChainItem {
DisplayItemClip clip;
const ActiveScrolledRoot* asr;
};
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -776,16 +776,18 @@ public:
* Indicates whether we should synchronously decode images. If true, we decode
* and draw whatever image data has been loaded. If false, we just draw
* whatever has already been decoded.
*/
void SetSyncDecodeImages(bool aSyncDecodeImages) {
mSyncDecodeImages = aSyncDecodeImages;
}
+ void FreeClipChains();
+
/**
* Helper method to generate background painting flags based on the
* information available in the display list builder. Currently only
* accounts for mSyncDecodeImages.
*/
uint32_t GetBackgroundPaintFlags();
/**
@@ -1663,17 +1665,17 @@ private:
nsDisplayItem* mGlassDisplayItem;
// A temporary list that we append scroll info items to while building
// display items for the contents of frames with SVG effects.
// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
// This is a pointer and not a real nsDisplayList value because the
// nsDisplayList class is defined below this class, so we can't use it here.
nsDisplayList* mScrollInfoItemsForHoisting;
nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
- AutoTArray<DisplayItemClipChain*, 128> mClipChainsToDestroy;
+ std::list<DisplayItemClipChain*> mClipChainsToDestroy;
nsTArray<nsDisplayItem*> mTemporaryItems;
const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
nsDisplayListBuilderMode mMode;
ViewID mCurrentScrollParentId;
ViewID mCurrentScrollbarTarget;
uint32_t mCurrentScrollbarFlags;
Preserves3DContext mPreserves3DCtx;
uint32_t mPerspectiveItemIndex;
@@ -2487,17 +2489,17 @@ public:
protected:
nsDisplayItem() = delete;
typedef bool (*PrefFunc)(void);
bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
bool CanUseAdvancedLayer(LayerManager* aManager) const;
nsIFrame* mFrame;
- const DisplayItemClipChain* mClipChain;
+ RefPtr<const DisplayItemClipChain> mClipChain;
const DisplayItemClip* mClip;
RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
// Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
const nsIFrame* mReferenceFrame;
RefPtr<struct AnimatedGeometryRoot> mAnimatedGeometryRoot;
// Result of ToReferenceFrame(mFrame), if mFrame is non-null
nsPoint mToReferenceFrame;
// This is the rectangle that needs to be painted.
@@ -2511,17 +2513,17 @@ protected:
bool mDisableSubpixelAA;
#ifdef MOZ_DUMP_PAINTING
// True if this frame has been painted.
bool mPainted;
#endif
struct {
nsRect mVisibleRect;
- const DisplayItemClipChain* mClipChain;
+ RefPtr<const DisplayItemClipChain> mClipChain;
const DisplayItemClip* mClip;
} mState;
};
/**
* Manages a singly-linked list of display list items.
*
* mSentinel is the sentinel list value, the first value in the null-terminated