Bug 539356 - Part 18 - Mark frames with only invalid children as an optimization to use when invalidating further frames. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 11 Jun 2012 16:45:39 +1200
changeset 101180 2865904db9fcb7b92bc8af7fb20633f2e12067d8
parent 101179 34e07b09c426eea9b8aa2e86ce991488528edaf3
child 101181 a284ccb25b838d6cd37abf9160a2d1c78d747c3d
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs539356
milestone16.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 539356 - Part 18 - Mark frames with only invalid children as an optimization to use when invalidating further frames. r=roc
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4584,16 +4584,22 @@ nsIFrame::GetTransformMatrix(nsIFrame* a
      NSAppUnitsToFloatPixels(delta.y, scaleFactor),
      0.0f);
 }
 
 void
 nsIFrame::InvalidateFrameSubtree(PRUint32 aFlags)
 {
   InvalidateFrame(aFlags);
+
+  if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT)) {
+    return;
+  }
+
+  AddStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
   
   nsAutoTArray<nsIFrame::ChildList,4> childListArray;
   GetCrossDocChildLists(&childListArray);
 
   nsIFrame::ChildListArrayIterator lists(childListArray);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
@@ -4614,17 +4620,19 @@ nsIFrame::ClearInvalidationStateBits()
     for (; !lists.IsDone(); lists.Next()) {
       nsFrameList::Enumerator childFrames(lists.CurrentList());
       for (; !childFrames.AtEnd(); childFrames.Next()) {
         childFrames.get()->ClearInvalidationStateBits();
       }
     }
   }
 
-  RemoveStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
+  RemoveStateBits(NS_FRAME_NEEDS_PAINT | 
+                  NS_FRAME_DESCENDANT_NEEDS_PAINT | 
+                  NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
 }
 
 void
 nsIFrame::InvalidateFrame(PRUint32 aFlags)
 {
   AddStateBits(NS_FRAME_NEEDS_PAINT);
   nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(this);
   while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
@@ -7756,16 +7764,23 @@ nsFrame::SetParent(nsIFrame* aParent)
     }
   }
 
   if (aParent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
     AddInPopupStateBitToDescendants(this);
   } else {
     RemoveInPopupStateBitFromDescendants(this);
   }
+  
+  // If our new parent only has invalid children, then we just invalidate
+  // ourselves too. This is probably faster than clearing the flag all
+  // the way up the frame tree.
+  if (aParent->HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT)) {
+    InvalidateFrame(INVALIDATE_DONT_SCHEDULE_PAINT);
+  }
 }
 
 void
 nsFrame::InitBoxMetrics(bool aClear)
 {
   FrameProperties props = Properties();
   if (aClear) {
     props.Delete(BoxMetricsProperty());
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -281,18 +281,24 @@ typedef PRUint64 nsFrameState;
 
 // Frame is marked as needing painting
 #define NS_FRAME_NEEDS_PAINT                        NS_FRAME_STATE_BIT(45)
 
 // Frame has a descendant frame that needs painting - This includes
 // cross-doc children.
 #define NS_FRAME_DESCENDANT_NEEDS_PAINT             NS_FRAME_STATE_BIT(46)
 
+// Frame has only descendant frames that needs painting - This includes
+// cross-doc children. This guarantees that all descendents have 
+// NS_FRAME_NEEDS_PAINT and NS_FRAME_ALL_DESCENDANTS_NEED_PAINT, or they 
+// have no display items.
+#define NS_FRAME_ALL_DESCENDANTS_NEED_PAINT         NS_FRAME_STATE_BIT(47)
+
 // Frame is a descendant of a popup
-#define NS_FRAME_IN_POPUP                           NS_FRAME_STATE_BIT(47)
+#define NS_FRAME_IN_POPUP                           NS_FRAME_STATE_BIT(48)
 
 // Box layout bits
 #define NS_STATE_IS_HORIZONTAL                      NS_FRAME_STATE_BIT(22)
 #define NS_STATE_IS_DIRECTION_NORMAL                NS_FRAME_STATE_BIT(31)
 
 // Helper macros
 #define NS_SUBTREE_DIRTY(_frame)  \
   (((_frame)->GetStateBits() &      \