Bug 1416065 - Ensure that override dirty rects are properly removed from frames r=mattwoodrow

MozReview-Commit-ID: 8uLgDFxl5MV

--HG--
extra : rebase_source : f8b1202e068b448499ebe470c9d9151715cb1419
This commit is contained in:
Miko Mynttinen 2017-11-10 01:32:29 +01:00
Родитель c94238ae4f
Коммит c94a72556d
2 изменённых файлов: 51 добавлений и 35 удалений

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

@ -1400,28 +1400,36 @@ nsLayoutUtils::InvalidateForDisplayPortChange(nsIContent* aContent,
// rect properties on so we can find the frame later to remove the properties. // rect properties on so we can find the frame later to remove the properties.
frame->SchedulePaint(); frame->SchedulePaint();
if (!gfxPrefs::LayoutRetainDisplayList()) {
return;
}
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(frame); nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(frame);
RetainedDisplayListBuilder* retainedBuilder = RetainedDisplayListBuilder* retainedBuilder =
displayRoot->GetProperty(RetainedDisplayListBuilder::Cached()); displayRoot->GetProperty(RetainedDisplayListBuilder::Cached());
if (retainedBuilder) {
nsRect* rect = if (!retainedBuilder) {
frame->GetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect()); return;
if (!rect) { }
rect = new nsRect();
frame->SetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect(), rect); nsRect* rect =
frame->SetHasOverrideDirtyRegion(true); frame->GetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect());
}
if (aHadDisplayPort) { if (!rect) {
// We only need to build a display list for any new areas added rect = new nsRect();
nsRegion newRegion(aNewDisplayPort); frame->SetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect(), rect);
newRegion.SubOut(aOldDisplayPort); frame->SetHasOverrideDirtyRegion(true);
rect->UnionRect(*rect, newRegion.GetBounds()); }
} else {
rect->UnionRect(*rect, aNewDisplayPort); 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 bool

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

@ -760,6 +760,20 @@ ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames)
return true; return true;
} }
static void
ClearFrameProps(nsTArray<nsIFrame*>& aFrames)
{
for (nsIFrame* f : aFrames) {
if (f->HasOverrideDirtyRegion()) {
f->SetHasOverrideDirtyRegion(false);
f->DeleteProperty(nsDisplayListBuilder::DisplayListBuildingRect());
f->DeleteProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect());
}
f->SetFrameIsModified(false);
}
}
bool bool
RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop) RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
{ {
@ -773,7 +787,10 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
nsTArray<nsIFrame*> modifiedFrames = nsTArray<nsIFrame*> modifiedFrames =
GetModifiedFrames(mBuilder.RootReferenceFrame()); GetModifiedFrames(mBuilder.RootReferenceFrame());
const bool shouldBuildPartial = ShouldBuildPartial(modifiedFrames); // Do not allow partial builds if the retained display list is empty, or if
// ShouldBuildPartial heuristic fails.
const bool shouldBuildPartial =
!mList.IsEmpty() && ShouldBuildPartial(modifiedFrames);
if (mPreviousCaret != mBuilder.GetCaretFrame()) { if (mPreviousCaret != mBuilder.GetCaretFrame()) {
if (mPreviousCaret) { if (mPreviousCaret) {
@ -795,8 +812,9 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
AnimatedGeometryRoot* modifiedAGR = nullptr; AnimatedGeometryRoot* modifiedAGR = nullptr;
nsTArray<nsIFrame*> framesWithProps; nsTArray<nsIFrame*> framesWithProps;
bool merged = false; bool merged = false;
if (shouldBuildPartial && !mList.IsEmpty() && if (shouldBuildPartial &&
ComputeRebuildRegion(modifiedFrames, &modifiedDirty, &modifiedAGR, &framesWithProps)) { ComputeRebuildRegion(modifiedFrames, &modifiedDirty,
&modifiedAGR, &framesWithProps)) {
modifiedDirty.IntersectRect(modifiedDirty, mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf()); modifiedDirty.IntersectRect(modifiedDirty, mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf());
PreProcessDisplayList(&mList, modifiedAGR); PreProcessDisplayList(&mList, modifiedAGR);
@ -838,21 +856,11 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList); mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList);
// TODO: Do we mark frames as modified during displaylist building? If // We set the override dirty regions during ComputeRebuildRegion or in
// we do this isn't gonna work. // nsLayoutUtils::InvalidateForDisplayPortChange. The display port change also
for (nsIFrame* f : modifiedFrames) { // marks the frame modified, so those regions are cleared here as well.
if (f) { ClearFrameProps(modifiedFrames);
f->SetFrameIsModified(false); ClearFrameProps(framesWithProps);
}
}
// Override dirty regions should only exist during this function. We set them up during
// ComputeRebuildRegion, and clear them here.
for (nsIFrame* f: framesWithProps) {
f->SetHasOverrideDirtyRegion(false);
f->DeleteProperty(nsDisplayListBuilder::DisplayListBuildingRect());
f->DeleteProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect());
}
return merged; return merged;
} }