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:
Gurzau Raul 2018-09-17 16:57:58 +03:00
Родитель 2237676d3a
Коммит da0121c598
8 изменённых файлов: 149 добавлений и 223 удалений

Просмотреть файл

@ -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) {