Bug 1002992. Part 2. Handle display ports and ignore viewport scrolling for image visibility display lists the same way we do for painting display lists. r=mats
authorTimothy Nikkel <tnikkel@gmail.com>
Fri, 06 Jun 2014 21:23:20 -0500
changeset 187309 1fabb6ff29cd1480a79b17c636a6642063d5a601
parent 187308 397d00aa598fce9d34f9a37c89ccdba43c5f5bf4
child 187310 a95c4223dba7aea9d6fb432c24a70dbcc4bce8af
push id44563
push usertnikkel@gmail.com
push dateSat, 07 Jun 2014 02:24:23 +0000
treeherdermozilla-inbound@47fcf180a0b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1002992
milestone32.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 1002992. Part 2. Handle display ports and ignore viewport scrolling for image visibility display lists the same way we do for painting display lists. r=mats
layout/base/nsPresShell.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
layout/generic/nsSubDocumentFrame.cpp
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5733,18 +5733,33 @@ PresShell::UpdateImageVisibility()
   nsIFrame* rootFrame = GetRootFrame();
   if (!rootFrame) {
     ClearVisibleImagesList();
     return;
   }
 
   // We could walk the frame tree directly and skip creating a display list for
   // better perf.
+  nsDisplayListBuilder builder(rootFrame, nsDisplayListBuilder::IMAGE_VISIBILITY, true);
   nsRect updateRect(nsPoint(0, 0), rootFrame->GetSize());
-  nsDisplayListBuilder builder(rootFrame, nsDisplayListBuilder::IMAGE_VISIBILITY, true);
+  nsIFrame* rootScroll = GetRootScrollFrame();
+  if (rootScroll) {
+    nsIContent* content = rootScroll->GetContent();
+    if (content) {
+      nsLayoutUtils::GetDisplayPort(content, &updateRect);
+    }
+
+    if (IgnoringViewportScrolling()) {
+      builder.SetIgnoreScrollFrame(rootScroll);
+      // The ExpandRect that the root scroll frame would do gets short circuited
+      // due to us ignoring the root scroll frame, so we do it here.
+      nsIScrollableFrame* rootScrollable = do_QueryFrame(rootScroll);
+      updateRect = rootScrollable->ExpandRect(updateRect);
+    }
+  }
   builder.IgnorePaintSuppression();
   builder.EnterPresShell(rootFrame, updateRect);
   nsDisplayList list;
   rootFrame->BuildDisplayListForStackingContext(&builder, updateRect, &list);
   builder.LeavePresShell(rootFrame, updateRect);
 
   RebuildImageVisibility(list);
 
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -274,16 +274,17 @@ public:
     mScrollPosForLayerPixelAlignment = GetScrollPosition();
   }
 
   bool UpdateOverflow();
 
   void UpdateSticky();
 
   bool IsRectNearlyVisible(const nsRect& aRect) const;
+  nsRect ExpandRect(const nsRect& aRect) const;
 
   // adjust the scrollbar rectangle aRect to account for any visible resizer.
   // aHasResizer specifies if there is a content resizer, however this method
   // will also check if a widget resizer is present as well.
   void AdjustScrollbarRectForResizer(nsIFrame* aFrame, nsPresContext* aPresContext,
                                      nsRect& aRect, bool aHasResizer, bool aVertical);
   // returns true if a resizer should be visible
   bool HasResizer() { return mResizerBox && !mCollapsedResizer; }
@@ -415,17 +416,16 @@ protected:
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollToWithOrigin(nsPoint aScrollPosition,
                           nsIScrollableFrame::ScrollMode aMode,
                           nsIAtom *aOrigin, // nullptr indicates "other" origin
                           const nsRect* aRange);
 
-  nsRect ExpandRect(const nsRect& aRect) const;
   static void EnsureImageVisPrefsCached();
   static bool sImageVisPrefsCached;
   // The number of scrollports wide/high to expand when looking for images.
   static uint32_t sHorzExpandScrollPort;
   static uint32_t sVertExpandScrollPort;
   // The fraction of the scrollport we allow to scroll by before we schedule
   // an update of image visibility.
   static int32_t sHorzScrollFraction;
@@ -666,16 +666,19 @@ public:
     return mHelper.mDidHistoryRestore;
   }
   virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
     mHelper.mDidHistoryRestore = false;
   }
   virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
     return mHelper.IsRectNearlyVisible(aRect);
   }
+  virtual nsRect ExpandRect(const nsRect& aRect) const MOZ_OVERRIDE {
+    return mHelper.ExpandRect(aRect);
+  }
   virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
     return mHelper.OriginOfLastScroll();
   }
   virtual uint32_t CurrentScrollGeneration() MOZ_OVERRIDE {
     return mHelper.CurrentScrollGeneration();
   }
   virtual void ResetOriginIfScrollAtGeneration(uint32_t aGeneration) MOZ_OVERRIDE {
     mHelper.ResetOriginIfScrollAtGeneration(aGeneration);
@@ -982,16 +985,19 @@ public:
     return mHelper.mDidHistoryRestore;
   }
   virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
     mHelper.mDidHistoryRestore = false;
   }
   virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
     return mHelper.IsRectNearlyVisible(aRect);
   }
+  virtual nsRect ExpandRect(const nsRect& aRect) const MOZ_OVERRIDE {
+    return mHelper.ExpandRect(aRect);
+  }
   virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
     return mHelper.OriginOfLastScroll();
   }
   virtual uint32_t CurrentScrollGeneration() MOZ_OVERRIDE {
     return mHelper.CurrentScrollGeneration();
   }
   virtual void ResetOriginIfScrollAtGeneration(uint32_t aGeneration) MOZ_OVERRIDE {
     mHelper.ResetOriginIfScrollAtGeneration(aGeneration);
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -281,16 +281,21 @@ public:
    * @see nsIStatefulFrame::RestoreState
    */
   virtual void ClearDidHistoryRestore() = 0;
   /**
    * Determine if the passed in rect is nearly visible according to the image
    * visibility heuristics for how close it is to the visible scrollport.
    */
   virtual bool IsRectNearlyVisible(const nsRect& aRect) = 0;
+ /**
+  * Expand the given rect taking into account which directions we can scroll
+  * and how far we want to expand for image visibility purposes.
+  */
+  virtual nsRect ExpandRect(const nsRect& aRect) const = 0;
   /**
    * Returns the origin passed in to the last ScrollToImpl call that took
    * effect.
    */
   virtual nsIAtom* OriginOfLastScroll() = 0;
   /**
    * Returns the current generation counter for the scroll. This counter
    * increments every time the scroll position is set.
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -392,16 +392,23 @@ nsSubDocumentFrame::BuildDisplayList(nsD
         haveDisplayPort = true;
         dirty = displayPort;
       }
 
       ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
       if (ignoreViewportScrolling) {
         savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
         aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
+
+        if (aBuilder->IsForImageVisibility()) {
+          // The ExpandRect that the root scroll frame would do gets short circuited
+          // due to us ignoring the root scroll frame, so we do it here.
+          nsIScrollableFrame* rootScrollableFrame = do_QueryFrame(rootScrollFrame);
+          dirty = rootScrollableFrame->ExpandRect(dirty);
+        }
       }
     }
 
     aBuilder->EnterPresShell(subdocRootFrame, dirty);
   }
 
   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
   if (ShouldClipSubdocument()) {