Bug 957668. Set the display port base rect in several places. r=roc
authorTimothy Nikkel <tnikkel@gmail.com>
Wed, 26 Mar 2014 21:46:24 -0400
changeset 175592 f9aee922c83bc59d1856c615f1575074cb162233
parent 175591 4a75c46797d127d92ae8bbe0293d7219239c03a6
child 175593 77ca7f1eda031c512c1813a2245309a7378acb7d
push id26494
push usercbook@mozilla.com
push dateThu, 27 Mar 2014 13:09:48 +0000
treeherdermozilla-central@d2ecc6d31622 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs957668
milestone31.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 957668. Set the display port base rect in several places. r=roc
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsSubDocumentFrame.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -755,16 +755,23 @@ nsLayoutUtils::GetDisplayPort(nsIContent
         *aResult = result;
       }
     }
   }
 
   return true;
 }
 
+void
+nsLayoutUtils::SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase)
+{
+  aContent->SetProperty(nsGkAtoms::DisplayPortBase, new nsRect(aBase),
+                        nsINode::DeleteProperty<nsRect>);
+}
+
 bool
 nsLayoutUtils::GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult)
 {
   void* property = aContent->GetProperty(nsGkAtoms::CriticalDisplayPort);
   if (!property) {
     return false;
   }
 
@@ -2368,17 +2375,22 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   }
 
   nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
   bool usingDisplayPort = false;
   nsRect displayport;
   if (rootScrollFrame && !aFrame->GetParent()) {
     nsIContent* content = rootScrollFrame->GetContent();
     if (content) {
-      usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayport);
+      usingDisplayPort = nsLayoutUtils::GetDisplayPort(content);
+      if (usingDisplayPort) {
+        nsLayoutUtils::SetDisplayPortBase(content,
+          nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)));
+        nsLayoutUtils::GetDisplayPort(content, &displayport);
+      }
     }
   }
 
   nsRegion visibleRegion;
   if (aFlags & PAINT_WIDGET_LAYERS) {
     // This layer tree will be reused, so we'll need to calculate it
     // for the whole "visible" area of the window
     // 
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -145,16 +145,22 @@ public:
    */
   static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
 
   /**
    * Get display port for the given element.
    */
   static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult = nullptr);
 
+ /**
+  * Set the display port base rect for given element to be used with display
+  * port margins.
+  */
+ static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
+
   /**
    * Get the critical display port for the given element.
    */
   static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult = nullptr);
 
   /**
    * Use heuristics to figure out the child list that
    * aChildFrame is currently in.
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2453,20 +2453,31 @@ ScrollFrameHelper::BuildDisplayList(nsDi
   // Not all our descendants will be clipped by overflow clipping, but all
   // the ones that aren't clipped will be out of flow frames that have already
   // had dirty rects saved for them by their parent frames calling
   // MarkOutOfFlowChildrenForDisplayList, so it's safe to restrict our
   // dirty rect here.
   nsRect dirtyRect = aDirtyRect.Intersect(mScrollPort);
 
   // Override the dirty rectangle if the displayport has been set.
+  bool usingDisplayport =
+    nsLayoutUtils::GetDisplayPort(mOuter->GetContent()) &&
+    !aBuilder->IsForEventDelivery();
+
+  // don't set the display port base rect for root scroll frames,
+  // nsLayoutUtils::PaintFrame or nsSubDocumentFrame::BuildDisplayList
+  // does that for root scroll frames before it expands the dirty rect
+  // to the display port.
+  if (usingDisplayport && !mIsRoot) {
+    nsLayoutUtils::SetDisplayPortBase(mOuter->GetContent(), dirtyRect);
+  }
+
+  // now that we have an updated base rect we can get the display port
   nsRect displayPort;
-  bool usingDisplayport =
-    nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort) &&
-    !aBuilder->IsForEventDelivery();
+  nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
   if (usingDisplayport && DisplayportExceedsMaxTextureSize(mOuter->PresContext(), displayPort)) {
     usingDisplayport = false;
   }
   if (usingDisplayport) {
     dirtyRect = displayPort;
   }
 
   if (aBuilder->IsForImageVisibility()) {
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -371,28 +371,34 @@ nsSubDocumentFrame::BuildDisplayList(nsD
   int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
   int32_t subdocAPD = presContext->AppUnitsPerDevPixel();
 
   nsRect dirty;
   bool haveDisplayPort = false;
   bool ignoreViewportScrolling = false;
   nsIFrame* savedIgnoreScrollFrame = nullptr;
   if (subdocRootFrame) {
-    nsRect displayPort;
-    if (nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort)) {
+    // get the dirty rect relative to the root frame of the subdoc
+    dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
+    // and convert into the appunits of the subdoc
+    dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
+
+    nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
+    if (nsLayoutUtils::ViewportHasDisplayPort(presContext)) {
       haveDisplayPort = true;
+      // for root content documents we want the base to be the composition bounds
+      nsLayoutUtils::SetDisplayPortBase(rootScrollFrame->GetContent(),
+        presContext->IsRootContentDocument() ?
+          nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)) :
+          dirty);
+      nsRect displayPort;
+      nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort);
       dirty = displayPort;
-    } else {
-      // get the dirty rect relative to the root frame of the subdoc
-      dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
-      // and convert into the appunits of the subdoc
-      dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
     }
 
-    nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
     ignoreViewportScrolling =
       rootScrollFrame && presShell->IgnoringViewportScrolling();
     if (ignoreViewportScrolling) {
       savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
       aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
     }
 
     aBuilder->EnterPresShell(subdocRootFrame, dirty);