Bug 1307242 - Call nsPresContext::NotifyNonBlankPaint when building the display list for a presshell that contains more than just canvas backgrounds. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Wed, 09 Nov 2016 22:46:26 -0500
changeset 322176 10dd4c02d4b635ed79599ed5b9b2756bb272c3b8
parent 322175 0318d13a32f95f4afe7f36d983ebd154b721bc07
child 322177 aa04cab9513bb57d300076b2ded9f217b2039778
push id83800
push usermstange@themasta.com
push dateFri, 11 Nov 2016 18:28:07 +0000
treeherdermozilla-inbound@447eb26dd36a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1307242
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1307242 - Call nsPresContext::NotifyNonBlankPaint when building the display list for a presshell that contains more than just canvas backgrounds. r=mattwoodrow MozReview-Commit-ID: LLmt3ooMxL3
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsLayoutUtils.cpp
layout/base/nsPresShell.cpp
layout/generic/nsSubDocumentFrame.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1022,23 +1022,57 @@ nsDisplayListBuilder::EnterPresShell(nsI
   nsPresContext* pc = aReferenceFrame->PresContext();
   nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
   if (docShell) {
     docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
   }
   mIsInChromePresContext = pc->IsChrome();
 }
 
+// A non-blank paint is a paint that does not just contain the canvas background.
+static bool
+DisplayListIsNonBlank(nsDisplayList* aList)
+{
+  for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
+    switch (i->GetType()) {
+      case nsDisplayItem::TYPE_LAYER_EVENT_REGIONS:
+      case nsDisplayItem::TYPE_CANVAS_BACKGROUND_COLOR:
+      case nsDisplayItem::TYPE_CANVAS_BACKGROUND_IMAGE:
+        continue;
+      case nsDisplayItem::TYPE_SOLID_COLOR:
+      case nsDisplayItem::TYPE_BACKGROUND:
+      case nsDisplayItem::TYPE_BACKGROUND_COLOR:
+        if (i->Frame()->GetType() == nsGkAtoms::canvasFrame) {
+          continue;
+        }
+        return true;
+      default:
+        return true;
+    }
+  }
+  return false;
+}
+
 void
-nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame)
+nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents)
 {
   NS_ASSERTION(CurrentPresShellState()->mPresShell ==
       aReferenceFrame->PresContext()->PresShell(),
       "Presshell mismatch");
 
+  if (mIsPaintingToWindow) {
+    nsPresContext* pc = aReferenceFrame->PresContext();
+    if (!pc->HadNonBlankPaint()) {
+      if (!CurrentPresShellState()->mIsBackgroundOnly &&
+          DisplayListIsNonBlank(aPaintedContents)) {
+        pc->NotifyNonBlankPaint();
+      }
+    }
+  }
+
   ResetMarkedFramesForDisplayList();
   mPresShellStates.SetLength(mPresShellStates.Length() - 1);
 
   if (!mPresShellStates.IsEmpty()) {
     nsPresContext* pc = CurrentPresContext();
     nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
     if (docShell) {
       docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -531,17 +531,17 @@ public:
    * clipping. Between each such batch of items, call
    * ResetMarkedFramesForDisplayList to make sure that the results of
    * MarkFramesForDisplayList do not carry over between batches.
    */
   void ResetMarkedFramesForDisplayList();
   /**
    * Notify the display list builder that we're leaving a presshell.
    */
-  void LeavePresShell(nsIFrame* aReferenceFrame);
+  void LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents);
 
   /**
    * Returns true if we're currently building a display list that's
    * directly or indirectly under an nsDisplayTransform.
    */
   bool IsInTransform() const { return mInTransform; }
   /**
    * Indicate whether or not we're directly or indirectly under and
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3180,17 +3180,17 @@ nsLayoutUtils::GetFramesForArea(nsIFrame
     }
   }
   if (aFlags & IGNORE_CROSS_DOC) {
     builder.SetDescendIntoSubdocuments(false);
   }
 
   builder.EnterPresShell(aFrame);
   aFrame->BuildDisplayListForStackingContext(&builder, aRect, &list);
-  builder.LeavePresShell(aFrame);
+  builder.LeavePresShell(aFrame, nullptr);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gDumpEventList) {
     fprintf_stderr(stderr, "Event handling --- (%d,%d):\n", aRect.x, aRect.y);
 
     std::stringstream ss;
     nsFrame::PrintDisplayList(&builder, list, ss);
     print_stderr(ss);
@@ -3560,17 +3560,17 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
     // can monkey with the contents if necessary.
     canvasArea.IntersectRect(canvasArea, visibleRegion.GetBounds());
     nsDisplayListBuilder::AutoBuildingDisplayList
       buildingDisplayList(&builder, aFrame, canvasArea, false);
     presShell->AddCanvasBackgroundColorItem(
            builder, list, aFrame, canvasArea, aBackstop);
   }
 
-  builder.LeavePresShell(aFrame);
+  builder.LeavePresShell(aFrame, &list);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,
                                  startBuildDisplayList);
 
   bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump");
   bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint();
 #ifdef MOZ_DUMP_PAINTING
   FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
 #endif
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4935,17 +4935,17 @@ PresShell::CreateRangePaintInfo(nsIDOMRa
   if (gDumpRangePaintList) {
     fprintf(stderr, "CreateRangePaintInfo --- before ClipListToRange:\n");
     nsFrame::PrintDisplayList(&(info->mBuilder), info->mList);
   }
 #endif
 
   nsRect rangeRect = ClipListToRange(&info->mBuilder, &info->mList, range);
 
-  info->mBuilder.LeavePresShell(ancestorFrame);
+  info->mBuilder.LeavePresShell(ancestorFrame, &info->mList);
 
 #ifdef DEBUG
   if (gDumpRangePaintList) {
     fprintf(stderr, "CreateRangePaintInfo --- after ClipListToRange:\n");
     nsFrame::PrintDisplayList(&(info->mBuilder), info->mList);
   }
 #endif
 
@@ -6058,20 +6058,20 @@ PresShell::DoUpdateApproximateFrameVisib
         RelativeTo::ScrollFrame);
     }
 
     if (IgnoringViewportScrolling()) {
       builder.SetIgnoreScrollFrame(rootScroll);
     }
   }
   builder.IgnorePaintSuppression();
-  builder.EnterPresShell(rootFrame, updateRect);
+  builder.EnterPresShell(rootFrame);
   nsDisplayList list;
   rootFrame->BuildDisplayListForStackingContext(&builder, updateRect, &list);
-  builder.LeavePresShell(rootFrame, updateRect);
+  builder.LeavePresShell(rootFrame, &list);
 
   RebuildApproximateFrameVisibilityDisplayList(list);
 
   ClearApproximateFrameVisibilityVisited(rootFrame->GetView(), true);
 
   list.DeleteAll();
 #endif
 }
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -500,17 +500,17 @@ nsSubDocumentFrame::BuildDisplayList(nsD
         uint32_t flags = nsIPresShell::FORCE_DRAW;
         presShell->AddCanvasBackgroundColorItem(
           *aBuilder, childItems, frame, bounds, NS_RGBA(0,0,0,0), flags);
       }
     }
   }
 
   if (subdocRootFrame) {
-    aBuilder->LeavePresShell(subdocRootFrame);
+    aBuilder->LeavePresShell(subdocRootFrame, &childItems);
 
     if (ignoreViewportScrolling) {
       aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
     }
   }
 
   // Generate a resolution and/or zoom item if needed. If one or both of those is
   // created, we don't need to create a separate nsDisplaySubDocument.