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.
frame->SchedulePaint();
if (!gfxPrefs::LayoutRetainDisplayList()) {
return;
}
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);
}
if (!retainedBuilder) {
return;
}
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

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

@ -760,6 +760,20 @@ ShouldBuildPartial(nsTArray<nsIFrame*>& aModifiedFrames)
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
RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
{
@ -773,7 +787,10 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
nsTArray<nsIFrame*> modifiedFrames =
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) {
@ -795,8 +812,9 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
AnimatedGeometryRoot* modifiedAGR = nullptr;
nsTArray<nsIFrame*> framesWithProps;
bool merged = false;
if (shouldBuildPartial && !mList.IsEmpty() &&
ComputeRebuildRegion(modifiedFrames, &modifiedDirty, &modifiedAGR, &framesWithProps)) {
if (shouldBuildPartial &&
ComputeRebuildRegion(modifiedFrames, &modifiedDirty,
&modifiedAGR, &framesWithProps)) {
modifiedDirty.IntersectRect(modifiedDirty, mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf());
PreProcessDisplayList(&mList, modifiedAGR);
@ -838,21 +856,11 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList);
// TODO: Do we mark frames as modified during displaylist building? If
// we do this isn't gonna work.
for (nsIFrame* f : modifiedFrames) {
if (f) {
f->SetFrameIsModified(false);
}
}
// 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());
}
// 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.
ClearFrameProps(modifiedFrames);
ClearFrameProps(framesWithProps);
return merged;
}