From 2b6a60fb3a183a0195081e87343b4905fc5c9c35 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Dec 2014 09:40:01 -0500 Subject: [PATCH] Bug 1098654 - Add a cache for animated geometry roots on the display list builder. r=roc --- layout/base/nsDisplayList.cpp | 26 ++++++++++++++++++++++++-- layout/base/nsDisplayList.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 9e021d45e3b..46e02da2242 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1182,12 +1182,28 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParen return false; } +bool +nsDisplayListBuilder::GetCachedAnimatedGeometryRoot(const nsIFrame* aFrame, + const nsIFrame* aStopAtAncestor, + nsIFrame** aOutResult) +{ + AnimatedGeometryRootLookup lookup(aFrame, aStopAtAncestor); + return mAnimatedGeometryRootCache.Get(lookup, aOutResult); +} + static nsIFrame* ComputeAnimatedGeometryRootFor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - const nsIFrame* aStopAtAncestor = nullptr) + const nsIFrame* aStopAtAncestor = nullptr, + bool aUseCache = false) { nsIFrame* cursor = aFrame; while (cursor != aStopAtAncestor) { + if (aUseCache) { + nsIFrame* result; + if (aBuilder->GetCachedAnimatedGeometryRoot(cursor, aStopAtAncestor, &result)) { + return result; + } + } nsIFrame* next; if (aBuilder->IsAnimatedGeometryRoot(cursor, &next)) return cursor; @@ -1202,13 +1218,19 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsIFrame* aFrame, const nsIFra if (aFrame == mCurrentFrame) { return mCurrentAnimatedGeometryRoot; } - return ComputeAnimatedGeometryRootFor(this, aFrame, aStopAtAncestor); + + nsIFrame* result = ComputeAnimatedGeometryRootFor(this, aFrame, aStopAtAncestor, true); + AnimatedGeometryRootLookup lookup(aFrame, aStopAtAncestor); + mAnimatedGeometryRootCache.Put(lookup, result); + return result; } void nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot() { mCurrentAnimatedGeometryRoot = ComputeAnimatedGeometryRootFor(this, const_cast(mCurrentFrame)); + AnimatedGeometryRootLookup lookup(mCurrentFrame, nullptr); + mAnimatedGeometryRootCache.Put(lookup, mCurrentAnimatedGeometryRoot); } void diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index e72544fdd31..123b6e04dc6 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -795,6 +795,15 @@ public: bool IsInWillChangeBudget(nsIFrame* aFrame) const; + /** + * Look up the cached animated geometry root for aFrame subject to + * aStopAtAncestor. Store the nsIFrame* result into *aOutResult, and return + * true if the cache was hit. Return false if the cache was not hit. + */ + bool GetCachedAnimatedGeometryRoot(const nsIFrame* aFrame, + const nsIFrame* aStopAtAncestor, + nsIFrame** aOutResult); + private: void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, const nsRect& aDirtyRect); @@ -840,6 +849,28 @@ private: nsPoint mCurrentOffsetToReferenceFrame; // The animated geometry root for mCurrentFrame. nsIFrame* mCurrentAnimatedGeometryRoot; + + struct AnimatedGeometryRootLookup { + const nsIFrame* mFrame; + const nsIFrame* mStopAtFrame; + + AnimatedGeometryRootLookup(const nsIFrame* aFrame, const nsIFrame* aStopAtFrame) + : mFrame(aFrame) + , mStopAtFrame(aStopAtFrame) + { + } + + PLDHashNumber Hash() const { + return mozilla::HashBytes(this, sizeof(this)); + } + + bool operator==(const AnimatedGeometryRootLookup& aOther) const { + return mFrame == aOther.mFrame && mStopAtFrame == aOther.mStopAtFrame; + } + }; + // Cache for storing animated geometry roots for arbitrary frames + nsDataHashtable, nsIFrame*> + mAnimatedGeometryRootCache; // will-change budget tracker nsDataHashtable, DocumentWillChangeBudget> mWillChangeBudget;