зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1488599) for bustages at /layout/painting/nsDisplayList.cpp on a CLOSED TREE
Backed out changeset ed780c8fd413 (bug 1488599) Backed out changeset 0f40b48ed3b4 (bug 1488599)
This commit is contained in:
Родитель
2237676d3a
Коммит
da0121c598
|
@ -479,14 +479,6 @@ nsLayoutUtils::AreRetainedDisplayListsEnabled()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::DisplayRootHasRetainedDisplayListBuilder(nsIFrame* aFrame)
|
||||
{
|
||||
const nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
|
||||
MOZ_ASSERT(displayRoot);
|
||||
return displayRoot->HasProperty(RetainedDisplayListBuilder::Cached());
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::GPUImageScalingEnabled()
|
||||
{
|
||||
|
@ -1196,8 +1188,15 @@ nsLayoutUtils::InvalidateForDisplayPortChange(nsIContent* aContent,
|
|||
// rect properties on so we can find the frame later to remove the properties.
|
||||
frame->SchedulePaint();
|
||||
|
||||
if (!nsLayoutUtils::AreRetainedDisplayListsEnabled() ||
|
||||
!nsLayoutUtils::DisplayRootHasRetainedDisplayListBuilder(frame)) {
|
||||
if (!nsLayoutUtils::AreRetainedDisplayListsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(frame);
|
||||
RetainedDisplayListBuilder* retainedBuilder =
|
||||
displayRoot->GetProperty(RetainedDisplayListBuilder::Cached());
|
||||
|
||||
if (!retainedBuilder) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1209,12 +1208,18 @@ nsLayoutUtils::InvalidateForDisplayPortChange(nsIContent* aContent,
|
|||
frame->SetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect(), rect);
|
||||
frame->SetHasOverrideDirtyRegion(true);
|
||||
|
||||
nsIFrame* rootFrame = frame->PresShell()->GetRootFrame();
|
||||
nsIFrame* rootFrame = frame->PresContext()->PresShell()->GetRootFrame();
|
||||
MOZ_ASSERT(rootFrame);
|
||||
|
||||
RetainedDisplayListData* data =
|
||||
GetOrSetRetainedDisplayListData(rootFrame);
|
||||
data->Flags(frame) |= RetainedDisplayListData::FrameFlags::HasProps;
|
||||
nsTArray<nsIFrame*>* frames =
|
||||
rootFrame->GetProperty(nsIFrame::OverriddenDirtyRectFrameList());
|
||||
|
||||
if (!frames) {
|
||||
frames = new nsTArray<nsIFrame*>();
|
||||
rootFrame->SetProperty(nsIFrame::OverriddenDirtyRectFrameList(), frames);
|
||||
}
|
||||
|
||||
frames->AppendElement(frame);
|
||||
}
|
||||
|
||||
if (aHadDisplayPort) {
|
||||
|
@ -3700,15 +3705,11 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
|||
|
||||
if (updateState == PartialUpdateResult::Failed) {
|
||||
list.DeleteAll(&builder);
|
||||
|
||||
builder.ClearRetainedWindowRegions();
|
||||
builder.ClearWillChangeBudget();
|
||||
|
||||
builder.EnterPresShell(aFrame);
|
||||
builder.SetDirtyRect(visibleRect);
|
||||
builder.ClearRetainedWindowRegions();
|
||||
aFrame->BuildDisplayListForStackingContext(&builder, &list);
|
||||
AddExtraBackgroundItems(
|
||||
builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
|
||||
AddExtraBackgroundItems(builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
|
||||
|
||||
builder.LeavePresShell(aFrame, &list);
|
||||
updateState = PartialUpdateResult::Updated;
|
||||
|
|
|
@ -2375,8 +2375,6 @@ public:
|
|||
*/
|
||||
static bool AreRetainedDisplayListsEnabled();
|
||||
|
||||
static bool DisplayRootHasRetainedDisplayListBuilder(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Find a suitable scale for a element (aFrame's content) over the course of any
|
||||
* animations and transitions of the CSS transform property on the
|
||||
|
|
|
@ -829,14 +829,12 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
|
|||
nsIFrame* rootFrame = shell->GetRootFrame();
|
||||
MOZ_ASSERT(rootFrame);
|
||||
if (this != rootFrame) {
|
||||
const RetainedDisplayListData* data =
|
||||
GetRetainedDisplayListData(rootFrame);
|
||||
|
||||
const bool inModifiedList = data &&
|
||||
(data->GetFlags(this) & RetainedDisplayListData::FrameFlags::Modified);
|
||||
|
||||
MOZ_ASSERT(!inModifiedList,
|
||||
"A dtor added this frame to modified frames list!");
|
||||
nsTArray<nsIFrame*>* modifiedFrames =
|
||||
rootFrame->GetProperty(nsIFrame::ModifiedFrameList());
|
||||
if (modifiedFrames) {
|
||||
MOZ_ASSERT(!modifiedFrames->Contains(this),
|
||||
"A dtor added this frame to ModifiedFrameList");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -967,36 +965,36 @@ nsIFrame::RemoveDisplayItemDataForDeletion()
|
|||
delete items;
|
||||
}
|
||||
|
||||
if (!nsLayoutUtils::AreRetainedDisplayListsEnabled()) {
|
||||
// Retained display lists are disabled, no need to update
|
||||
// RetainedDisplayListData.
|
||||
return;
|
||||
if (IsFrameModified()) {
|
||||
nsIFrame* rootFrame = PresShell()->GetRootFrame();
|
||||
MOZ_ASSERT(rootFrame);
|
||||
|
||||
nsTArray<nsIFrame*>* modifiedFrames =
|
||||
rootFrame->GetProperty(nsIFrame::ModifiedFrameList());
|
||||
MOZ_ASSERT(modifiedFrames);
|
||||
|
||||
for (auto& frame : *modifiedFrames) {
|
||||
if (frame == this) {
|
||||
frame = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool updateData =
|
||||
IsFrameModified() || HasOverrideDirtyRegion() || MayHaveWillChangeBudget();
|
||||
if (HasOverrideDirtyRegion()) {
|
||||
nsIFrame* rootFrame = PresShell()->GetRootFrame();
|
||||
MOZ_ASSERT(rootFrame);
|
||||
|
||||
if (!updateData) {
|
||||
// No RetainedDisplayListData to update.
|
||||
return;
|
||||
}
|
||||
nsTArray<nsIFrame*>* frames =
|
||||
rootFrame->GetProperty(nsIFrame::OverriddenDirtyRectFrameList());
|
||||
MOZ_ASSERT(frames);
|
||||
|
||||
nsIFrame* rootFrame = PresShell()->GetRootFrame();
|
||||
MOZ_ASSERT(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()) {
|
||||
// Remove deleted frames from RetainedDisplayListData.
|
||||
DebugOnly<bool> removed = data->Remove(this);
|
||||
MOZ_ASSERT(removed,
|
||||
"Frame had flags set, but it was not found in DisplayListData!");
|
||||
for (auto& frame : *frames) {
|
||||
if (frame == this) {
|
||||
frame = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1017,13 @@ nsIFrame::MarkNeedsDisplayItemRebuild()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!nsLayoutUtils::DisplayRootHasRetainedDisplayListBuilder(this)) {
|
||||
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
|
||||
MOZ_ASSERT(displayRoot);
|
||||
|
||||
RetainedDisplayListBuilder* retainedBuilder =
|
||||
displayRoot->GetProperty(RetainedDisplayListBuilder::Cached());
|
||||
|
||||
if (!retainedBuilder) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1030,12 +1034,35 @@ nsIFrame::MarkNeedsDisplayItemRebuild()
|
|||
return;
|
||||
}
|
||||
|
||||
RetainedDisplayListData* data = GetOrSetRetainedDisplayListData(rootFrame);
|
||||
data->Flags(this) |= RetainedDisplayListData::FrameFlags::Modified;
|
||||
SetFrameIsModified(true);
|
||||
nsTArray<nsIFrame*>* modifiedFrames =
|
||||
rootFrame->GetProperty(nsIFrame::ModifiedFrameList());
|
||||
|
||||
MOZ_ASSERT(
|
||||
PresContext()->LayoutPhaseCount(eLayoutPhase_DisplayListBuilding) == 0);
|
||||
if (!modifiedFrames) {
|
||||
modifiedFrames = new nsTArray<nsIFrame*>();
|
||||
rootFrame->SetProperty(nsIFrame::ModifiedFrameList(), modifiedFrames);
|
||||
}
|
||||
|
||||
if (this == rootFrame) {
|
||||
// If this is the root frame, then marking us as needing a display
|
||||
// item rebuild implies the same for all our descendents. Clear them
|
||||
// all out to reduce the number of modified frames we keep around.
|
||||
for (nsIFrame* f : *modifiedFrames) {
|
||||
if (f) {
|
||||
f->SetFrameIsModified(false);
|
||||
}
|
||||
}
|
||||
modifiedFrames->Clear();
|
||||
} else if (modifiedFrames->Length() > gfxPrefs::LayoutRebuildFrameLimit()) {
|
||||
// If the list starts getting too big, then just mark the root frame
|
||||
// as needing a rebuild.
|
||||
rootFrame->MarkNeedsDisplayItemRebuild();
|
||||
return;
|
||||
}
|
||||
|
||||
modifiedFrames->AppendElement(this);
|
||||
|
||||
MOZ_ASSERT(PresContext()->LayoutPhaseCount(eLayoutPhase_DisplayListBuilding) == 0);
|
||||
SetFrameIsModified(true);
|
||||
|
||||
// Hopefully this is cheap, but we could use a frame state bit to note
|
||||
// the presence of dependencies to speed it up.
|
||||
|
@ -3492,7 +3519,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY))
|
||||
return;
|
||||
|
||||
aBuilder->RemoveFromWillChangeBudget(child);
|
||||
aBuilder->ClearWillChangeBudget(child);
|
||||
|
||||
const bool shortcutPossible = aBuilder->IsPaintingToWindow() &&
|
||||
aBuilder->BuildCompositorHitTestInfo();
|
||||
|
@ -3569,7 +3596,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
isPlaceholder = true;
|
||||
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(child);
|
||||
child = placeholder->GetOutOfFlowFrame();
|
||||
aBuilder->RemoveFromWillChangeBudget(child);
|
||||
aBuilder->ClearWillChangeBudget(child);
|
||||
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
|
||||
// ancestor of the placeholder, and it will be painted by that block and
|
||||
|
|
|
@ -1251,6 +1251,8 @@ public:
|
|||
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
|
||||
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(ModifiedFrameList, nsTArray<nsIFrame*>)
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverriddenDirtyRectFrameList, nsTArray<nsIFrame*>)
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems, DisplayItemArray)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
|
||||
|
|
|
@ -41,29 +41,6 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
RetainedDisplayListData*
|
||||
GetRetainedDisplayListData(nsIFrame* aRootFrame)
|
||||
{
|
||||
RetainedDisplayListData* data =
|
||||
aRootFrame->GetProperty(RetainedDisplayListData::DisplayListData());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
RetainedDisplayListData*
|
||||
GetOrSetRetainedDisplayListData(nsIFrame* aRootFrame)
|
||||
{
|
||||
RetainedDisplayListData* data = GetRetainedDisplayListData(aRootFrame);
|
||||
|
||||
if (!data) {
|
||||
data = new RetainedDisplayListData();
|
||||
aRootFrame->SetProperty(RetainedDisplayListData::DisplayListData(), data);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
MarkFramesWithItemsAndImagesModified(nsDisplayList* aList)
|
||||
{
|
||||
|
@ -660,37 +637,36 @@ RetainedDisplayListBuilder::MergeDisplayLists(
|
|||
|
||||
static void
|
||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
nsTArray<nsIFrame*>* aModifiedFrames,
|
||||
nsTArray<nsIFrame*>* aFramesWithProps,
|
||||
nsIFrame* aRootFrame)
|
||||
{
|
||||
MOZ_ASSERT(aRootFrame);
|
||||
|
||||
RetainedDisplayListData* data = GetRetainedDisplayListData(aRootFrame);
|
||||
nsTArray<nsIFrame*>* frames =
|
||||
aRootFrame->GetProperty(nsIFrame::ModifiedFrameList());
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
if (frames) {
|
||||
for (nsIFrame* f : *frames) {
|
||||
if (f) {
|
||||
aModifiedFrames->AppendElement(f);
|
||||
}
|
||||
}
|
||||
|
||||
frames->Clear();
|
||||
}
|
||||
|
||||
for (auto it = data->Iterator(); !it.Done(); it.Next()) {
|
||||
nsIFrame* frame = it.Key();
|
||||
const RetainedDisplayListData::FrameFlags& flags = it.Data();
|
||||
frames = aRootFrame->GetProperty(nsIFrame::OverriddenDirtyRectFrameList());
|
||||
|
||||
if (flags & RetainedDisplayListData::FrameFlags::Modified) {
|
||||
aModifiedFrames->AppendElement(frame);
|
||||
if (frames) {
|
||||
for (nsIFrame* f : *frames) {
|
||||
if (f) {
|
||||
aFramesWithProps->AppendElement(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & RetainedDisplayListData::FrameFlags::HasProps) {
|
||||
aFramesWithProps->AppendElement(frame);
|
||||
}
|
||||
|
||||
if (flags & RetainedDisplayListData::FrameFlags::HadWillChange) {
|
||||
aBuilder->RemoveFromWillChangeBudget(frame);
|
||||
}
|
||||
frames->Clear();
|
||||
}
|
||||
|
||||
data->Clear();
|
||||
}
|
||||
|
||||
struct CbData
|
||||
|
@ -753,7 +729,7 @@ SubDocEnumCb(nsIDocument* aDocument, void* aData)
|
|||
nsIFrame* rootFrame = GetRootFrameForPainting(data->builder, aDocument);
|
||||
if (rootFrame) {
|
||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||
data->builder, data->modifiedFrames, data->framesWithProps, rootFrame);
|
||||
data->modifiedFrames, data->framesWithProps, rootFrame);
|
||||
|
||||
nsIDocument* innerDoc = rootFrame->PresShell()->GetDocument();
|
||||
if (innerDoc) {
|
||||
|
@ -768,13 +744,14 @@ GetModifiedAndFramesWithProps(nsDisplayListBuilder* aBuilder,
|
|||
nsTArray<nsIFrame*>* aOutModifiedFrames,
|
||||
nsTArray<nsIFrame*>* aOutFramesWithProps)
|
||||
{
|
||||
nsIFrame* rootFrame = aBuilder->RootReferenceFrame();
|
||||
MOZ_ASSERT(rootFrame);
|
||||
MOZ_ASSERT(aBuilder->RootReferenceFrame());
|
||||
|
||||
TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
|
||||
aBuilder, aOutModifiedFrames, aOutFramesWithProps, rootFrame);
|
||||
aOutModifiedFrames, aOutFramesWithProps, aBuilder->RootReferenceFrame());
|
||||
|
||||
nsIDocument* rootdoc =
|
||||
aBuilder->RootReferenceFrame()->PresContext()->Document();
|
||||
|
||||
nsIDocument* rootdoc = rootFrame->PresContext()->Document();
|
||||
if (rootdoc) {
|
||||
CbData data = { aBuilder, aOutModifiedFrames, aOutFramesWithProps };
|
||||
|
||||
|
@ -1253,11 +1230,6 @@ ClearFrameProps(nsTArray<nsIFrame*>& aFrames)
|
|||
class AutoClearFramePropsArray
|
||||
{
|
||||
public:
|
||||
explicit AutoClearFramePropsArray(size_t aCapacity)
|
||||
: mFrames(aCapacity)
|
||||
{
|
||||
}
|
||||
|
||||
AutoClearFramePropsArray() = default;
|
||||
|
||||
~AutoClearFramePropsArray() { ClearFrameProps(mFrames); }
|
||||
|
@ -1296,7 +1268,7 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
|
|||
// We set the override dirty regions during ComputeRebuildRegion or in
|
||||
// nsLayoutUtils::InvalidateForDisplayPortChange. The display port change also
|
||||
// marks the frame modified, so those regions are cleared here as well.
|
||||
AutoClearFramePropsArray modifiedFrames(64);
|
||||
AutoClearFramePropsArray modifiedFrames;
|
||||
AutoClearFramePropsArray framesWithProps;
|
||||
GetModifiedAndFramesWithProps(
|
||||
&mBuilder, &modifiedFrames.Frames(), &framesWithProps.Frames());
|
||||
|
|
|
@ -9,78 +9,11 @@
|
|||
|
||||
#include "nsDisplayList.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
namespace mozilla {
|
||||
class DisplayListChecker;
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
/**
|
||||
* RetainedDisplayListData contains frame invalidation information. It is stored
|
||||
* in root frames, and used by RetainedDisplayListBuilder.
|
||||
* Currently this is implemented as a map of frame pointers to flags.
|
||||
*/
|
||||
struct RetainedDisplayListData
|
||||
{
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListData, RetainedDisplayListData)
|
||||
|
||||
enum class FrameFlags : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
Modified = 1 << 0,
|
||||
HasProps = 1 << 1,
|
||||
HadWillChange = 1 << 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all the frames from this RetainedDisplayListData.
|
||||
*/
|
||||
void Clear() { mFrames.Clear(); }
|
||||
|
||||
/**
|
||||
* Returns a mutable reference to flags set for the given |aFrame|. If the
|
||||
* frame does not exist in this RetainedDisplayListData, it is added with
|
||||
* default constructible flags FrameFlags::None.
|
||||
*/
|
||||
FrameFlags& Flags(nsIFrame* aFrame) { return mFrames.GetOrInsert(aFrame); }
|
||||
|
||||
/**
|
||||
* Returns flags set for the given |aFrame|, or FrameFlags::None if the frame
|
||||
* is not in this RetainedDisplayListData.
|
||||
*/
|
||||
FrameFlags GetFlags(nsIFrame* aFrame) const { return mFrames.Get(aFrame); }
|
||||
|
||||
/**
|
||||
* Returns an iterator to the underlying frame storage.
|
||||
*/
|
||||
auto Iterator() { return mFrames.Iter(); }
|
||||
|
||||
/**
|
||||
* Removes the given |aFrame| from this RetainedDisplayListData.
|
||||
*/
|
||||
bool Remove(nsIFrame* aFrame) { return mFrames.Remove(aFrame); }
|
||||
|
||||
private:
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, FrameFlags> mFrames;
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(RetainedDisplayListData::FrameFlags)
|
||||
|
||||
/**
|
||||
* Returns RetainedDisplayListData property for the given |aRootFrame|, or
|
||||
* nullptr if the property is not set.
|
||||
*/
|
||||
RetainedDisplayListData*
|
||||
GetRetainedDisplayListData(nsIFrame* aRootFrame);
|
||||
|
||||
/**
|
||||
* Returns RetainedDisplayListData property for the given |aRootFrame|. Creates
|
||||
* and sets a new RetainedDisplayListData property if it is not already set.
|
||||
*/
|
||||
RetainedDisplayListData*
|
||||
GetOrSetRetainedDisplayListData(nsIFrame* aRootFrame);
|
||||
|
||||
struct RetainedDisplayListBuilder
|
||||
{
|
||||
RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
|
|
|
@ -1060,7 +1060,6 @@ nsDisplayListBuilder::EndFrame()
|
|||
NS_ASSERTION(!mInInvalidSubtree,
|
||||
"Someone forgot to cleanup mInInvalidSubtree!");
|
||||
mFrameToAnimatedGeometryRootMap.Clear();
|
||||
mAGRBudgetSet.Clear();
|
||||
mActiveScrolledRoots.Clear();
|
||||
FreeClipChains();
|
||||
FreeTemporaryItems();
|
||||
|
@ -2121,20 +2120,29 @@ nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
|
|||
return true; // Already accounted
|
||||
}
|
||||
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
nsRect area = presContext->GetVisibleArea();
|
||||
nsPresContext* key = aFrame->PresContext();
|
||||
DocumentWillChangeBudget budget;
|
||||
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) *
|
||||
nsPresContext::AppUnitsToIntCSSPixels(area.height);
|
||||
|
||||
uint32_t cost = GetLayerizationCost(aSize);
|
||||
|
||||
DocumentWillChangeBudget& budget = mWillChangeBudget.GetOrInsert(presContext);
|
||||
|
||||
bool onBudget =
|
||||
(budget.mBudget + cost) / gWillChangeAreaMultiplier < budgetLimit;
|
||||
|
||||
if (onBudget) {
|
||||
budget.mBudget += cost;
|
||||
mWillChangeBudgetSet.Put(aFrame, FrameWillChangeBudget(presContext, cost));
|
||||
willChangeBudgetEntry.Data() = budget;
|
||||
mWillChangeBudgetSet.Put(aFrame, cost);
|
||||
aFrame->SetMayHaveWillChangeBudget(true);
|
||||
}
|
||||
|
||||
|
@ -2171,29 +2179,23 @@ nsDisplayListBuilder::IsInWillChangeBudget(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
void
|
||||
nsDisplayListBuilder::RemoveFromWillChangeBudget(nsIFrame* aFrame)
|
||||
nsDisplayListBuilder::ClearWillChangeBudget(nsIFrame* aFrame)
|
||||
{
|
||||
FrameWillChangeBudget* frameBudget = mWillChangeBudgetSet.GetValue(aFrame);
|
||||
|
||||
if (!frameBudget) {
|
||||
if (!aFrame->MayHaveWillChangeBudget()) {
|
||||
return;
|
||||
}
|
||||
aFrame->SetMayHaveWillChangeBudget(false);
|
||||
|
||||
uint32_t cost = 0;
|
||||
if (!mWillChangeBudgetSet.Get(aFrame, &cost)) {
|
||||
return;
|
||||
}
|
||||
mWillChangeBudgetSet.Remove(aFrame);
|
||||
|
||||
DocumentWillChangeBudget* budget =
|
||||
mWillChangeBudget.GetValue(frameBudget->mPresContext);
|
||||
MOZ_ASSERT(budget);
|
||||
|
||||
budget->mBudget -= frameBudget->mUsage;
|
||||
MOZ_ASSERT(budget->mBudget >= 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayListBuilder::ClearWillChangeBudget()
|
||||
{
|
||||
mWillChangeBudgetSet.Clear();
|
||||
mWillChangeBudget.Clear();
|
||||
DocumentWillChangeBudget& budget =
|
||||
mWillChangeBudget.GetOrInsert(aFrame->PresContext());
|
||||
MOZ_ASSERT(budget.mBudget >= cost);
|
||||
budget.mBudget -= cost;
|
||||
}
|
||||
|
||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
|
|
|
@ -1815,9 +1815,7 @@ public:
|
|||
*/
|
||||
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
|
||||
|
||||
void RemoveFromWillChangeBudget(nsIFrame* aFrame);
|
||||
|
||||
void ClearWillChangeBudget();
|
||||
void ClearWillChangeBudget(nsIFrame* aFrame);
|
||||
|
||||
void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
|
||||
void ExitSVGEffectsContents();
|
||||
|
@ -2042,19 +2040,13 @@ private:
|
|||
|
||||
struct FrameWillChangeBudget
|
||||
{
|
||||
FrameWillChangeBudget()
|
||||
: mPresContext(nullptr)
|
||||
, mUsage(0)
|
||||
{
|
||||
}
|
||||
|
||||
FrameWillChangeBudget(nsPresContext* aPresContext, uint32_t aUsage)
|
||||
: mPresContext(aPresContext)
|
||||
FrameWillChangeBudget(nsIFrame* aFrame, uint32_t aUsage)
|
||||
: mFrame(aFrame)
|
||||
, mUsage(aUsage)
|
||||
{
|
||||
}
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
nsIFrame* mFrame;
|
||||
uint32_t mUsage;
|
||||
};
|
||||
|
||||
|
@ -2092,8 +2084,7 @@ private:
|
|||
|
||||
// Any frame listed in this set is already counted in the budget
|
||||
// and thus is in-budget.
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, FrameWillChangeBudget>
|
||||
mWillChangeBudgetSet;
|
||||
nsDataHashtable<nsPtrHashKey<nsIFrame>, uint32_t> mWillChangeBudgetSet;
|
||||
|
||||
// Area of animated geometry root budget already allocated
|
||||
uint32_t mUsedAGRBudget;
|
||||
|
@ -3368,7 +3359,7 @@ public:
|
|||
/**
|
||||
* Remove all items from the list and call their destructors.
|
||||
*/
|
||||
virtual void DeleteAll(nsDisplayListBuilder* aBuilder);
|
||||
void DeleteAll(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
/**
|
||||
* @return the item at the top of the list, or null if the list is empty
|
||||
|
@ -3763,7 +3754,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
void DeleteAll(nsDisplayListBuilder* aBuilder) override
|
||||
void DeleteAll(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
for (OldItemInfo& i : mOldItems) {
|
||||
if (i.mItem) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче