Bug 1022612. Part 27: Make FrameLayerBuilder responsible for setting all layer visible regions. r=mattwoodrow
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 18 Jun 2014 15:12:55 +1200
changeset 217073 d1df8efc0422e4b28a0e150c98891104e5fc4dfe
parent 217072 03b03d30bb743d54b1ae51fe795d28eb386bf3ba
child 217074 3ced9a3b4e499b39f7fb724a1dfe180e9c9dabe6
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1022612
milestone33.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 1022612. Part 27: Make FrameLayerBuilder responsible for setting all layer visible regions. r=mattwoodrow Calling Layer::SetVisibleRegion multiple times in a transaction can result in unnecessary IPC traffic. This patch removes Intersect(childGfxBounds). This is only needed to restrict the visible region to something sane for 3D transforms, and this will be fixed up in a later patch.
layout/base/FrameLayerBuilder.cpp
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsVideoFrame.cpp
layout/ipc/RenderFrameParent.cpp
layout/xul/nsImageBoxFrame.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1609,40 +1609,37 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem
  * about whether CONTENT_OPAQUE is set; if layer was opaque in the old
  * visible region, it will still be opaque in the new one.
  * @param aLayerVisibleRegion the visible region of the layer, in the layer's
  * coordinate space
  * @param aRestrictToRect the rect to restrict the visible region to, in the
  * parent's coordinate system
  */
 static void
-SetVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aLayerVisibleRegion,
-                         const nsIntRect& aRestrictToRect)
+SetVisibleRegionForLayer(Layer* aLayer, const nsIntRect* aLayerVisibleRect,
+                         const nsIntRect& aOuterVisibleRect)
 {
   gfx3DMatrix transform;
   To3DMatrix(aLayer->GetTransform(), transform);
 
   // if 'transform' is not invertible, then nothing will be displayed
   // for the layer, so it doesn't really matter what we do here
-  gfxRect itemVisible(aRestrictToRect.x, aRestrictToRect.y,
-                      aRestrictToRect.width, aRestrictToRect.height);
-  nsIntRect childBounds = aLayerVisibleRegion.GetBounds();
-  gfxRect childGfxBounds(childBounds.x, childBounds.y,
-                         childBounds.width, childBounds.height);
-  gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible);
-  layerVisible = layerVisible.Intersect(childGfxBounds);
+  gfxRect outerVisible(aOuterVisibleRect.x, aOuterVisibleRect.y,
+                       aOuterVisibleRect.width, aOuterVisibleRect.height);
+  gfxRect layerVisible = transform.Inverse().ProjectRectBounds(outerVisible);
   layerVisible.RoundOut();
 
   nsIntRect visibleRect;
   if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect)) {
     aLayer->SetVisibleRegion(nsIntRegion());
   } else {
-    nsIntRegion rgn;
-    rgn.And(aLayerVisibleRegion, visibleRect);
-    aLayer->SetVisibleRegion(rgn);
+    if (aLayerVisibleRect) {
+      visibleRect.IntersectRect(visibleRect, *aLayerVisibleRect);
+    }
+    aLayer->SetVisibleRegion(nsIntRegion(visibleRect));
   }
 }
 
 nscolor
 ContainerState::FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex)
 {
   ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex];
   for (int32_t i = aThebesLayerIndex - 1; i >= 0; --i) {
@@ -2650,17 +2647,17 @@ ContainerState::ProcessDisplayItems(nsDi
           // The visible region may be excluding opaque content above the
           // item, and we need to ensure that that content is not placed
           // in a ThebesLayer below the item!
           data->AddDrawAboveRegion(itemDrawRect);
         }
       }
       itemVisibleRect.MoveBy(mParameters.mOffset);
       if (item->SetVisibleRegionOnLayer()) {
-        SetVisibleRegionForLayer(ownLayer, ownLayer->GetVisibleRegion(), itemVisibleRect);
+        SetVisibleRegionForLayer(ownLayer, nullptr, itemVisibleRect);
       }
 
       // rounded rectangle clipping using mask layers
       // (must be done after visible rect is set on layer)
       if (itemClip.IsRectClippedByRoundedCorner(itemContent)) {
         SetupMaskLayer(ownLayer, itemClip);
       }
 
