зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1490404 - Part 2: Add retained display list statistics r=mattwoodrow
Differential Revision: https://phabricator.services.mozilla.com/D33680 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fbfcf25cc9
Коммит
6c57050ada
|
@ -66,7 +66,7 @@ std::string Diagnostics::GetFrameOverlayString(const GPUStats& aStats) {
|
|||
gpuTimeString = nsPrintfCString("%0.1fms", mGPUDrawMs.Average()).get();
|
||||
}
|
||||
|
||||
// DL = nsDisplayListBuilder
|
||||
// DL = nsDisplayListBuilder, p = partial, f = full
|
||||
// FLB = FrameLayerBuilder
|
||||
// R = ClientLayerManager::EndTransaction
|
||||
// CP = ShadowLayerForwarder::EndTransaction (txn build)
|
||||
|
@ -80,17 +80,10 @@ std::string Diagnostics::GetFrameOverlayString(const GPUStats& aStats) {
|
|||
"[CC] Build: %0.1fms Exec: %0.1fms GPU: %s Fill Ratio: %0.1f/%0.1f",
|
||||
mPrepareMs.Average(), mCompositeMs.Average(), gpuTimeString.c_str(),
|
||||
pixelFillRatio, screenFillRatio);
|
||||
nsCString line3;
|
||||
if (mDlb2Ms.Average() != 0.0f) {
|
||||
line3 += nsPrintfCString(
|
||||
"[Content] DL: %0.1f/%0.1fms FLB: %0.1fms Raster: %0.1fms",
|
||||
mDlb2Ms.Average(), mDlbMs.Average(), mFlbMs.Average(),
|
||||
mRasterMs.Average());
|
||||
} else {
|
||||
line3 += nsPrintfCString(
|
||||
"[Content] DL: %0.1fms FLB: %0.1fms Raster: %0.1fms", mDlbMs.Average(),
|
||||
mFlbMs.Average(), mRasterMs.Average());
|
||||
}
|
||||
nsPrintfCString line3(
|
||||
"[Content] DL p: %0.1f DL f: %0.1fms FLB: %0.1fms Raster: %0.1fms",
|
||||
mDlbMs.Average(), mDlb2Ms.Average(), mFlbMs.Average(),
|
||||
mRasterMs.Average());
|
||||
nsPrintfCString line4("[IPDL] Build: %0.1fms Send: %0.1fms Update: %0.1fms",
|
||||
mSerializeMs.Average(), mSendMs.Average(),
|
||||
mUpdateMs.Average());
|
||||
|
|
|
@ -3558,8 +3558,11 @@ struct TemporaryDisplayListBuilder {
|
|||
const bool aBuildCaret)
|
||||
: mBuilder(aFrame, aBuilderMode, aBuildCaret) {}
|
||||
|
||||
~TemporaryDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
|
||||
|
||||
nsDisplayListBuilder mBuilder;
|
||||
nsDisplayList mList;
|
||||
RetainedDisplayListMetrics mMetrics;
|
||||
};
|
||||
|
||||
nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
||||
|
@ -3569,7 +3572,6 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
nsDisplayListBuilderMode aBuilderMode,
|
||||
PaintFrameFlags aFlags) {
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame", GRAPHICS);
|
||||
typedef RetainedDisplayListBuilder::PartialUpdateResult PartialUpdateResult;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (!gPaintCountStack) {
|
||||
|
@ -3620,16 +3622,21 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
Maybe<TemporaryDisplayListBuilder> temporaryBuilder;
|
||||
nsDisplayListBuilder* builder = nullptr;
|
||||
nsDisplayList* list = nullptr;
|
||||
RetainedDisplayListMetrics* metrics = nullptr;
|
||||
|
||||
if (useRetainedBuilder) {
|
||||
builder = retainedBuilder->Builder();
|
||||
list = retainedBuilder->List();
|
||||
metrics = retainedBuilder->Metrics();
|
||||
} else {
|
||||
temporaryBuilder.emplace(aFrame, aBuilderMode, buildCaret);
|
||||
builder = &temporaryBuilder->mBuilder;
|
||||
list = &temporaryBuilder->mList;
|
||||
metrics = &temporaryBuilder->mMetrics;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(builder && list && metrics);
|
||||
|
||||
// Retained builder exists, but display list retaining is disabled.
|
||||
if (!useRetainedBuilder && retainedBuilder) {
|
||||
// Clear the modified frames lists and frame properties.
|
||||
|
@ -3639,6 +3646,9 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
retainedBuilder->List()->DeleteAll(retainedBuilder->Builder());
|
||||
}
|
||||
|
||||
metrics->Reset();
|
||||
metrics->StartBuild();
|
||||
|
||||
builder->BeginFrame();
|
||||
|
||||
if (aFlags & PaintFrameFlags::InTransform) {
|
||||
|
@ -3745,8 +3755,6 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
AUTO_PROFILER_TRACING("Paint", "DisplayList", GRAPHICS);
|
||||
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::DisplayList);
|
||||
TimeStamp dlStart = TimeStamp::Now();
|
||||
|
||||
{
|
||||
// If a scrollable container layer is created in
|
||||
// nsDisplayList::PaintForFrame, it will be the scroll parent for display
|
||||
|
@ -3826,28 +3834,35 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
if (StaticPrefs::LayoutVerifyRetainDisplayList()) {
|
||||
beforeMergeChecker.Set(list, "BM");
|
||||
}
|
||||
|
||||
updateState = retainedBuilder->AttemptPartialUpdate(
|
||||
aBackstop, beforeMergeChecker ? &toBeMergedChecker : nullptr);
|
||||
|
||||
if ((updateState != PartialUpdateResult::Failed) &&
|
||||
beforeMergeChecker) {
|
||||
afterMergeChecker.Set(list, "AM");
|
||||
}
|
||||
|
||||
metrics->EndPartialBuild(updateState);
|
||||
} else {
|
||||
// Partial updates are disabled.
|
||||
metrics->mPartialUpdateResult = PartialUpdateResult::Failed;
|
||||
metrics->mPartialUpdateFailReason = PartialUpdateFailReason::Disabled;
|
||||
}
|
||||
|
||||
if ((updateState != PartialUpdateResult::Failed) &&
|
||||
(StaticPrefs::LayoutDisplayListBuildTwice() || afterMergeChecker)) {
|
||||
updateState = PartialUpdateResult::Failed;
|
||||
if (StaticPrefs::LayersDrawFPS()) {
|
||||
if (RefPtr<LayerManager> lm = builder->GetWidgetLayerManager()) {
|
||||
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(lm)) {
|
||||
pt->dl2Ms() = (TimeStamp::Now() - dlStart).ToMilliseconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
dlStart = TimeStamp::Now();
|
||||
// Rebuild the full display list if the partial display list build failed,
|
||||
// or if the merge checker is used.
|
||||
bool doFullRebuild =
|
||||
updateState == PartialUpdateResult::Failed || afterMergeChecker;
|
||||
|
||||
if (StaticPrefs::LayoutDisplayListBuildTwice()) {
|
||||
// Build display list twice to compare partial and full display list
|
||||
// build times.
|
||||
metrics->StartBuild();
|
||||
doFullRebuild = true;
|
||||
}
|
||||
|
||||
if (updateState == PartialUpdateResult::Failed) {
|
||||
if (doFullRebuild) {
|
||||
list->DeleteAll(builder);
|
||||
|
||||
builder->ClearRetainedWindowRegions();
|
||||
|
@ -3860,6 +3875,8 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
visibleRegion, aBackstop);
|
||||
|
||||
builder->LeavePresShell(aFrame, list);
|
||||
metrics->EndFullBuild();
|
||||
|
||||
updateState = PartialUpdateResult::Updated;
|
||||
|
||||
if (afterMergeChecker) {
|
||||
|
@ -3888,13 +3905,15 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
|
||||
builder->SetIsBuilding(false);
|
||||
builder->IncrementPresShellPaintCount(presShell);
|
||||
}
|
||||
|
||||
if (StaticPrefs::LayersDrawFPS()) {
|
||||
if (RefPtr<LayerManager> lm = builder->GetWidgetLayerManager()) {
|
||||
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(lm)) {
|
||||
pt->dlMs() = (TimeStamp::Now() - dlStart).ToMilliseconds();
|
||||
}
|
||||
}
|
||||
if (StaticPrefs::LayersDrawFPS()) {
|
||||
RefPtr<LayerManager> lm = builder->GetWidgetLayerManager();
|
||||
PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(lm);
|
||||
|
||||
if (pt) {
|
||||
pt->dlMs() = static_cast<float>(metrics->mPartialBuildDuration);
|
||||
pt->dl2Ms() = static_cast<float>(metrics->mFullBuildDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4116,13 +4135,28 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
{
|
||||
AUTO_PROFILER_TRACING("Paint", "DisplayListResources", GRAPHICS);
|
||||
|
||||
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
|
||||
if (!useRetainedBuilder) {
|
||||
list->DeleteAll(builder);
|
||||
}
|
||||
|
||||
builder->EndFrame();
|
||||
|
||||
if (!useRetainedBuilder) {
|
||||
temporaryBuilder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (metrics->mPartialUpdateResult == PartialUpdateResult::Failed) {
|
||||
printf("DL partial update failed: %s, Frame: %p\n",
|
||||
metrics->FailReasonString(), aFrame);
|
||||
} else {
|
||||
printf(
|
||||
"DL partial build success!"
|
||||
" new: %d, reused: %d, rebuilt: %d, removed: %d, total: %d\n",
|
||||
metrics->mNewItems, metrics->mReusedItems, metrics->mRebuiltItems,
|
||||
metrics->mRemovedItems, metrics->mTotalItems);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
}
|
||||
|
||||
item->Destroy(&mBuilder);
|
||||
Metrics()->mRemovedItems++;
|
||||
|
||||
i++;
|
||||
aUpdated = PartialUpdateResult::Updated;
|
||||
|
@ -396,6 +397,7 @@ void OldItemInfo::Discard(RetainedDisplayListBuilder* aBuilder,
|
|||
if (mItem) {
|
||||
MOZ_ASSERT(mOwnsItem);
|
||||
mItem->Destroy(aBuilder->Builder());
|
||||
aBuilder->Metrics()->mRemovedItems++;
|
||||
}
|
||||
mItem = nullptr;
|
||||
}
|
||||
|
@ -436,6 +438,7 @@ class MergeState {
|
|||
HasModifiedFrame(aNewItem));
|
||||
if (!aNewItem->HasModifiedFrame() &&
|
||||
HasMatchingItemInOldList(aNewItem, &oldIndex)) {
|
||||
mBuilder->Metrics()->mRebuiltItems++;
|
||||
nsDisplayItem* oldItem = mOldItems[oldIndex.val].mItem;
|
||||
MOZ_DIAGNOSTIC_ASSERT(oldItem->GetPerFrameKey() ==
|
||||
aNewItem->GetPerFrameKey() &&
|
||||
|
@ -648,6 +651,8 @@ class MergeState {
|
|||
#endif
|
||||
|
||||
mMergedItems.AppendToTop(aItem);
|
||||
mBuilder->Metrics()->mTotalItems++;
|
||||
|
||||
MergedListIndex newIndex =
|
||||
mMergedDAG.AddNode(aDirectPredecessors, aExtraDirectPredecessor);
|
||||
return newIndex;
|
||||
|
@ -671,6 +676,7 @@ class MergeState {
|
|||
mBuilder->IncrementSubDocPresShellPaintCount(item);
|
||||
}
|
||||
item->SetReused(true);
|
||||
mBuilder->Metrics()->mReusedItems++;
|
||||
mOldItems[aNode.val].AddedToMergedList(
|
||||
AddNewNode(item, Some(aNode), aDirectPredecessors, Nothing()));
|
||||
}
|
||||
|
@ -813,6 +819,7 @@ bool RetainedDisplayListBuilder::MergeDisplayLists(
|
|||
|
||||
Maybe<MergedListIndex> previousItemIndex;
|
||||
while (nsDisplayItem* item = aNewList->RemoveBottom()) {
|
||||
Metrics()->mNewItems++;
|
||||
previousItemIndex = merge.ProcessItemFromNewList(item, previousItemIndex);
|
||||
}
|
||||
|
||||
|
@ -1302,11 +1309,26 @@ bool RetainedDisplayListBuilder::ComputeRebuildRegion(
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple early exit heuristic to avoid slow partial display list rebuilds.
|
||||
*/
|
||||
static bool ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames) {
|
||||
bool RetainedDisplayListBuilder::ShouldBuildPartial(
|
||||
nsTArray<nsIFrame*>& aModifiedFrames) {
|
||||
if (mList.IsEmpty()) {
|
||||
// Partial builds without a previous display list do not make sense.
|
||||
Metrics()->mPartialUpdateFailReason = PartialUpdateFailReason::EmptyList;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aModifiedFrames.Length() > StaticPrefs::LayoutRebuildFrameLimit()) {
|
||||
// Computing a dirty rect with too many modified frames can be slow.
|
||||
Metrics()->mPartialUpdateFailReason = PartialUpdateFailReason::RebuildLimit;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't support retaining with overlay scrollbars, since they require
|
||||
// us to look at the display list and pick the highest z-index, which
|
||||
// we can't do during partial building.
|
||||
if (mBuilder.DisablePartialUpdates()) {
|
||||
mBuilder.SetDisablePartialUpdates(false);
|
||||
Metrics()->mPartialUpdateFailReason = PartialUpdateFailReason::Disabled;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1324,6 +1346,7 @@ static bool ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames) {
|
|||
if (type == LayoutFrameType::Viewport ||
|
||||
type == LayoutFrameType::PageContent ||
|
||||
type == LayoutFrameType::Canvas || type == LayoutFrameType::Scrollbar) {
|
||||
Metrics()->mPartialUpdateFailReason = PartialUpdateFailReason::FrameType;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1331,6 +1354,26 @@ static bool ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RetainedDisplayListBuilder::InvalidateCaretFramesIfNeeded(
|
||||
nsTArray<nsIFrame*>& aModifiedFrames) {
|
||||
if (mPreviousCaret == mBuilder.GetCaretFrame()) {
|
||||
// The current caret frame is the same as the previous one.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPreviousCaret &&
|
||||
mBuilder.MarkFrameModifiedDuringBuilding(mPreviousCaret)) {
|
||||
aModifiedFrames.AppendElement(mPreviousCaret);
|
||||
}
|
||||
|
||||
if (mBuilder.GetCaretFrame() &&
|
||||
mBuilder.MarkFrameModifiedDuringBuilding(mBuilder.GetCaretFrame())) {
|
||||
aModifiedFrames.AppendElement(mBuilder.GetCaretFrame());
|
||||
}
|
||||
|
||||
mPreviousCaret = mBuilder.GetCaretFrame();
|
||||
}
|
||||
|
||||
static void ClearFrameProps(nsTArray<nsIFrame*>& aFrames) {
|
||||
for (nsIFrame* f : aFrames) {
|
||||
if (f->HasOverrideDirtyRegion()) {
|
||||
|
@ -1347,13 +1390,10 @@ static void ClearFrameProps(nsTArray<nsIFrame*>& aFrames) {
|
|||
class AutoClearFramePropsArray {
|
||||
public:
|
||||
explicit AutoClearFramePropsArray(size_t aCapacity) : mFrames(aCapacity) {}
|
||||
|
||||
AutoClearFramePropsArray() = default;
|
||||
|
||||
~AutoClearFramePropsArray() { ClearFrameProps(mFrames); }
|
||||
|
||||
nsTArray<nsIFrame*>& Frames() { return mFrames; }
|
||||
|
||||
bool IsEmpty() const { return mFrames.IsEmpty(); }
|
||||
|
||||
private:
|
||||
|
@ -1367,9 +1407,8 @@ void RetainedDisplayListBuilder::ClearFramesWithProps() {
|
|||
&framesWithProps.Frames());
|
||||
}
|
||||
|
||||
auto RetainedDisplayListBuilder::AttemptPartialUpdate(
|
||||
nscolor aBackstop, mozilla::DisplayListChecker* aChecker)
|
||||
-> PartialUpdateResult {
|
||||
PartialUpdateResult RetainedDisplayListBuilder::AttemptPartialUpdate(
|
||||
nscolor aBackstop, mozilla::DisplayListChecker* aChecker) {
|
||||
mBuilder.RemoveModifiedWindowRegions();
|
||||
mBuilder.ClearWindowOpaqueRegion();
|
||||
|
||||
|
@ -1387,33 +1426,11 @@ auto RetainedDisplayListBuilder::AttemptPartialUpdate(
|
|||
GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames.Frames(),
|
||||
&framesWithProps.Frames());
|
||||
|
||||
// Do not allow partial builds if the retained display list is empty, or if
|
||||
// ShouldBuildPartial heuristic fails.
|
||||
bool shouldBuildPartial =
|
||||
!mList.IsEmpty() && ShouldBuildPartial(modifiedFrames.Frames());
|
||||
// Do not allow partial builds if the |ShouldBuildPartial()| heuristic fails.
|
||||
bool shouldBuildPartial = ShouldBuildPartial(modifiedFrames.Frames());
|
||||
|
||||
// We don't support retaining with overlay scrollbars, since they require
|
||||
// us to look at the display list and pick the highest z-index, which
|
||||
// we can't do during partial building.
|
||||
if (mBuilder.DisablePartialUpdates()) {
|
||||
shouldBuildPartial = false;
|
||||
mBuilder.SetDisablePartialUpdates(false);
|
||||
}
|
||||
|
||||
if (mPreviousCaret != mBuilder.GetCaretFrame()) {
|
||||
if (mPreviousCaret) {
|
||||
if (mBuilder.MarkFrameModifiedDuringBuilding(mPreviousCaret)) {
|
||||
modifiedFrames.Frames().AppendElement(mPreviousCaret);
|
||||
}
|
||||
}
|
||||
|
||||
if (mBuilder.GetCaretFrame()) {
|
||||
if (mBuilder.MarkFrameModifiedDuringBuilding(mBuilder.GetCaretFrame())) {
|
||||
modifiedFrames.Frames().AppendElement(mBuilder.GetCaretFrame());
|
||||
}
|
||||
}
|
||||
|
||||
mPreviousCaret = mBuilder.GetCaretFrame();
|
||||
if (shouldBuildPartial) {
|
||||
InvalidateCaretFramesIfNeeded(modifiedFrames.Frames());
|
||||
}
|
||||
|
||||
nsRect modifiedDirty;
|
||||
|
@ -1465,6 +1482,7 @@ auto RetainedDisplayListBuilder::AttemptPartialUpdate(
|
|||
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), nullptr);
|
||||
mList.DeleteAll(&mBuilder);
|
||||
modifiedDL.DeleteAll(&mBuilder);
|
||||
Metrics()->mPartialUpdateFailReason = PartialUpdateFailReason::Content;
|
||||
return PartialUpdateResult::Failed;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,77 @@ RetainedDisplayListData* GetRetainedDisplayListData(nsIFrame* aRootFrame);
|
|||
*/
|
||||
RetainedDisplayListData* GetOrSetRetainedDisplayListData(nsIFrame* aRootFrame);
|
||||
|
||||
enum class PartialUpdateResult { Failed, NoChange, Updated };
|
||||
|
||||
enum class PartialUpdateFailReason {
|
||||
NA,
|
||||
EmptyList,
|
||||
RebuildLimit,
|
||||
FrameType,
|
||||
Disabled,
|
||||
Content
|
||||
};
|
||||
|
||||
struct RetainedDisplayListMetrics {
|
||||
RetainedDisplayListMetrics() { Reset(); }
|
||||
|
||||
void Reset() {
|
||||
mNewItems = 0;
|
||||
mRebuiltItems = 0;
|
||||
mRemovedItems = 0;
|
||||
mReusedItems = 0;
|
||||
mTotalItems = 0;
|
||||
mPartialBuildDuration = 0;
|
||||
mFullBuildDuration = 0;
|
||||
mPartialUpdateFailReason = PartialUpdateFailReason::NA;
|
||||
mPartialUpdateResult = PartialUpdateResult::NoChange;
|
||||
}
|
||||
|
||||
void StartBuild() { mStartTime = mozilla::TimeStamp::Now(); }
|
||||
|
||||
void EndFullBuild() { mFullBuildDuration = Elapsed(); }
|
||||
|
||||
void EndPartialBuild(PartialUpdateResult aResult) {
|
||||
mPartialBuildDuration = Elapsed();
|
||||
mPartialUpdateResult = aResult;
|
||||
}
|
||||
|
||||
double Elapsed() {
|
||||
return (mozilla::TimeStamp::Now() - mStartTime).ToMilliseconds();
|
||||
}
|
||||
|
||||
const char* FailReasonString() const {
|
||||
switch (mPartialUpdateFailReason) {
|
||||
case PartialUpdateFailReason::NA:
|
||||
return "N/A";
|
||||
case PartialUpdateFailReason::EmptyList:
|
||||
return "Empty list";
|
||||
case PartialUpdateFailReason::RebuildLimit:
|
||||
return "Rebuild limit";
|
||||
case PartialUpdateFailReason::FrameType:
|
||||
return "Frame type";
|
||||
case PartialUpdateFailReason::Disabled:
|
||||
return "Disabled";
|
||||
case PartialUpdateFailReason::Content:
|
||||
return "Content";
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Enum value not handled!");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int mNewItems;
|
||||
unsigned int mRebuiltItems;
|
||||
unsigned int mRemovedItems;
|
||||
unsigned int mReusedItems;
|
||||
unsigned int mTotalItems;
|
||||
|
||||
mozilla::TimeStamp mStartTime;
|
||||
double mPartialBuildDuration;
|
||||
double mFullBuildDuration;
|
||||
PartialUpdateFailReason mPartialUpdateFailReason;
|
||||
PartialUpdateResult mPartialUpdateResult;
|
||||
};
|
||||
|
||||
struct RetainedDisplayListBuilder {
|
||||
RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
nsDisplayListBuilderMode aMode, bool aBuildCaret)
|
||||
|
@ -102,7 +173,7 @@ struct RetainedDisplayListBuilder {
|
|||
|
||||
nsDisplayList* List() { return &mList; }
|
||||
|
||||
enum class PartialUpdateResult { Failed, NoChange, Updated };
|
||||
RetainedDisplayListMetrics* Metrics() { return &mMetrics; }
|
||||
|
||||
PartialUpdateResult AttemptPartialUpdate(
|
||||
nscolor aBackstop, mozilla::DisplayListChecker* aChecker);
|
||||
|
@ -118,6 +189,19 @@ struct RetainedDisplayListBuilder {
|
|||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(Cached, RetainedDisplayListBuilder)
|
||||
|
||||
private:
|
||||
void IncrementSubDocPresShellPaintCount(nsDisplayItem* aItem);
|
||||
|
||||
/**
|
||||
* Invalidates the current and previous caret frame if they have changed.
|
||||
*/
|
||||
void InvalidateCaretFramesIfNeeded(nsTArray<nsIFrame*>& aModifiedFrames);
|
||||
|
||||
/**
|
||||
* A simple early exit heuristic to avoid slow partial display list rebuilds.
|
||||
* Returns true if a partial display list build should be attempted.
|
||||
*/
|
||||
bool ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames);
|
||||
|
||||
/**
|
||||
* Recursively pre-processes the old display list tree before building the
|
||||
* new partial display lists, and serializes the old list into an array,
|
||||
|
@ -156,19 +240,19 @@ struct RetainedDisplayListBuilder {
|
|||
nsRect* aOutDirty,
|
||||
AnimatedGeometryRoot** aOutModifiedAGR,
|
||||
nsTArray<nsIFrame*>& aOutFramesWithProps);
|
||||
|
||||
bool ProcessFrame(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aStopAtFrame,
|
||||
nsTArray<nsIFrame*>& aOutFramesWithProps,
|
||||
const bool aStopAtStackingContext, nsRect* aOutDirty,
|
||||
AnimatedGeometryRoot** aOutModifiedAGR);
|
||||
|
||||
void IncrementSubDocPresShellPaintCount(nsDisplayItem* aItem);
|
||||
|
||||
friend class MergeState;
|
||||
|
||||
nsDisplayListBuilder mBuilder;
|
||||
RetainedDisplayList mList;
|
||||
WeakFrame mPreviousCaret;
|
||||
RetainedDisplayListMetrics mMetrics;
|
||||
};
|
||||
|
||||
#endif // RETAINEDDISPLAYLISTBUILDER_H_
|
||||
|
|
Загрузка…
Ссылка в новой задаче