Add logging for ComputeRebuildRegion
authorMatt Woodrow <>
Tue, 19 Sep 2017 11:34:31 +1200
changeset 685640 3e66c3bb56881547abf5c8e0fcc4190d13fa392a
parent 685639 4dbe9ae4248c0f5205342494ba4031539bc1e991
child 685641 224aa41383ca2b5483a5eec16823877ef4ea5fa7
push id86010
push dateWed, 25 Oct 2017 00:44:42 +0000
Add logging for ComputeRebuildRegion
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4056,38 +4056,49 @@ GetModifiedFrames(nsIFrame* aDisplayRoot
   if (rootdoc) {
     rootdoc->EnumerateSubDocuments(SubDocEnumCb, &modifiedFrames);
   return modifiedFrames;
+// ComputeRebuildRegion  debugging
+// #define CRR_DEBUG 0
+#  define CRR_LOG(...) printf_stderr(__VA_ARGS__)
+#  define CRR_LOG(...)
 static bool
 ComputeRebuildRegion(nsDisplayListBuilder& aBuilder,
                      std::vector<WeakFrame>& aModifiedFrames,
                      nsIFrame* aDisplayRootFrame,
                      const nsRect& aRootDirtyRect,
                      nsRect* aOutDirty,
                      AnimatedGeometryRoot** aOutModifiedAGR,
                      nsTArray<nsIFrame*>* aOutFramesWithProps)
+  CRR_LOG("Computing rebuild regions for %d frames:\n", aModifiedFrames.size());
   for (nsIFrame* f : aModifiedFrames) {
     if (!f) {
     if (f->HasOverrideDirtyRegion()) {
     // TODO: There is almost certainly a faster way of doing this, probably can be combined with the ancestor
     // walk for TransformFrameRectToAncestor.
     AnimatedGeometryRoot* agr = aBuilder.FindAnimatedGeometryRootFor(f)->GetAsyncAGR();
+    CRR_LOG("Processing frame %p with agr %p\n", f, agr->mFrame);
     // Convert the frame's overflow rect into the coordinate space
     // of the nearest stacking context that has an existing display item.
     // We store the overflow rect on that stacking context so that we build
     // all items that intersect that changed frame within the stacking context,
     // and then we use MarkFrameForDisplayIfVisible to make sure the stacking
     // context itself gets built. We don't need to build items that intersect outside
     // of the stacking context, since we know the stacking context item exists in
@@ -4098,16 +4109,17 @@ ComputeRebuildRegion(nsDisplayListBuilde
     while (currentFrame != aDisplayRootFrame) {
       overflow = nsLayoutUtils::TransformFrameRectToAncestor(currentFrame, overflow, aDisplayRootFrame,
                                                              nullptr, nullptr,
                                                              /* aStopAtStackingContextAndDisplayPort = */ true,
       if (nsLayoutUtils::FrameHasDisplayPort(currentFrame)) {
+        CRR_LOG("Frame belongs to displayport frame %p\n", currentFrame);
         nsIScrollableFrame* sf = do_QueryFrame(currentFrame);
         nsRect displayPort;
         DebugOnly<bool> hasDisplayPort =
           nsLayoutUtils::GetDisplayPort(currentFrame->GetContent(), &displayPort, RelativeTo::ScrollPort);
         // get it relative to the scrollport (from the scrollframe)
         nsRect r = overflow - sf->GetScrollPortRect().TopLeft();
@@ -4117,29 +4129,31 @@ ComputeRebuildRegion(nsDisplayListBuilde
           if (!rect) {
             rect = new nsRect();
             currentFrame->SetProperty(nsDisplayListBuilder::DisplayListBuildingDisplayPortRect(), rect);
           rect->UnionRect(*rect, r);
+          CRR_LOG("Adding area to displayport draw area: %d %d %d %d\n", r.x, r.y, r.width, r.height);
           // TODO: Can we just use MarkFrameForDisplayIfVisible, plus MarkFramesForDifferentAGR to
           // ensure that this displayport, plus any items that move relative to it get rebuilt,
           // and then not contribute to the root dirty area?
           overflow = sf->GetScrollPortRect();
         } else {
           // Don't contribute to the root dirty area at all.
       if (currentFrame->IsStackingContext()) {
+        CRR_LOG("Frame belongs to stacking context frame %p\n", currentFrame);
         // If we found an intermediate stacking context with an existing display item
         // then we can store the dirty rect there and stop.
         if (currentFrame != aDisplayRootFrame &&
             currentFrame->RealDisplayItemData().Length() != 0) {
           // Store the stacking context relative dirty area such
           // that display list building will pick it up when it
@@ -4148,38 +4162,42 @@ ComputeRebuildRegion(nsDisplayListBuilde
           if (!data) {
             data = new nsDisplayListBuilder::DisplayListBuildingData;
             currentFrame->SetProperty(nsDisplayListBuilder::DisplayListBuildingRect(), data);
           data->mDirtyRect.UnionRect(data->mDirtyRect, overflow);
+          CRR_LOG("Adding area to stacking context draw area: %d %d %d %d\n", overflow.x, overflow.y, overflow.width, overflow.height);
           if (!data->mModifiedAGR) {
             data->mModifiedAGR = agr;
           } else if (data->mModifiedAGR != agr) {
             data->mDirtyRect = currentFrame->GetVisualOverflowRectRelativeToSelf();
+            CRR_LOG("Found multiple modified AGRs within this stacking context, giving up\n");
           // Don't contribute to the root dirty area at all.
           agr = nullptr;
     aOutDirty->UnionRect(*aOutDirty, overflow);
+    CRR_LOG("Adding area to root draw area: %d %d %d %d\n", overflow.x, overflow.y, overflow.width, overflow.height);
     // If we get changed frames from multiple AGRS, then just give up as it gets really complex to
     // track which items would need to be marked in MarkFramesForDifferentAGR.
     // TODO: We should store the modifiedAGR on the per-stacking context data and only do the
     // marking within the scope of the current stacking context.
     if (!*aOutModifiedAGR) {
       *aOutModifiedAGR = agr;
     } else if (agr && *aOutModifiedAGR != agr) {
+      CRR_LOG("Found multiple AGRs in root stacking context, giving up\n");
       return false;
   return true;
 void MarkFramesWithItemsAndImagesModified(nsDisplayList* aList)