mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 1404181 - Part 1: Make AnimatedGeometryRoot/ActiveScrolledRoot retained and refcounted on the heap. r=mstange
MozReview-Commit-ID: Gcm5pOAdCeI --HG-- extra : rebase_source : c5b3df4e683b98f15fefa65b7c9b10bd47acb7ed
This commit is contained in:
parent
2791600a48
commit
1f861fe60c
@ -350,6 +350,11 @@ private:
|
||||
public:
|
||||
bool IsScrollbarOnRight() const;
|
||||
bool IsScrollingActive(nsDisplayListBuilder* aBuilder) const;
|
||||
bool MayBeAsynchronouslyScrolled() const {
|
||||
// If this is true, then we'll build an ASR, and that's what we want
|
||||
// to know I think.
|
||||
return mWillBuildScrollableLayer;
|
||||
}
|
||||
bool IsMaybeScrollingActive() const;
|
||||
bool IsProcessingAsyncScroll() const {
|
||||
return mAsyncScroll != nullptr || mAsyncSmoothMSDScroll != nullptr;
|
||||
@ -893,6 +898,9 @@ public:
|
||||
virtual bool IsMaybeScrollingActive() const override {
|
||||
return mHelper.IsMaybeScrollingActive();
|
||||
}
|
||||
virtual bool MayBeAsynchronouslyScrolled() override {
|
||||
return mHelper.MayBeAsynchronouslyScrolled();
|
||||
}
|
||||
virtual bool IsProcessingAsyncScroll() override {
|
||||
return mHelper.IsProcessingAsyncScroll();
|
||||
}
|
||||
@ -1330,6 +1338,9 @@ public:
|
||||
virtual bool IsMaybeScrollingActive() const override {
|
||||
return mHelper.IsMaybeScrollingActive();
|
||||
}
|
||||
virtual bool MayBeAsynchronouslyScrolled() override {
|
||||
return mHelper.MayBeAsynchronouslyScrolled();
|
||||
}
|
||||
virtual bool IsProcessingAsyncScroll() override {
|
||||
return mHelper.IsProcessingAsyncScroll();
|
||||
}
|
||||
|
@ -315,6 +315,13 @@ public:
|
||||
* expectation that scrolling is going to happen.
|
||||
*/
|
||||
virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this scroll frame might be scrolled
|
||||
* asynchronously by the compositor.
|
||||
*/
|
||||
virtual bool MayBeAsynchronouslyScrolled() = 0;
|
||||
|
||||
/**
|
||||
* Same as the above except doesn't take into account will-change budget,
|
||||
* which means that it can be called during display list building.
|
||||
|
@ -124,12 +124,6 @@ SpammyLayoutWarningsEnabled()
|
||||
}
|
||||
#endif
|
||||
|
||||
void*
|
||||
AnimatedGeometryRoot::operator new(size_t aSize, nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return aBuilder->Allocate(aSize, DisplayItemType::TYPE_ZERO);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ActiveScrolledRoot::IsAncestor(const ActiveScrolledRoot* aAncestor,
|
||||
const ActiveScrolledRoot* aDescendant)
|
||||
@ -924,8 +918,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mCurrentContainerASR(nullptr),
|
||||
mCurrentFrame(aReferenceFrame),
|
||||
mCurrentReferenceFrame(aReferenceFrame),
|
||||
mCurrentAGR(&mRootAGR),
|
||||
mRootAGR(aReferenceFrame, nullptr),
|
||||
mRootAGR(AnimatedGeometryRoot::CreateAGRForFrame(aReferenceFrame, nullptr, true, false)),
|
||||
mCurrentAGR(mRootAGR),
|
||||
mUsedAGRBudget(0),
|
||||
mDirtyRect(-1,-1,-1,-1),
|
||||
mGlassDisplayItem(nullptr),
|
||||
@ -941,6 +935,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mIsBuildingScrollbar(false),
|
||||
mCurrentScrollbarWillHaveLayer(false),
|
||||
mBuildCaret(aBuildCaret),
|
||||
mRetainingDisplayList(false),
|
||||
mIgnoreSuppression(false),
|
||||
mIsAtRootOfPseudoStackingContext(false),
|
||||
mIncludeAllOutOfFlows(false),
|
||||
@ -983,8 +978,8 @@ void
|
||||
nsDisplayListBuilder::BeginFrame()
|
||||
{
|
||||
nsCSSRendering::BeginFrameTreesLocked();
|
||||
mCurrentAGR = &mRootAGR;
|
||||
mFrameToAnimatedGeometryRootMap.Put(mReferenceFrame, &mRootAGR);
|
||||
mCurrentAGR = mRootAGR;
|
||||
mFrameToAnimatedGeometryRootMap.Put(mReferenceFrame, mRootAGR);
|
||||
|
||||
mIsPaintingToWindow = false;
|
||||
mIgnoreSuppression = false;
|
||||
@ -996,6 +991,7 @@ void
|
||||
nsDisplayListBuilder::EndFrame()
|
||||
{
|
||||
mFrameToAnimatedGeometryRootMap.Clear();
|
||||
mActiveScrolledRoots.Clear();
|
||||
|
||||
nsCSSRendering::EndFrameTreesLocked();
|
||||
}
|
||||
@ -1020,22 +1016,25 @@ bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(nsDisplayItem* a
|
||||
|
||||
AnimatedGeometryRoot*
|
||||
nsDisplayListBuilder::WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
|
||||
bool aIsAsync,
|
||||
AnimatedGeometryRoot* aParent /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot) == AGR_YES);
|
||||
DebugOnly<bool> dummy;
|
||||
MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot, dummy) == AGR_YES);
|
||||
|
||||
AnimatedGeometryRoot* result = nullptr;
|
||||
RefPtr<AnimatedGeometryRoot> result;
|
||||
if (!mFrameToAnimatedGeometryRootMap.Get(aAnimatedGeometryRoot, &result)) {
|
||||
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(RootReferenceFrame(), aAnimatedGeometryRoot));
|
||||
AnimatedGeometryRoot* parent = aParent;
|
||||
RefPtr<AnimatedGeometryRoot> parent = aParent;
|
||||
if (!parent) {
|
||||
nsIFrame* parentFrame = nsLayoutUtils::GetCrossDocParentFrame(aAnimatedGeometryRoot);
|
||||
if (parentFrame) {
|
||||
nsIFrame* parentAGRFrame = FindAnimatedGeometryRootFrameFor(parentFrame);
|
||||
parent = WrapAGRForFrame(parentAGRFrame);
|
||||
bool isAsync;
|
||||
nsIFrame* parentAGRFrame = FindAnimatedGeometryRootFrameFor(parentFrame, isAsync);
|
||||
parent = WrapAGRForFrame(parentAGRFrame, isAsync);
|
||||
}
|
||||
}
|
||||
result = new (this) AnimatedGeometryRoot(aAnimatedGeometryRoot, parent);
|
||||
result = AnimatedGeometryRoot::CreateAGRForFrame(aAnimatedGeometryRoot, parent, aIsAsync, IsRetainingDisplayList());
|
||||
mFrameToAnimatedGeometryRootMap.Put(aAnimatedGeometryRoot, result);
|
||||
}
|
||||
MOZ_ASSERT(!aParent || result->mParentAGR == aParent);
|
||||
@ -1056,18 +1055,19 @@ AnimatedGeometryRoot*
|
||||
nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsIFrame* aFrame)
|
||||
{
|
||||
if (!IsPaintingToWindow()) {
|
||||
return &mRootAGR;
|
||||
return mRootAGR;
|
||||
}
|
||||
if (aFrame == mCurrentFrame) {
|
||||
return mCurrentAGR;
|
||||
}
|
||||
AnimatedGeometryRoot* result = nullptr;
|
||||
RefPtr<AnimatedGeometryRoot> result;
|
||||
if (mFrameToAnimatedGeometryRootMap.Get(aFrame, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIFrame* agrFrame = FindAnimatedGeometryRootFrameFor(aFrame);
|
||||
result = WrapAGRForFrame(agrFrame);
|
||||
bool isAsync;
|
||||
nsIFrame* agrFrame = FindAnimatedGeometryRootFrameFor(aFrame, isAsync);
|
||||
result = WrapAGRForFrame(agrFrame, isAsync);
|
||||
mFrameToAnimatedGeometryRootMap.Put(aFrame, result);
|
||||
return result;
|
||||
}
|
||||
@ -1162,9 +1162,6 @@ nsDisplayListBuilder::~nsDisplayListBuilder() {
|
||||
"All presshells should have been exited");
|
||||
NS_ASSERTION(!mCurrentTableItem, "No table item should be active");
|
||||
|
||||
for (ActiveScrolledRoot* asr : mActiveScrolledRoots) {
|
||||
asr->ActiveScrolledRoot::~ActiveScrolledRoot();
|
||||
}
|
||||
for (nsDisplayItem* i : mTemporaryItems) {
|
||||
i->Destroy(this);
|
||||
}
|
||||
@ -1316,6 +1313,8 @@ nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* a
|
||||
docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
|
||||
}
|
||||
mIsInChromePresContext = pc->IsChrome();
|
||||
} else {
|
||||
mCurrentAGR = mRootAGR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1410,9 +1409,7 @@ ActiveScrolledRoot*
|
||||
nsDisplayListBuilder::AllocateActiveScrolledRoot(const ActiveScrolledRoot* aParent,
|
||||
nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
void* p = Allocate(sizeof(ActiveScrolledRoot), DisplayItemType::TYPE_ZERO);
|
||||
ActiveScrolledRoot* asr =
|
||||
new (KnownNotNull, p) ActiveScrolledRoot(aParent, aScrollableFrame);
|
||||
RefPtr<ActiveScrolledRoot> asr = ActiveScrolledRoot::CreateASRForFrame(aParent, aScrollableFrame, IsRetainingDisplayList());
|
||||
mActiveScrolledRoots.AppendElement(asr);
|
||||
return asr;
|
||||
}
|
||||
@ -1539,9 +1536,12 @@ IsStickyFrameActive(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame*
|
||||
|
||||
nsDisplayListBuilder::AGRState
|
||||
nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
bool& aIsAsync,
|
||||
nsIFrame** aParent)
|
||||
{
|
||||
aIsAsync = false;
|
||||
if (aFrame == mReferenceFrame) {
|
||||
aIsAsync = true;
|
||||
return AGR_YES;
|
||||
}
|
||||
if (!IsPaintingToWindow()) {
|
||||
@ -1551,6 +1551,41 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
return AGR_NO;
|
||||
}
|
||||
|
||||
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
||||
if (!parent) {
|
||||
aIsAsync = true;
|
||||
return AGR_YES;
|
||||
}
|
||||
|
||||
AGRState result = AGR_NO; // Possible to transition from not being an AGR
|
||||
// to being an AGR without a style change.
|
||||
|
||||
LayoutFrameType parentType = parent->Type();
|
||||
|
||||
if (aFrame->IsTransformed()) {
|
||||
aIsAsync = EffectCompositor::HasAnimationsForCompositor(aFrame, eCSSProperty_transform);
|
||||
result = AGR_YES;
|
||||
}
|
||||
|
||||
if (parentType == LayoutFrameType::Scroll ||
|
||||
parentType == LayoutFrameType::ListControl) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
||||
if (sf->GetScrolledFrame() == aFrame) {
|
||||
if (sf->IsScrollingActive(this)) {
|
||||
aIsAsync = aIsAsync || sf->MayBeAsynchronouslyScrolled();
|
||||
result = AGR_YES;
|
||||
} else {
|
||||
result = AGR_MAYBE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finished checking all conditions that might set aIsAsync, so we can
|
||||
// early return now.
|
||||
if (result == AGR_YES) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::IsPopup(aFrame))
|
||||
return AGR_YES;
|
||||
if (ActiveLayerTracker::IsOffsetStyleAnimated(aFrame)) {
|
||||
@ -1565,18 +1600,8 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
// for background-attachment:fixed elements.
|
||||
return AGR_YES;
|
||||
}
|
||||
if (aFrame->IsTransformed()) {
|
||||
return AGR_YES;
|
||||
}
|
||||
|
||||
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
||||
if (!parent)
|
||||
return AGR_YES;
|
||||
|
||||
bool maybe = false; // Possible to transition from not being an AGR
|
||||
// to being an AGR without a style change.
|
||||
|
||||
LayoutFrameType parentType = parent->Type();
|
||||
// Treat the slider thumb as being as an active scrolled root when it wants
|
||||
// its own layer so that it can move without repainting.
|
||||
if (parentType == LayoutFrameType::Slider) {
|
||||
@ -1588,26 +1613,16 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
if (sf && sf->IsMaybeScrollingActive()) {
|
||||
return AGR_YES;
|
||||
}
|
||||
maybe = true;
|
||||
result = AGR_MAYBE;
|
||||
}
|
||||
|
||||
if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||
if (IsStickyFrameActive(this, aFrame, parent)) {
|
||||
return AGR_YES;
|
||||
}
|
||||
maybe = true;
|
||||
result = AGR_MAYBE;
|
||||
}
|
||||
|
||||
if (parentType == LayoutFrameType::Scroll ||
|
||||
parentType == LayoutFrameType::ListControl) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
||||
if (sf->GetScrolledFrame() == aFrame) {
|
||||
if (sf->IsScrollingActive(this)) {
|
||||
return AGR_YES;
|
||||
}
|
||||
maybe = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed-pos frames are parented by the viewport frame, which has no parent.
|
||||
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) {
|
||||
@ -1623,23 +1638,23 @@ nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
// For example, layout/reftests/svg/fragmentIdentifier-01.xhtml
|
||||
//
|
||||
// see https://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers
|
||||
maybe = true;
|
||||
result = AGR_MAYBE;
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
*aParent = parent;
|
||||
}
|
||||
return !maybe ? AGR_NO : AGR_MAYBE;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame)
|
||||
nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync)
|
||||
{
|
||||
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(RootReferenceFrame(), aFrame));
|
||||
nsIFrame* cursor = aFrame;
|
||||
while (cursor != RootReferenceFrame()) {
|
||||
nsIFrame* next;
|
||||
if (IsAnimatedGeometryRoot(cursor, &next) == AGR_YES)
|
||||
if (IsAnimatedGeometryRoot(cursor, aIsAsync, &next) == AGR_YES)
|
||||
return cursor;
|
||||
cursor = next;
|
||||
}
|
||||
@ -1649,20 +1664,21 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame)
|
||||
void
|
||||
nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot()
|
||||
{
|
||||
bool isAsync;
|
||||
if (*mCurrentAGR != mCurrentFrame &&
|
||||
IsAnimatedGeometryRoot(const_cast<nsIFrame*>(mCurrentFrame)) == AGR_YES) {
|
||||
IsAnimatedGeometryRoot(const_cast<nsIFrame*>(mCurrentFrame), isAsync) == AGR_YES) {
|
||||
AnimatedGeometryRoot* oldAGR = mCurrentAGR;
|
||||
mCurrentAGR = WrapAGRForFrame(const_cast<nsIFrame*>(mCurrentFrame), mCurrentAGR);
|
||||
mCurrentAGR = WrapAGRForFrame(const_cast<nsIFrame*>(mCurrentFrame), isAsync, mCurrentAGR);
|
||||
|
||||
// Iterate the AGR cache and look for any objects that reference the old AGR and check
|
||||
// to see if they need to be updated. AGRs can be in the cache multiple times, so we may
|
||||
// end up doing the work multiple times for AGRs that don't change.
|
||||
for (auto iter = mFrameToAnimatedGeometryRootMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
AnimatedGeometryRoot* cached = iter.UserData();
|
||||
RefPtr<AnimatedGeometryRoot> cached = iter.UserData();
|
||||
if (cached->mParentAGR == oldAGR && cached != mCurrentAGR) {
|
||||
// It's possible that this cached AGR struct that has the old AGR as a parent
|
||||
// should instead have mCurrentFrame has a parent.
|
||||
nsIFrame* parent = FindAnimatedGeometryRootFrameFor(*cached);
|
||||
nsIFrame* parent = FindAnimatedGeometryRootFrameFor(*cached, isAsync);
|
||||
MOZ_ASSERT(parent == mCurrentFrame || parent == *oldAGR);
|
||||
if (parent == mCurrentFrame) {
|
||||
cached->mParentAGR = mCurrentAGR;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#ifndef NSDISPLAYLIST_H_
|
||||
#define NSDISPLAYLIST_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "gfxContext.h"
|
||||
#include "mozilla/ArenaAllocator.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
@ -153,20 +154,67 @@ typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
|
||||
*/
|
||||
struct AnimatedGeometryRoot
|
||||
{
|
||||
AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent)
|
||||
: mFrame(aFrame)
|
||||
, mParentAGR(aParent)
|
||||
{}
|
||||
static already_AddRefed<AnimatedGeometryRoot>
|
||||
CreateAGRForFrame(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
|
||||
{
|
||||
RefPtr<AnimatedGeometryRoot> result;
|
||||
if (aIsRetained) {
|
||||
result = aFrame->GetProperty(AnimatedGeometryRootCache());
|
||||
}
|
||||
|
||||
if (result) {
|
||||
result->mParentAGR = aParent;
|
||||
result->mIsAsync = aIsAsync;
|
||||
} else {
|
||||
result = new AnimatedGeometryRoot(aFrame, aParent, aIsAsync, aIsRetained);
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
operator nsIFrame*() { return mFrame; }
|
||||
|
||||
nsIFrame* operator ->() const { return mFrame; }
|
||||
|
||||
void* operator new(size_t aSize,
|
||||
nsDisplayListBuilder* aBuilder);
|
||||
AnimatedGeometryRoot* GetAsyncAGR() {
|
||||
AnimatedGeometryRoot* agr = this;
|
||||
while (!agr->mIsAsync && agr->mParentAGR) {
|
||||
agr = agr->mParentAGR;
|
||||
}
|
||||
return agr;
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)
|
||||
|
||||
nsIFrame* mFrame;
|
||||
AnimatedGeometryRoot* mParentAGR;
|
||||
RefPtr<AnimatedGeometryRoot> mParentAGR;
|
||||
bool mIsAsync;
|
||||
bool mIsRetained;
|
||||
|
||||
protected:
|
||||
static void DetachAGR(AnimatedGeometryRoot* aAGR) {
|
||||
aAGR->mFrame = nullptr;
|
||||
aAGR->mParentAGR = nullptr;
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache, AnimatedGeometryRoot, DetachAGR)
|
||||
|
||||
AnimatedGeometryRoot(nsIFrame* aFrame, AnimatedGeometryRoot* aParent, bool aIsAsync, bool aIsRetained)
|
||||
: mFrame(aFrame)
|
||||
, mParentAGR(aParent)
|
||||
, mIsAsync(aIsAsync)
|
||||
, mIsRetained(aIsRetained)
|
||||
{
|
||||
MOZ_ASSERT(mParentAGR || mIsAsync, "The root AGR should always be treated as an async AGR.");
|
||||
if (mIsRetained) {
|
||||
aFrame->SetProperty(AnimatedGeometryRootCache(), this);
|
||||
}
|
||||
}
|
||||
|
||||
~AnimatedGeometryRoot()
|
||||
{
|
||||
if (mFrame && mIsRetained) {
|
||||
mFrame->DeleteProperty(AnimatedGeometryRootCache());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
@ -188,12 +236,31 @@ namespace mozilla {
|
||||
* is on the stack.
|
||||
*/
|
||||
struct ActiveScrolledRoot {
|
||||
ActiveScrolledRoot(const ActiveScrolledRoot* aParent,
|
||||
nsIScrollableFrame* aScrollableFrame)
|
||||
: mParent(aParent)
|
||||
, mScrollableFrame(aScrollableFrame)
|
||||
, mDepth(mParent ? mParent->mDepth + 1 : 1)
|
||||
static already_AddRefed<ActiveScrolledRoot>
|
||||
CreateASRForFrame(const ActiveScrolledRoot* aParent,
|
||||
nsIScrollableFrame* aScrollableFrame,
|
||||
bool aIsRetained)
|
||||
{
|
||||
nsIFrame* f = do_QueryFrame(aScrollableFrame);
|
||||
|
||||
RefPtr<ActiveScrolledRoot> asr;
|
||||
if (aIsRetained) {
|
||||
asr = f->GetProperty(ActiveScrolledRootCache());
|
||||
}
|
||||
|
||||
if (!asr) {
|
||||
asr = new ActiveScrolledRoot();
|
||||
|
||||
if (aIsRetained) {
|
||||
f->SetProperty(ActiveScrolledRootCache(), asr);
|
||||
}
|
||||
}
|
||||
asr->mParent = aParent;
|
||||
asr->mScrollableFrame = aScrollableFrame;
|
||||
asr->mDepth = aParent ? aParent->mDepth + 1 : 1;
|
||||
asr->mRetained = aIsRetained;
|
||||
|
||||
return asr.forget();
|
||||
}
|
||||
|
||||
static const ActiveScrolledRoot* PickAncestor(const ActiveScrolledRoot* aOne,
|
||||
@ -218,15 +285,36 @@ struct ActiveScrolledRoot {
|
||||
// Call this when inserting an ancestor.
|
||||
void IncrementDepth() { mDepth++; }
|
||||
|
||||
const ActiveScrolledRoot* mParent;
|
||||
RefPtr<const ActiveScrolledRoot> mParent;
|
||||
nsIScrollableFrame* mScrollableFrame;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)
|
||||
|
||||
private:
|
||||
ActiveScrolledRoot()
|
||||
{
|
||||
}
|
||||
|
||||
~ActiveScrolledRoot()
|
||||
{
|
||||
if (mScrollableFrame && mRetained) {
|
||||
nsIFrame* f = do_QueryFrame(mScrollableFrame);
|
||||
f->DeleteProperty(ActiveScrolledRootCache());
|
||||
}
|
||||
}
|
||||
|
||||
static void DetachASR(ActiveScrolledRoot* aASR) {
|
||||
aASR->mParent = nullptr;
|
||||
aASR->mScrollableFrame = nullptr;
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache, ActiveScrolledRoot, DetachASR)
|
||||
|
||||
static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
|
||||
return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
|
||||
}
|
||||
|
||||
uint32_t mDepth;
|
||||
bool mRetained;
|
||||
};
|
||||
|
||||
}
|
||||
@ -518,6 +606,8 @@ public:
|
||||
*/
|
||||
bool IsBuildingCaret() { return mBuildCaret; }
|
||||
|
||||
bool IsRetainingDisplayList() const { return mRetainingDisplayList; }
|
||||
|
||||
/**
|
||||
* Allows callers to selectively override the regular paint suppression checks,
|
||||
* so that methods like GetFrameForPoint work when painting is suppressed.
|
||||
@ -554,7 +644,7 @@ public:
|
||||
return mCurrentAGR;
|
||||
}
|
||||
AnimatedGeometryRoot* GetRootAnimatedGeometryRoot() {
|
||||
return &mRootAGR;
|
||||
return mRootAGR;
|
||||
}
|
||||
|
||||
void RecomputeCurrentAnimatedGeometryRoot();
|
||||
@ -865,10 +955,11 @@ public:
|
||||
aBuilder->FindReferenceFrameFor(aForChild,
|
||||
&aBuilder->mCurrentOffsetToReferenceFrame);
|
||||
}
|
||||
mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild);
|
||||
bool isAsync;
|
||||
mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild, isAsync);
|
||||
if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
|
||||
if (mCurrentAGRState == AGR_YES) {
|
||||
aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, aBuilder->mCurrentAGR);
|
||||
aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, isAsync, aBuilder->mCurrentAGR);
|
||||
}
|
||||
} else if (aForChild != aBuilder->mCurrentFrame) {
|
||||
aBuilder->mCurrentAGR = aBuilder->FindAnimatedGeometryRootFor(aForChild);
|
||||
@ -913,7 +1004,7 @@ public:
|
||||
nsDisplayLayerEventRegions* mPrevLayerEventRegions;
|
||||
nsPoint mPrevOffset;
|
||||
nsRect mPrevDirtyRect;
|
||||
AnimatedGeometryRoot* mPrevAGR;
|
||||
RefPtr<AnimatedGeometryRoot> mPrevAGR;
|
||||
bool mPrevIsAtRootOfPseudoStackingContext;
|
||||
bool mPrevAncestorHasApzAwareEventHandler;
|
||||
bool mPrevBuildingInvisibleItems;
|
||||
@ -1443,13 +1534,14 @@ private:
|
||||
* returning the next ancestor to check.
|
||||
*/
|
||||
AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame,
|
||||
bool& aIsAsync,
|
||||
nsIFrame** aParent = nullptr);
|
||||
|
||||
/**
|
||||
* Returns the nearest ancestor frame to aFrame that is considered to have
|
||||
* (or will have) animated geometry. This can return aFrame.
|
||||
*/
|
||||
nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame);
|
||||
nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync);
|
||||
|
||||
friend class nsDisplayCanvasBackgroundImage;
|
||||
friend class nsDisplayBackgroundImage;
|
||||
@ -1461,9 +1553,10 @@ private:
|
||||
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
|
||||
|
||||
AnimatedGeometryRoot* WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
|
||||
bool aIsAsync,
|
||||
AnimatedGeometryRoot* aParent = nullptr);
|
||||
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, AnimatedGeometryRoot*> mFrameToAnimatedGeometryRootMap;
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, RefPtr<AnimatedGeometryRoot>> mFrameToAnimatedGeometryRootMap;
|
||||
|
||||
/**
|
||||
* Add the current frame to the AGR budget if possible and remember
|
||||
@ -1526,8 +1619,8 @@ private:
|
||||
// The offset from mCurrentFrame to mCurrentReferenceFrame.
|
||||
nsPoint mCurrentOffsetToReferenceFrame;
|
||||
|
||||
AnimatedGeometryRoot* mCurrentAGR;
|
||||
AnimatedGeometryRoot mRootAGR;
|
||||
RefPtr<AnimatedGeometryRoot> mRootAGR;
|
||||
RefPtr<AnimatedGeometryRoot> mCurrentAGR;
|
||||
|
||||
// will-change budget tracker
|
||||
nsDataHashtable<nsPtrHashKey<nsPresContext>, DocumentWillChangeBudget>
|
||||
@ -1556,7 +1649,7 @@ private:
|
||||
// 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<ActiveScrolledRoot*> mActiveScrolledRoots;
|
||||
nsTArray<RefPtr<ActiveScrolledRoot>> mActiveScrolledRoots;
|
||||
AutoTArray<DisplayItemClipChain*, 128> mClipChainsToDestroy;
|
||||
nsTArray<nsDisplayItem*> mTemporaryItems;
|
||||
const ActiveScrolledRoot* mActiveScrolledRootForRootScrollframe;
|
||||
@ -1571,6 +1664,7 @@ private:
|
||||
bool mIsBuildingScrollbar;
|
||||
bool mCurrentScrollbarWillHaveLayer;
|
||||
bool mBuildCaret;
|
||||
bool mRetainingDisplayList;
|
||||
bool mIgnoreSuppression;
|
||||
bool mIsAtRootOfPseudoStackingContext;
|
||||
bool mIncludeAllOutOfFlows;
|
||||
@ -2340,10 +2434,10 @@ protected:
|
||||
nsIFrame* mFrame;
|
||||
const DisplayItemClipChain* mClipChain;
|
||||
const DisplayItemClip* mClip;
|
||||
const ActiveScrolledRoot* mActiveScrolledRoot;
|
||||
RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
|
||||
// Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
|
||||
const nsIFrame* mReferenceFrame;
|
||||
struct AnimatedGeometryRoot* mAnimatedGeometryRoot;
|
||||
RefPtr<struct AnimatedGeometryRoot> mAnimatedGeometryRoot;
|
||||
// Result of ToReferenceFrame(mFrame), if mFrame is non-null
|
||||
nsPoint mToReferenceFrame;
|
||||
// This is the rectangle that needs to be painted.
|
||||
@ -4666,7 +4760,7 @@ protected:
|
||||
nsDisplayList* aList, uint32_t aIndex);
|
||||
void Init(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
|
||||
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
|
||||
uint32_t mIndex;
|
||||
bool mIsFixedBackground;
|
||||
};
|
||||
@ -5383,8 +5477,8 @@ private:
|
||||
// Accumulated transform of ancestors on the preserves-3d chain.
|
||||
Matrix4x4 mTransformPreserves3D;
|
||||
ComputeTransformFunction mTransformGetter;
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRootForChildren;
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
|
||||
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForChildren;
|
||||
RefPtr<AnimatedGeometryRoot> mAnimatedGeometryRootForScrollMetadata;
|
||||
nsRect mChildrenVisibleRect;
|
||||
uint32_t mIndex;
|
||||
mutable nsRect mBounds;
|
||||
|
Loading…
Reference in New Issue
Block a user