@@ -3532,17 +3529,17 @@ FrameLayerBuilder::BuildContainerLayerFo
       aContainerFrame->AddStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
       continue;
     }
     break;
   }
 
   pixBounds.MoveBy(nsIntPoint(scaleParameters.mOffset.x, scaleParameters.mOffset.y));
   if (aParameters.mAncestorClipRect && !(aFlags & CONTAINER_NOT_CLIPPED_BY_ANCESTORS)) {
-    SetVisibleRegionForLayer(containerLayer, nsIntRegion(pixBounds),
+    SetVisibleRegionForLayer(containerLayer, &pixBounds,
                              *aParameters.mAncestorClipRect);
   } else {
     containerLayer->SetVisibleRegion(pixBounds);
   }
 
   // CONTENT_COMPONENT_ALPHA is propogated up to the nearest CONTENT_OPAQUE
   // ancestor so that BasicLayerManager knows when to copy the background into
   // pushed groups. Accelerated layers managers can't necessarily do this (only
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2030,17 +2030,16 @@ nsDisplayBackgroundImage::ConfigureLayer
   NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!");
 
   gfxPoint p = mDestRect.TopLeft() + aOffset;
   gfx::Matrix transform;
   transform.Translate(p.x, p.y);
   transform.Scale(mDestRect.width/imageSize.width,
                   mDestRect.height/imageSize.height);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
-  aLayer->SetVisibleRegion(nsIntRect(0, 0, imageSize.width, imageSize.height));
 }
 
 void
 nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
                                   const nsRect& aRect,
                                   HitTestState* aState,
                                   nsTArray<nsIFrame*> *aOutFrames)
 {
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2630,16 +2630,22 @@ public:
   {
     NS_ASSERTION(mList.IsEmpty() || !ReferenceFrame() ||
                  !mList.GetBottom()->ReferenceFrame() ||
                  mList.GetBottom()->ReferenceFrame() == ReferenceFrame(),
                  "Children must have same reference frame");
     return &mList;
   }
   virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return &mList; }
+  /**
+   * All our subclasses BuildLayers call
+   * FrameLayerBuilder::BuildContainerLayerFor, which
+   * sets the visible region of the layer correctly.
+   */
+  virtual bool SetVisibleRegionOnLayer() { return false; }
 
   virtual int32_t ZIndex() const MOZ_OVERRIDE
   {
     return (mOverrideZIndex > 0) ? mOverrideZIndex : nsDisplayItem::ZIndex();
   }
 
   void SetOverrideZIndex(int32_t aZIndex)
   {
@@ -2898,18 +2904,16 @@ public:
                                              const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
 
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                  nsRegion* aVisibleRegion,
                                  const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
 
-  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return !(mFlags & GENERATE_SCROLLABLE_LAYER); }
-
   virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
 
   NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
 protected:
   ViewID mScrollParentId;
 };
@@ -3035,18 +3039,16 @@ public:
   // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
   // number does not include nsDisplayScrollInfoLayers. If this number is not 1
   // after merging, all the nsDisplayScrollLayers should flatten away.
   intptr_t GetScrollLayerCount();
 
   virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
   virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
 
-  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
-
 #ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
 #endif
 
 protected:
   nsIFrame* mScrollFrame;
   nsIFrame* mScrolledFrame;
   ViewID mScrollParentId;
@@ -3416,18 +3418,16 @@ public:
    * Return true when we should try to prerender the entire contents of the
    * transformed frame even when it's not completely visible (yet).
    */
   static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame,
                                                 bool aLogAnimations = false);
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 
-  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
-
 #ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
 #endif
 private:
   void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
 
   static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
                                                          const nsPoint& aOrigin,
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -266,17 +266,16 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayL
 
   // Transform the canvas into the right place
   gfx::Matrix transform;
   gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
   transform.Translate(p.x, p.y);
   transform.Scale(r.Width()/canvasSize.width, r.Height()/canvasSize.height);
   layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
   layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
