Bug 625672. Part 2: Build temporary layer manager to render inactive layers after we've recomputed visibility. r=tnikkel,a=blocker
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 10 Feb 2011 21:58:11 +1300
changeset 62293 221893d96b9383130bb9d0820d1e6511eca0fdf8
parent 62292 216a0dd9c4c309d9fa6474cc4a10a3e9f0b707c8
child 62294 afb62e95311a2ca29ccf89087591461fdd1f4ddb
push idunknown
push userunknown
push dateunknown
reviewerstnikkel, blocker
bugs625672
milestone2.0b12pre
Bug 625672. Part 2: Build temporary layer manager to render inactive layers after we've recomputed visibility. r=tnikkel,a=blocker
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/reftests/scrolling/fixed-text-2.html
layout/reftests/scrolling/reftest.list
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1171,41 +1171,37 @@ ContainerState::FindThebesLayerFor(nsDis
     thebesLayerData = mThebesLayerDataStack[lowestUsableLayerWithScrolledRoot];
     layer = thebesLayerData->mLayer;
   }
 
   thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect, aClip);
   return layer.forget();
 }
 
-static already_AddRefed<BasicLayerManager>
-BuildTempManagerForInactiveLayer(nsDisplayListBuilder* aBuilder,
-                                 nsDisplayItem* aItem)
+static void
+PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
+                   nsDisplayItem* aItem,
+                   gfxContext* aContext)
 {
-  // This item has an inactive layer. We will render it to a ThebesLayer
-  // using a temporary BasicLayerManager. Set up the layer
-  // manager now so that if we need to modify the retained layer
-  // tree during this process, those modifications will happen
-  // during the construction phase for the retained layer tree.
+  // This item has an inactive layer. Render it to a ThebesLayer
+  // using a temporary BasicLayerManager.
   nsRefPtr<BasicLayerManager> tempManager = new BasicLayerManager();
-  tempManager->BeginTransaction();
+  tempManager->BeginTransactionWithTarget(aContext);
   nsRefPtr<Layer> layer = aItem->BuildLayer(aBuilder, tempManager);
   if (!layer) {
     tempManager->EndTransaction(nsnull, nsnull);
-    return nsnull;
+    return;
   }
   PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
   nsIntRect itemVisibleRect =
     aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
   SetVisibleRectForLayer(layer, itemVisibleRect);
 
   tempManager->SetRoot(layer);
-  // No painting should occur yet, since there is no target context.
-  tempManager->EndTransaction(nsnull, nsnull);
-  return tempManager.forget();
+  tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
 }
 
 /*
  * Iterate through the non-clip items in aList and its descendants.
  * For each item we compute the effective clip rect. Each item is assigned
  * to a layer. We invalidate the areas in ThebesLayers where an item
  * has moved from one ThebesLayer to another. Also,
  * aState->mInvalidThebesContent is invalidated in every ThebesLayer.
@@ -1296,23 +1292,16 @@ ContainerState::ProcessDisplayItems(cons
       NS_ASSERTION(!mNewChildLayers.Contains(ownLayer),
                    "Layer already in list???");
 
       InvalidateForLayerChange(item, ownLayer);
 
       mNewChildLayers.AppendElement(ownLayer);
       mBuilder->LayerBuilder()->AddLayerDisplayItem(ownLayer, item);
     } else {
-      nsRefPtr<BasicLayerManager> tempLayerManager;
-      if (layerState != LAYER_NONE) {
-        tempLayerManager = BuildTempManagerForInactiveLayer(mBuilder, item);
-        if (!tempLayerManager)
-          continue;
-      }
-
       nsIFrame* f = item->GetUnderlyingFrame();
       nsIFrame* activeScrolledRoot =
         nsLayoutUtils::GetActiveScrolledRootFor(f, mBuilder->ReferenceFrame());
       if (item->IsFixedAndCoveringViewport(mBuilder)) {
         // Make its active scrolled root be the active scrolled root of
         // the enclosing viewport, since it shouldn't be scrolled by scrolled
         // frames in its document. InvalidateFixedBackgroundFramesFromList in
         // nsGfxScrollFrame will not repaint this item when scrolling occurs.
@@ -1326,17 +1315,17 @@ ContainerState::ProcessDisplayItems(cons
       nsRefPtr<ThebesLayer> thebesLayer =
         FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
                            activeScrolledRoot);
 
       InvalidateForLayerChange(item, thebesLayer);
 
       mBuilder->LayerBuilder()->
         AddThebesDisplayItem(thebesLayer, item, aClip, mContainerFrame,
-                             layerState, tempLayerManager);
+                             layerState);
     }
   }
 }
 
 void
 ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
 {
   nsIFrame* f = aItem->GetUnderlyingFrame();
@@ -1387,28 +1376,27 @@ FrameLayerBuilder::NeedToInvalidateFixed
       !HasRetainedLayerFor(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey());
 }
 
 void
 FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
                                         nsDisplayItem* aItem,
                                         const Clip& aClip,
                                         nsIFrame* aContainerLayerFrame,
-                                        LayerState aLayerState,
-                                        LayerManager* aTempManager)
+                                        LayerState aLayerState)
 {
   AddLayerDisplayItem(aLayer, aItem);
 
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     entry->mContainerLayerFrame = aContainerLayerFrame;
     NS_ASSERTION(aItem->GetUnderlyingFrame(), "Must have frame");
     ClippedDisplayItem* cdi =
       entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip));
-    cdi->mTempLayerManager = aTempManager;
+    cdi->mInactiveLayer = aLayerState != LAYER_NONE;
   }
 }
 
 void
 FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
                                        nsDisplayItem* aItem)
 {
   if (aLayer->Manager() != mRetainingManager)
@@ -1873,21 +1861,18 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
       setClipRect = cdi->mClip.mHaveClipRect;
       if (setClipRect) {
         currentClip = cdi->mClip;
         aContext->Save();
         currentClip.ApplyTo(aContext, presContext);
       }
     }
 
-    if (cdi->mTempLayerManager) {
-      // This item has an inactive layer. Render it to the ThebesLayer
-      // using the temporary BasicLayerManager.
-      cdi->mTempLayerManager->BeginTransactionWithTarget(aContext);
-      cdi->mTempLayerManager->EndTransaction(DrawThebesLayer, builder);
+    if (cdi->mInactiveLayer) {
+      PaintInactiveLayer(builder, cdi->mItem, aContext);
     } else {
       cdi->mItem->Paint(builder, rc);
     }
 
     if (builder->LayerBuilder()->CheckDOMModified())
       break;
   }
 
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -233,18 +233,17 @@ public:
    * for the container layer this ThebesItem belongs to.
    * aItem must have an underlying frame.
    */
   struct Clip;
   void AddThebesDisplayItem(ThebesLayer* aLayer,
                             nsDisplayItem* aItem,
                             const Clip& aClip,
                             nsIFrame* aContainerLayerFrame,
-                            LayerState aLayerState,
-                            LayerManager* aTempManager);
+                            LayerState aLayerState);
 
   /**
    * Given a frame and a display item key that uniquely identifies a
    * display item for the frame, find the layer that was last used to
    * render that display item. Returns null if there is no such layer.
    * This could be a dedicated layer for the display item, or a ThebesLayer
    * that renders many display items.
    */
