Bug 1404181 - Part 23: Only rebuild items within a displayport when the displayport changes, rather than rebuilding the whole document. r=mstange

MozReview-Commit-ID: IYEPCKSvtBY

--HG--
extra : rebase_source : f6b65a88dcd82b7828af371874bf3adde2af688f
This commit is contained in:
Matt Woodrow ext:(%2C%20Miko%20Mynttinen%20%3Cmikokm%40gmail.com%3E%2C%20Timothy%20Nikkel%20%3Ctnikkel%40gmail.com%3E) 2017-09-29 10:54:15 +13:00
Родитель 3fa03bb34e
Коммит 4dc75f2d67
4 изменённых файлов: 69 добавлений и 13 удалений

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

@ -474,6 +474,9 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
}
}
nsLayoutUtils::InvalidateForDisplayPortChange(content, !!currentData,
currentData ? currentData->mRect : nsRect(), displayport);
nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
if (rootFrame) {
rootFrame->SchedulePaint();

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

@ -1375,6 +1375,54 @@ nsLayoutUtils::GetDisplayPortForVisibilityTesting(
return usingDisplayPort;
}
void
nsLayoutUtils::InvalidateForDisplayPortChange(nsIContent* aContent,
bool aHadDisplayPort,
const nsRect& aOldDisplayPort,
const nsRect& aNewDisplayPort,
RepaintMode aRepaintMode)
{
if (aRepaintMode != RepaintMode::Repaint) {
return;
}
bool changed = !aHadDisplayPort ||
!aOldDisplayPort.IsEqualEdges(aNewDisplayPort);
nsIFrame* frame = GetScrollFrameFromContent(aContent);
if (frame) {
frame = do_QueryFrame(frame->GetScrollTargetFrame());
}
if (changed && frame) {
// It is important to call SchedulePaint on the same frame that we set the dirty
// rect properties on so we can find the frame later to remove the properties.
frame->SchedulePaint();
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(frame);
RetainedDisplayListBuilder* retainedBuilder =
displayRoot->GetProperty(RetainedDisplayListBuilder::Cached());
if (retainedBuilder) {
nsRect* rect =
frame->GetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect());
if (!rect) {
rect = new nsRect();
frame->SetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect(), rect);
frame->SetHasOverrideDirtyRegion(true);
}
if (aHadDisplayPort) {
// We only need to build a display list for any new areas added
nsRegion newRegion(aNewDisplayPort);
newRegion.SubOut(aOldDisplayPort);
rect->UnionRect(*rect, newRegion.GetBounds());
} else {
rect->UnionRect(*rect, aNewDisplayPort);
}
}
}
}
bool
nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent,
nsIPresShell* aPresShell,
@ -1403,9 +1451,6 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent,
DebugOnly<bool> hasDisplayPort = GetHighResolutionDisplayPort(aContent, &newDisplayPort);
MOZ_ASSERT(hasDisplayPort);
bool changed = !hadDisplayPort ||
!oldDisplayPort.IsEqualEdges(newDisplayPort);
if (gfxPrefs::LayoutUseContainersForRootFrames()) {
nsIFrame* rootScrollFrame = aPresShell->GetRootScrollFrame();
if (rootScrollFrame &&
@ -1419,12 +1464,8 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent,
}
}
if (changed && aRepaintMode == RepaintMode::Repaint) {
nsIFrame* frame = aContent->GetPrimaryFrame();
if (frame) {
frame->SchedulePaint();
}
}
InvalidateForDisplayPortChange(aContent, hadDisplayPort, oldDisplayPort,
newDisplayPort, aRepaintMode);
nsIFrame* frame = GetScrollFrameFromContent(aContent);
nsIScrollableFrame* scrollableFrame = frame ? frame->GetScrollTargetFrame() : nullptr;
@ -3723,7 +3764,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
MaybeCreateDisplayPortInFirstScrollFrameEncountered(aFrame, builder);
}
nsRect dirtyRect = visibleRegion.GetBounds();
nsRect visibleRect = visibleRegion.GetBounds();
{
AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame:BuildDisplayList",
@ -3760,7 +3801,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id);
builder.SetVisibleRect(dirtyRect);
builder.SetVisibleRect(visibleRect);
builder.SetIsBuilding(true);
const bool paintedPreviously =
@ -3777,7 +3818,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
if (!merged) {
list.DeleteAll(&builder);
builder.EnterPresShell(aFrame);
builder.SetDirtyRect(dirtyRect);
builder.SetDirtyRect(visibleRect);
builder.ClearWindowDraggingRegion();
aFrame->BuildDisplayListForStackingContext(&builder, &list);
AddExtraBackgroundItems(builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
@ -3838,7 +3879,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
}
#endif
*ss << nsPrintfCString("Painting --- before optimization (dirty %d,%d,%d,%d):\n",
dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height).get();
visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height).get();
nsFrame::PrintDisplayList(&builder, list, *ss, gfxEnv::DumpPaintToFile());
if (gfxEnv::DumpPaint() || gfxEnv::DumpPaintItems()) {

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

@ -252,6 +252,15 @@ public:
DoNotRepaint
};
/**
* Invalidate for displayport change.
*/
static void InvalidateForDisplayPortChange(nsIContent* aContent,
bool aHadDisplayPort,
const nsRect& aOldDisplayPort,
const nsRect& aNewDisplayPort,
RepaintMode aRepaintMode = RepaintMode::Repaint);
/**
* Set the display port margins for a content element to be used with a
* display port base (see SetDisplayPortBase()).

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

@ -3302,6 +3302,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
// It's safe to get this value before the DecideScrollableLayer call below
// because that call cannot create a displayport for root scroll frames,
// and hence it cannot create an ignore scroll frame.
bool ignoringThisScrollFrame =
aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping();