зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1488599 - Part 2: Fix will-change budget r=mattwoodrow
Depends on D5245 Differential Revision: https://phabricator.services.mozilla.com/D5246 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e646042ce1
Коммит
8383187890
|
@ -3700,11 +3700,15 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||||
|
|
||||||
if (updateState == PartialUpdateResult::Failed) {
|
if (updateState == PartialUpdateResult::Failed) {
|
||||||
list.DeleteAll(&builder);
|
list.DeleteAll(&builder);
|
||||||
|
|
||||||
|
builder.ClearRetainedWindowRegions();
|
||||||
|
builder.ClearWillChangeBudget();
|
||||||
|
|
||||||
builder.EnterPresShell(aFrame);
|
builder.EnterPresShell(aFrame);
|
||||||
builder.SetDirtyRect(visibleRect);
|
builder.SetDirtyRect(visibleRect);
|
||||||
builder.ClearRetainedWindowRegions();
|
|
||||||
aFrame->BuildDisplayListForStackingContext(&builder, &list);
|
aFrame->BuildDisplayListForStackingContext(&builder, &list);
|
||||||
AddExtraBackgroundItems(builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
|
AddExtraBackgroundItems(
|
||||||
|
builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
|
||||||
|
|
||||||
builder.LeavePresShell(aFrame, &list);
|
builder.LeavePresShell(aFrame, &list);
|
||||||
updateState = PartialUpdateResult::Updated;
|
updateState = PartialUpdateResult::Updated;
|
||||||
|
|
|
@ -986,6 +986,12 @@ nsIFrame::RemoveDisplayItemDataForDeletion()
|
||||||
|
|
||||||
RetainedDisplayListData* data = GetOrSetRetainedDisplayListData(rootFrame);
|
RetainedDisplayListData* data = GetOrSetRetainedDisplayListData(rootFrame);
|
||||||
|
|
||||||
|
if (MayHaveWillChangeBudget()) {
|
||||||
|
// Keep the frame in list, so it can be removed from the will-change budget.
|
||||||
|
data->Flags(this) = RetainedDisplayListData::FrameFlags::HadWillChange;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsFrameModified() || HasOverrideDirtyRegion()) {
|
if (IsFrameModified() || HasOverrideDirtyRegion()) {
|
||||||
// Remove deleted frames from RetainedDisplayListData.
|
// Remove deleted frames from RetainedDisplayListData.
|
||||||
DebugOnly<bool> removed = data->Remove(this);
|
DebugOnly<bool> removed = data->Remove(this);
|
||||||
|
@ -3486,7 +3492,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY))
|
NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
aBuilder->ClearWillChangeBudget(child);
|
aBuilder->RemoveFromWillChangeBudget(child);
|
||||||
|
|
||||||
const bool shortcutPossible = aBuilder->IsPaintingToWindow() &&
|
const bool shortcutPossible = aBuilder->IsPaintingToWindow() &&
|
||||||
aBuilder->BuildCompositorHitTestInfo();
|
aBuilder->BuildCompositorHitTestInfo();
|
||||||
|
@ -3563,7 +3569,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
isPlaceholder = true;
|
isPlaceholder = true;
|
||||||
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
|
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
|
||||||
child = placeholder->GetOutOfFlowFrame();
|
child = placeholder->GetOutOfFlowFrame();
|
||||||
aBuilder->ClearWillChangeBudget(child);
|
aBuilder->RemoveFromWillChangeBudget(child);
|
||||||
NS_ASSERTION(child, "No out of flow frame?");
|
NS_ASSERTION(child, "No out of flow frame?");
|
||||||
// If 'child' is a pushed float then it's owned by a block that's not an
|
// If 'child' is a pushed float then it's owned by a block that's not an
|
||||||
// ancestor of the placeholder, and it will be painted by that block and
|
// ancestor of the placeholder, and it will be painted by that block and
|
||||||
|
|
|
@ -660,6 +660,7 @@ RetainedDisplayListBuilder::MergeDisplayLists(
|
||||||
|
|
||||||
static void
|
static void
|
||||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||||
|
nsDisplayListBuilder* aBuilder,
|
||||||
nsTArray<nsIFrame*>* aModifiedFrames,
|
nsTArray<nsIFrame*>* aModifiedFrames,
|
||||||
nsTArray<nsIFrame*>* aFramesWithProps,
|
nsTArray<nsIFrame*>* aFramesWithProps,
|
||||||
nsIFrame* aRootFrame)
|
nsIFrame* aRootFrame)
|
||||||
|
@ -683,6 +684,10 @@ TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||||
if (flags & RetainedDisplayListData::FrameFlags::HasProps) {
|
if (flags & RetainedDisplayListData::FrameFlags::HasProps) {
|
||||||
aFramesWithProps->AppendElement(frame);
|
aFramesWithProps->AppendElement(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & RetainedDisplayListData::FrameFlags::HadWillChange) {
|
||||||
|
aBuilder->RemoveFromWillChangeBudget(frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->Clear();
|
data->Clear();
|
||||||
|
@ -748,7 +753,7 @@ SubDocEnumCb(nsIDocument* aDocument, void* aData)
|
||||||
nsIFrame* rootFrame = GetRootFrameForPainting(data->builder, aDocument);
|
nsIFrame* rootFrame = GetRootFrameForPainting(data->builder, aDocument);
|
||||||
if (rootFrame) {
|
if (rootFrame) {
|
||||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||||
data->modifiedFrames, data->framesWithProps, rootFrame);
|
data->builder, data->modifiedFrames, data->framesWithProps, rootFrame);
|
||||||
|
|
||||||
nsIDocument* innerDoc = rootFrame->PresShell()->GetDocument();
|
nsIDocument* innerDoc = rootFrame->PresShell()->GetDocument();
|
||||||
if (innerDoc) {
|
if (innerDoc) {
|
||||||
|
@ -763,14 +768,13 @@ GetModifiedAndFramesWithProps(nsDisplayListBuilder* aBuilder,
|
||||||
nsTArray<nsIFrame*>* aOutModifiedFrames,
|
nsTArray<nsIFrame*>* aOutModifiedFrames,
|
||||||
nsTArray<nsIFrame*>* aOutFramesWithProps)
|
nsTArray<nsIFrame*>* aOutFramesWithProps)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aBuilder->RootReferenceFrame());
|
nsIFrame* rootFrame = aBuilder->RootReferenceFrame();
|
||||||
|
MOZ_ASSERT(rootFrame);
|
||||||
|
|
||||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||||
aOutModifiedFrames, aOutFramesWithProps, aBuilder->RootReferenceFrame());
|
aBuilder, aOutModifiedFrames, aOutFramesWithProps, rootFrame);
|
||||||
|
|
||||||
nsIDocument* rootdoc =
|
|
||||||
aBuilder->RootReferenceFrame()->PresContext()->Document();
|
|
||||||
|
|
||||||
|
nsIDocument* rootdoc = rootFrame->PresContext()->Document();
|
||||||
if (rootdoc) {
|
if (rootdoc) {
|
||||||
CbData data = { aBuilder, aOutModifiedFrames, aOutFramesWithProps };
|
CbData data = { aBuilder, aOutModifiedFrames, aOutFramesWithProps };
|
||||||
|
|
||||||
|
|
|
@ -1060,6 +1060,7 @@ nsDisplayListBuilder::EndFrame()
|
||||||
NS_ASSERTION(!mInInvalidSubtree,
|
NS_ASSERTION(!mInInvalidSubtree,
|
||||||
"Someone forgot to cleanup mInInvalidSubtree!");
|
"Someone forgot to cleanup mInInvalidSubtree!");
|
||||||
mFrameToAnimatedGeometryRootMap.Clear();
|
mFrameToAnimatedGeometryRootMap.Clear();
|
||||||
|
mAGRBudgetSet.Clear();
|
||||||
mActiveScrolledRoots.Clear();
|
mActiveScrolledRoots.Clear();
|
||||||
FreeClipChains();
|
FreeClipChains();
|
||||||
FreeTemporaryItems();
|
FreeTemporaryItems();
|
||||||
|
@ -2120,29 +2121,20 @@ nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
|
||||||
return true; // Already accounted
|
return true; // Already accounted
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPresContext* key = aFrame->PresContext();
|
nsPresContext* presContext = aFrame->PresContext();
|
||||||
DocumentWillChangeBudget budget;
|
nsRect area = presContext->GetVisibleArea();
|
||||||
auto willChangeBudgetEntry = mWillChangeBudget.LookupForAdd(key);
|
|
||||||
if (willChangeBudgetEntry) {
|
|
||||||
// We have an existing entry.
|
|
||||||
budget = willChangeBudgetEntry.Data();
|
|
||||||
} else {
|
|
||||||
budget = DocumentWillChangeBudget();
|
|
||||||
willChangeBudgetEntry.OrInsert([&budget]() { return budget; });
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRect area = aFrame->PresContext()->GetVisibleArea();
|
|
||||||
uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
|
uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
|
||||||
nsPresContext::AppUnitsToIntCSSPixels(area.height);
|
nsPresContext::AppUnitsToIntCSSPixels(area.height);
|
||||||
|
|
||||||
uint32_t cost = GetLayerizationCost(aSize);
|
uint32_t cost = GetLayerizationCost(aSize);
|
||||||
|
|
||||||
|
DocumentWillChangeBudget& budget = mWillChangeBudget.GetOrInsert(presContext);
|
||||||
|
|
||||||
bool onBudget =
|
bool onBudget =
|
||||||
(budget.mBudget + cost) / gWillChangeAreaMultiplier < budgetLimit;
|
(budget.mBudget + cost) / gWillChangeAreaMultiplier < budgetLimit;
|
||||||
|
|
||||||
if (onBudget) {
|
if (onBudget) {
|
||||||
budget.mBudget += cost;
|
budget.mBudget += cost;
|
||||||
willChangeBudgetEntry.Data() = budget;
|
mWillChangeBudgetSet.Put(aFrame, FrameWillChangeBudget(presContext, cost));
|
||||||
mWillChangeBudgetSet.Put(aFrame, cost);
|
|
||||||
aFrame->SetMayHaveWillChangeBudget(true);
|
aFrame->SetMayHaveWillChangeBudget(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2179,23 +2171,29 @@ nsDisplayListBuilder::IsInWillChangeBudget(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsDisplayListBuilder::ClearWillChangeBudget(nsIFrame* aFrame)
|
nsDisplayListBuilder::RemoveFromWillChangeBudget(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
if (!aFrame->MayHaveWillChangeBudget()) {
|
FrameWillChangeBudget* frameBudget = mWillChangeBudgetSet.GetValue(aFrame);
|
||||||
return;
|
|
||||||
}
|
|
||||||
aFrame->SetMayHaveWillChangeBudget(false);
|
|
||||||
|
|
||||||
uint32_t cost = 0;
|
if (!frameBudget) {
|
||||||
if (!mWillChangeBudgetSet.Get(aFrame, &cost)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mWillChangeBudgetSet.Remove(aFrame);
|
mWillChangeBudgetSet.Remove(aFrame);
|
||||||
|
|
||||||
DocumentWillChangeBudget& budget =
|
DocumentWillChangeBudget* budget =
|
||||||
mWillChangeBudget.GetOrInsert(aFrame->PresContext());
|
mWillChangeBudget.GetValue(frameBudget->mPresContext);
|
||||||
MOZ_ASSERT(budget.mBudget >= cost);
|
MOZ_ASSERT(budget);
|
||||||
budget.mBudget -= cost;
|
|
||||||
|
budget->mBudget -= frameBudget->mUsage;
|
||||||
|
MOZ_ASSERT(budget->mBudget >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsDisplayListBuilder::ClearWillChangeBudget()
|
||||||
|
{
|
||||||
|
mWillChangeBudgetSet.Clear();
|
||||||
|
mWillChangeBudget.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||||
|
|
|
@ -1815,7 +1815,9 @@ public:
|
||||||
*/
|
*/
|
||||||
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
|
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
|
||||||
|
|
||||||
void ClearWillChangeBudget(nsIFrame* aFrame);
|
void RemoveFromWillChangeBudget(nsIFrame* aFrame);
|
||||||
|
|
||||||
|
void ClearWillChangeBudget();
|
||||||
|
|
||||||
void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
|
void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
|
||||||
void ExitSVGEffectsContents();
|
void ExitSVGEffectsContents();
|
||||||
|
@ -2040,13 +2042,19 @@ private:
|
||||||
|
|
||||||
struct FrameWillChangeBudget
|
struct FrameWillChangeBudget
|
||||||
{
|
{
|
||||||
FrameWillChangeBudget(nsIFrame* aFrame, uint32_t aUsage)
|
FrameWillChangeBudget()
|
||||||
: mFrame(aFrame)
|
: mPresContext(nullptr)
|
||||||
|
, mUsage(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameWillChangeBudget(nsPresContext* aPresContext, uint32_t aUsage)
|
||||||
|
: mPresContext(aPresContext)
|
||||||
, mUsage(aUsage)
|
, mUsage(aUsage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* mFrame;
|
nsPresContext* mPresContext;
|
||||||
uint32_t mUsage;
|
uint32_t mUsage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2084,7 +2092,8 @@ private:
|
||||||
|
|
||||||
// Any frame listed in this set is already counted in the budget
|
// Any frame listed in this set is already counted in the budget
|
||||||
// and thus is in-budget.
|
// and thus is in-budget.
|
||||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, uint32_t> mWillChangeBudgetSet;
|
nsDataHashtable<nsPtrHashKey<nsIFrame>, FrameWillChangeBudget>
|
||||||
|
mWillChangeBudgetSet;
|
||||||
|
|
||||||
// Area of animated geometry root budget already allocated
|
// Area of animated geometry root budget already allocated
|
||||||
uint32_t mUsedAGRBudget;
|
uint32_t mUsedAGRBudget;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче