Bug 599113. Part 3. Can't restrict invalidated rects to visible portion of a scroll frame if we retain content that might be outside the visible portion of the scroll frame. r=roc a=blocking-betaN+
authorTimothy Nikkel <tnikkel@gmail.com>
Thu, 14 Oct 2010 20:03:46 -0500
changeset 55830 8188183a6402dbedb59dc484ee068421fc1c262a
parent 55829 bed182d7f22d38cc9add486f1506de93f9ecc12c
child 55831 417a9fc988ec775b91cb7e84d0c1e26bc8fac06d
push id16303
push usertnikkel@gmail.com
push dateFri, 15 Oct 2010 01:08:21 +0000
treeherdermozilla-central@417a9fc988ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, blocking-betaN
bugs599113
milestone2.0b8pre
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 599113. Part 3. Can't restrict invalidated rects to visible portion of a scroll frame if we retain content that might be outside the visible portion of the scroll frame. r=roc a=blocking-betaN+
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsViewportFrame.cpp
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4094,16 +4094,19 @@ nsIFrame::InvalidateInternalAfterResize(
     // rendering and the display items that trigger layers are nested inside
     // the nsDisplayTransform
     // XXX need to set INVALIDATE_NO_THEBES_LAYERS for certain kinds of
     // invalidation, e.g. video update, 'opacity' change
     FrameLayerBuilder::InvalidateThebesLayerContents(this,
         aDamageRect + nsPoint(aX, aY));
     // Don't need to invalidate any more Thebes layers
     aFlags |= INVALIDATE_NO_THEBES_LAYERS;
+    if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
+      return;
+    }
   }
   if (IsTransformed()) {
     nsRect newDamageRect;
     newDamageRect.UnionRect(nsDisplayTransform::TransformRect
                             (aDamageRect, this, nsPoint(-aX, -aY)), aDamageRect);
     GetParent()->
       InvalidateInternal(newDamageRect, aX + mRect.x, aY + mRect.y, this,
                          aFlags);
@@ -4227,16 +4230,19 @@ void
 nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
 {
   NS_ASSERTION(nsLayoutUtils::GetDisplayRootFrame(this) == this,
                "Can only call this on display roots");
 
   if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
       !(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
     FrameLayerBuilder::InvalidateThebesLayerContents(this, aDamageRect);
+    if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
+      return;
+    }
   }
 
   PRUint32 flags =
     (aFlags & INVALIDATE_IMMEDIATE) ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
 
   nsRect rect = aDamageRect;
   nsRegion* excludeRegion = static_cast<nsRegion*>
     (Properties().Get(DeferInvalidatesProperty()));
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -192,18 +192,26 @@ nsHTMLScrollFrame::InvalidateInternal(co
       // restrict aDamageRect to the scrollable view's bounds
       nsRect damage = aDamageRect + nsPoint(aX, aY);
       // damage is now in our coordinate system, which means it was
       // translated using the current scroll position. Adjust it to
       // reflect the scroll position at last paint, since that's what
       // the layer system wants us to invalidate.
       damage += GetScrollPosition() - mInner.mScrollPosAtLastPaint;
       nsRect r;
-      if (r.IntersectRect(damage, mInner.mScrollPort)) {
-        nsHTMLContainerFrame::InvalidateInternal(r, 0, 0, aForChild, aFlags);
+      r.IntersectRect(damage, mInner.mScrollPort);
+      PRBool seperateThebes = IsScrollingActive() &&
+        !(aFlags & INVALIDATE_NO_THEBES_LAYERS) && r != damage;
+      if (seperateThebes) {
+        nsHTMLContainerFrame::InvalidateInternal(damage, 0, 0, aForChild,
+          aFlags | INVALIDATE_ONLY_THEBES_LAYERS);
+      }
+      if (!r.IsEmpty()) {
+        nsHTMLContainerFrame::InvalidateInternal(r, 0, 0, aForChild,
+          aFlags | (seperateThebes ? INVALIDATE_NO_THEBES_LAYERS : 0));
       }
       if (mInner.mIsRoot && r != damage) {
         // Make sure we notify our prescontext about invalidations outside
         // viewport clipping.
         // This is important for things that are snapshotting the viewport,
         // possibly outside the scrolled bounds.
         // We don't need to propagate this any further up, though. Anyone who
         // cares about scrolled-out-of-view invalidates had better be listening
@@ -1045,18 +1053,26 @@ nsXULScrollFrame::InvalidateInternal(con
                                      nscoord aX, nscoord aY, nsIFrame* aForChild,
                                      PRUint32 aFlags)
 {
   if (aForChild == mInner.mScrolledFrame) {
     // restrict aDamageRect to the scrollable view's bounds
     nsRect damage = aDamageRect + nsPoint(aX, aY) +
       GetScrollPosition() - mInner.mScrollPosAtLastPaint;
     nsRect r;
-    if (r.IntersectRect(damage, mInner.mScrollPort)) {
-      nsBoxFrame::InvalidateInternal(r, 0, 0, aForChild, aFlags);
+    r.IntersectRect(damage, mInner.mScrollPort);
+    PRBool seperateThebes = IsScrollingActive() &&
+      !(aFlags & INVALIDATE_NO_THEBES_LAYERS) && r != damage;
+    if (seperateThebes) {
+      nsBoxFrame::InvalidateInternal(damage, 0, 0, aForChild,
+        aFlags | INVALIDATE_ONLY_THEBES_LAYERS);
+    }
+    if (!r.IsEmpty()) {
+      nsBoxFrame::InvalidateInternal(r, 0, 0, aForChild,
+        aFlags | (seperateThebes ? INVALIDATE_NO_THEBES_LAYERS : 0));
     }
     return;
   }
   
   nsBoxFrame::InvalidateInternal(aDamageRect, aX, aY, aForChild, aFlags);
 }
 
 nscoord
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1999,16 +1999,18 @@ public:
    * @param aFlags INVALIDATE_REASON_SCROLL_BLIT: set if the invalidation
    * was really just the scroll machinery copying pixels from one
    * part of the window to another
    * @param aFlags INVALIDATE_REASON_SCROLL_REPAINT: set if the invalidation
    * was triggered by scrolling
    * @param aFlags INVALIDATE_NO_THEBES_LAYERS: don't invalidate the
    * ThebesLayers of any container layer owned by an ancestor. Set this
    * only if ThebesLayers definitely don't need to be updated.
+   * @param aFlags INVALIDATE_ONLY_THEBES_LAYERS: invalidate only in the
+   * ThebesLayers of the nearest container layer.
    * @param aFlags INVALIDATE_EXCLUDE_CURRENT_PAINT: if the invalidation
    * occurs while we're painting (to be precise, while
    * BeginDeferringInvalidatesForDisplayRoot is active on the display root),
    * then invalidation in the current paint region is simply discarded.
    * Use this flag if areas that are being painted do not need
    * to be invalidated. By default, when this flag is not specified,
    * areas that are invalidated while currently being painted will be repainted
    * again.
@@ -2019,17 +2021,18 @@ public:
   enum {
     INVALIDATE_IMMEDIATE = 0x01,
     INVALIDATE_CROSS_DOC = 0x02,
     INVALIDATE_REASON_SCROLL_BLIT = 0x04,
     INVALIDATE_REASON_SCROLL_REPAINT = 0x08,
     INVALIDATE_REASON_MASK = INVALIDATE_REASON_SCROLL_BLIT |
                              INVALIDATE_REASON_SCROLL_REPAINT,
     INVALIDATE_NO_THEBES_LAYERS = 0x10,
-    INVALIDATE_EXCLUDE_CURRENT_PAINT = 0x20
+    INVALIDATE_ONLY_THEBES_LAYERS = 0x20,
+    INVALIDATE_EXCLUDE_CURRENT_PAINT = 0x40
   };
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aOffsetX, nscoord aOffsetY,
                                   nsIFrame* aForChild, PRUint32 aFlags);
 
   /**
    * Helper function that funnels an InvalidateInternal request up to the
    * parent.  This function is used so that if MOZ_SVG is not defined, we still
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -364,16 +364,19 @@ ViewportFrame::InvalidateInternal(const 
   nsPresContext* presContext = PresContext();
   presContext->NotifyInvalidation(r, aFlags);
 
   if ((mState & NS_FRAME_HAS_CONTAINER_LAYER) &&
       !(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
     FrameLayerBuilder::InvalidateThebesLayerContents(this, r);
     // Don't need to invalidate any more Thebes layers
     aFlags |= INVALIDATE_NO_THEBES_LAYERS;
+    if (aFlags & INVALIDATE_ONLY_THEBES_LAYERS) {
+      return;
+    }
   }
 
   nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
   if (parent) {
     if (!presContext->PresShell()->IsActive())
       return;
     nsPoint pt = -parent->GetOffsetToCrossDoc(this);
     PRInt32 ourAPD = presContext->AppUnitsPerDevPixel();