Bug 776836. When invalidating ThebesLayers due to an appunits-per-dev-pixel
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 07 Aug 2012 23:07:07 +1200
changeset 102340 56e05fc797123b0d4bbaed66b6ee991c58e1bfb7
parent 102339 7c89662c33108f8dcc43cd2641635e339435685b
child 102341 568fd13e400836ca874f10220cc29f9d4563ff21
push id1875
push userktomlinson@mozilla.com
push dateFri, 10 Aug 2012 00:40:33 +0000
treeherdermozilla-aurora@56e05fc79712 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs776836
milestone16.0a2
Bug 776836. When invalidating ThebesLayers due to an appunits-per-dev-pixel change, we can't trust the frame geometry. r=mattwoodrow a=lsblakk (transplanted from e52c71762ca4c8a3f3db2de7270ffdeecc72bc8c)
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsPresContext.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2248,26 +2248,33 @@ FrameLayerBuilder::InvalidateThebesLayer
           aRect + *offsetAtLastPaint);
   invalidThebesContent->mRegion.SimplifyOutward(20);
 }
 
 /**
  * Returns true if we find a descendant with a container layer
  */
 static bool
-InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame)
+InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame, bool aTrustFrameGeometry)
 {
   if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT))
     return false;
 
   bool foundContainerLayer = false;
   if (aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
-    // Delete the invalid region to indicate that all Thebes contents
-    // need to be invalidated
-    FrameLayerBuilder::InvalidateThebesLayerContents(aFrame, aFrame->GetVisualOverflowRectRelativeToSelf());
+    if (aTrustFrameGeometry) {
+      // Just invalidate the area covered by the frame. This helps if a single
+      // region is being shared by multiple container layers.
+      FrameLayerBuilder::InvalidateThebesLayerContents(aFrame,
+        aFrame->GetVisualOverflowRectRelativeToSelf());
+    } else {
+      // Delete the invalid region to indicate that all Thebes contents
+      // need to be invalidated
+      aFrame->Properties().Delete(ThebesLayerInvalidRegionProperty());
+    }
     foundContainerLayer = true;
   }
 
   nsAutoTArray<nsIFrame::ChildList,4> childListArray;
   if (!aFrame->GetFirstPrincipalChild()) {
     nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(aFrame);
     if (subdocumentFrame) {
       // Descend into the subdocument
@@ -2280,32 +2287,39 @@ InternalInvalidateThebesLayersInSubtree(
     }
   }
 
   aFrame->GetChildLists(&childListArray);
   nsIFrame::ChildListArrayIterator lists(childListArray);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
-      if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
+      if (InternalInvalidateThebesLayersInSubtree(childFrames.get(),
+                                                  aTrustFrameGeometry)) {
         foundContainerLayer = true;
       }
     }
   }
 
   if (!foundContainerLayer) {
     aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
   }
   return foundContainerLayer;
 }
 
 /* static */ void
 FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame)
 {
-  InternalInvalidateThebesLayersInSubtree(aFrame);
+  InternalInvalidateThebesLayersInSubtree(aFrame, true);
+}
+
+/* static */ void
+FrameLayerBuilder::InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(nsIFrame* aFrame)
+{
+  InternalInvalidateThebesLayersInSubtree(aFrame, false);
 }
 
 /* static */ void
 FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>
     (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -203,16 +203,22 @@ public:
    * For any descendant frame of aFrame (including across documents) that
    * has an associated container layer, invalidate all the contents of
    * all ThebesLayer children of the container. Useful when aFrame is
    * being moved and we need to invalidate everything in aFrame's subtree.
    */
   static void InvalidateThebesLayersInSubtree(nsIFrame* aFrame);
 
   /**
+   * As InvalidateThebesLayersInSubtree, but don't trust frame geometry
+   * (e.g. because appunits-per-dev-pixel changed).
+   */
+  static void InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(nsIFrame* aFrame);
+
+  /**
    * Call this to force all retained layers to be discarded and recreated at
    * the next paint.
    */
   static void InvalidateAllLayers(LayerManager* aManager);
 
   /**
    * Call this to determine if a frame has a dedicated (non-Thebes) layer
    * for the given display item key. If there isn't one, we return null,
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -795,17 +795,17 @@ nsPresContext::InvalidateThebesLayers()
 {
   if (!mShell)
     return;
   nsIFrame* rootFrame = mShell->FrameManager()->GetRootFrame();
   if (rootFrame) {
     // FrameLayerBuilder caches invalidation-related values that depend on the
     // appunits-per-dev-pixel ratio, so ensure that all ThebesLayer drawing
     // is completely flushed.
-    FrameLayerBuilder::InvalidateThebesLayersInSubtree(rootFrame);
+    FrameLayerBuilder::InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(rootFrame);
   }
 }
 
 void
 nsPresContext::AppUnitsPerDevPixelChanged()
 {
   InvalidateThebesLayers();