@@ -425,18 +424,18 @@ protected:
    */
   struct ClippedDisplayItem {
     ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip)
       : mItem(aItem), mClip(aClip)
     {
     }
 
     nsDisplayItem* mItem;
-    nsRefPtr<LayerManager> mTempLayerManager;
     Clip mClip;
+    PRPackedBool mInactiveLayer;
   };
 
   /**
    * We accumulate ClippedDisplayItem elements in a hashtable during
    * the paint process. This is the hashentry for that hashtable.
    */
   class ThebesLayerItemsEntry : public nsPtrHashKey<ThebesLayer> {
   public:
new file mode 100644
--- /dev/null
+++ b/layout/reftests/scrolling/fixed-text-2.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<style>
+p { margin:0; }
+</style>
+</head>
+<body style="overflow:hidden;">
+<div style="position: fixed; bottom: 0; z-index: 1; width: 100%; height: 50px; background-color: black;"></div>
+<div style="-moz-transform: scale(1);">
+<script>
+for (var i = 1; i <= 100; ++i) {
+  document.write("<p>This is some text: " + i + "\n");
+}
+</script>
+</div>
+<script src="scrolling.js"></script>
+</body>
+</html>
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -1,9 +1,10 @@
 HTTP == fixed-1.html fixed-1.html?ref
 HTTP == fixed-opacity-1.html fixed-opacity-1.html?ref
 HTTP == fixed-text-1.html fixed-text-1.html?ref
+HTTP == fixed-text-2.html fixed-text-2.html?ref
 HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref
 random-if(cocoaWidget) HTTP == opacity-mixed-scrolling-2.html opacity-mixed-scrolling-2.html?ref # see bug 625357
 HTTP == simple-1.html simple-1.html?ref
 HTTP == text-1.html text-1.html?ref
 == uncovering-1.html uncovering-1-ref.html
 == uncovering-2.html uncovering-2-ref.html