Bug 1098654 - Add a cache for animated geometry roots on the display list builder. r=roc

This commit is contained in:
Kartikaya Gupta 2014-12-30 09:40:01 -05:00
parent b492715b7d
commit 2b6a60fb3a
2 changed files with 55 additions and 2 deletions

View File

@ -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<nsIFrame *>(mCurrentFrame));
AnimatedGeometryRootLookup lookup(mCurrentFrame, nullptr);
mAnimatedGeometryRootCache.Put(lookup, mCurrentAnimatedGeometryRoot);
}
void

View File

@ -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<nsGenericHashKey<AnimatedGeometryRootLookup>, nsIFrame*>
mAnimatedGeometryRootCache;
// will-change budget tracker
nsDataHashtable<nsPtrHashKey<nsPresContext>, DocumentWillChangeBudget>
mWillChangeBudget;