-  layer->SetVisibleRegion(nsIntRect(0, 0, canvasSize.width, canvasSize.height));
 
   return layer.forget();
 }
 
 void
 nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1420,17 +1420,16 @@ nsDisplayImage::ConfigureLayer(ImageLaye
   const gfxRect destRect = GetDestRect();
 
   gfx::Matrix transform;
   gfxPoint p = destRect.TopLeft() + aOffset;
   transform.Translate(p.x, p.y);
   transform.Scale(destRect.Width()/imageWidth,
                   destRect.Height()/imageHeight);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
-  aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
 }
 
 void
 nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
                          const nsRect& aDirtyRect, imgIContainer* aImage,
                          uint32_t aFlags)
 {
   // Render the image into our content area (the area inside
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1607,17 +1607,16 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   }
 
   // Set a transform on the layer to draw the plugin in the right place
   Matrix transform;
   gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
   transform.Translate(p.x, p.y);
 
   layer->SetBaseTransform(Matrix4x4::From2D(transform));
-  layer->SetVisibleRegion(ThebesIntRect(IntRect(IntPoint(0, 0), size)));
   return layer.forget();
 }
 
 void
 nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
                            nsRenderingContext& aRenderingContext,
                            const nsRect& aDirtyRect, const nsRect& aPluginRect)
 {
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -214,17 +214,16 @@ nsVideoFrame::BuildLayer(nsDisplayListBu
   layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
   layer->SetContentFlags(Layer::CONTENT_OPAQUE);
   // Set a transform on the layer to draw the video in the right place
   gfx::Matrix transform;
   gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
   transform.Translate(p.x, p.y);
   transform.Scale(r.Width()/frameSize.width, r.Height()/frameSize.height);
   layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
-  layer->SetVisibleRegion(nsIntRect(0, 0, frameSize.width, frameSize.height));
   nsRefPtr<Layer> result = layer.forget();
   return result.forget();
 }
 
 class DispatchResizeToControls : public nsRunnable
 {
 public:
   DispatchResizeToControls(nsIContent* aContent)
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -868,17 +868,16 @@ RenderFrameParent::BuildLayer(nsDisplayL
     }
     if (!layer) {
       // Probably a temporary layer manager that doesn't know how to
       // use ref layers.
       return nullptr;
     }
     static_cast<RefLayer*>(layer.get())->SetReferentId(id);
     nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
-    layer->SetVisibleRegion(aVisibleRect - offset);
     // We can only have an offset if we're a child of an inactive
     // container, but our display item is LAYER_ACTIVE_FORCE which
     // forces all layers above to be active.
     MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
     gfx::Matrix4x4 m;
     m.Translate(offset.x, offset.y, 0.0);
     // Remote content can't be repainted by us, so we multiply down
     // the resolution that our container expects onto our container.
@@ -921,17 +920,16 @@ RenderFrameParent::BuildLayer(nsDisplayL
   if (mFrameLoader->AsyncScrollEnabled()) {
     const nsContentView* view = GetRootContentView();
     BuildBackgroundPatternFor(mContainer,
                               shadowRoot,
                               view->GetViewConfig(),
                               mBackgroundColor,
                               aManager, aFrame);
   }
-  mContainer->SetVisibleRegion(aVisibleRect);
 
   return nsRefPtr<Layer>(mContainer).forget();
 }
 
 void
 RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
 {
   NS_ABORT_IF_FALSE(mFrameLoader->GetOwnerContent() == aContent,
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -401,18 +401,16 @@ nsDisplayXULImage::ConfigureLayer(ImageL
   NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
 
   gfxPoint p = destRect.TopLeft() + aOffset;
   gfx::Matrix transform;
   transform.Translate(p.x, p.y);
   transform.Scale(destRect.Width()/imageWidth,
                   destRect.Height()/imageHeight);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
-
-  aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
 }
 
 already_AddRefed<ImageContainer>
 nsDisplayXULImage::GetContainer(LayerManager* aManager, nsDisplayListBuilder* aBuilder)
 {
   return static_cast<nsImageBoxFrame*>(mFrame)->GetContainer(aManager);
 }