Bug 1200158 - Avoid expensive computations involving the maybe-hit region in hot code paths. r=mstange
authorBotond Ballo <botond@mozilla.com>
Mon, 31 Aug 2015 19:53:34 -0400
changeset 260618 f385a5b646963fd5c38fc1badd7450f6fdbc96d9
parent 260617 825bd60177ede2990ff5ac62699f2d7e59ec393d
child 260619 fe1792ea939245f128d13c976c0ff07fe5fd836e
push id29318
push usercbook@mozilla.com
push dateThu, 03 Sep 2015 11:15:07 +0000
treeherdermozilla-central@74fbd245369c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1200158
milestone43.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 1200158 - Avoid expensive computations involving the maybe-hit region in hot code paths. r=mstange
layout/base/FrameLayerBuilder.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -417,17 +417,17 @@ public:
                   const DisplayItemClip& aClip,
                   LayerState aLayerState);
   const nsIFrame* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; }
 
   /**
    * Add the given hit regions to the hit regions to the hit retions for this
    * PaintedLayer.
    */
-  void AccumulateEventRegions(nsDisplayLayerEventRegions* aEventRegions);
+  void AccumulateEventRegions(ContainerState* aState, nsDisplayLayerEventRegions* aEventRegions);
 
   /**
    * If this represents only a nsDisplayImage, and the image type supports being
    * optimized to an ImageLayer, returns true.
    */
   bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
 
   /**
@@ -482,16 +482,24 @@ public:
   /**
    * The region for this PaintedLayer that is sensitive to events and
    * allows vertical panning but not zooming. This is an approximation
    * and any deviation from the true region will be part of the
    * mDispatchToContentHitRegion.
    */
   nsRegion mVerticalPanRegion;
   /**
+   * Scaled versions of mHitRegion and mMaybeHitRegion.
+   * We store these because FindPaintedLayerFor() needs to consume them
+   * in this form, and it's a hot code path so we don't wnat to scale
+   * them inside that function.
+   */
+  nsIntRegion mScaledHitRegion;
+  nsIntRegion mScaledMaybeHitRegion;
+  /**
    * The "active scrolled root" for all content in the layer. Must
    * be non-null; all content in a PaintedLayer must have the same
    * active scrolled root.
    */
   const nsIFrame* mAnimatedGeometryRoot;
   /**
    * The offset between mAnimatedGeometryRoot and the reference frame.
    */
@@ -2584,18 +2592,18 @@ PaintedLayerDataNode::FindPaintedLayerFo
         lowestUsableLayer = &data;
         nsIntRegion visibleRegion = data.mVisibleRegion;
         // When checking whether the visible region intersects the given
         // visible rect, also include the event-regions in the visible region,
         // unless we're in an inactive layer, in which case the event-regions
         // will be hoisted out into their own layer.
         ContainerState& contState = mTree.ContState();
         if (!contState.IsInInactiveLayer()) {
-          visibleRegion.OrWith(contState.ScaleRegionToOutsidePixels(data.mHitRegion));
-          visibleRegion.OrWith(contState.ScaleRegionToOutsidePixels(data.mMaybeHitRegion));
+          visibleRegion.OrWith(data.mScaledHitRegion);
+          visibleRegion.OrWith(data.mScaledMaybeHitRegion);
         }
         if (visibleRegion.Intersects(aVisibleRect)) {
           break;
         }
       }
       if (lowestUsableLayer) {
         return lowestUsableLayer;
       }
@@ -3425,26 +3433,36 @@ PaintedLayerData::Accumulate(ContainerSt
   if (aState->mParameters.mInActiveTransformedSubtree &&
        (mNeedComponentAlpha ||
          !aItem->GetComponentAlphaBounds(aState->mBuilder).IsEmpty())) {
     mDisableFlattening = true;
   }
 }
 
 void
-PaintedLayerData::AccumulateEventRegions(nsDisplayLayerEventRegions* aEventRegions)
+PaintedLayerData::AccumulateEventRegions(ContainerState* aState, nsDisplayLayerEventRegions* aEventRegions)
 {
   FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating event regions %p against pld=%p\n", aEventRegions, this);
 
   mHitRegion.Or(mHitRegion, aEventRegions->HitRegion());
   mMaybeHitRegion.Or(mMaybeHitRegion, aEventRegions->MaybeHitRegion());
   mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, aEventRegions->DispatchToContentHitRegion());
   mNoActionRegion.Or(mNoActionRegion, aEventRegions->NoActionRegion());
   mHorizontalPanRegion.Or(mHorizontalPanRegion, aEventRegions->HorizontalPanRegion());
   mVerticalPanRegion.Or(mVerticalPanRegion, aEventRegions->VerticalPanRegion());
+
+  // Simplify the maybe-hit region because it can be a complex region
+  // and operations on it, such as the scaling below and the use of the
+  // result in hot code paths like FindPaintedLayerFor(), can be very expensive.
+  mMaybeHitRegion.SimplifyOutward(8);
+
+  // Calculate scaled versions of mHitRegion and mMaybeHitRegion for quick
+  // access in FindPaintedLayerFor().
+  mScaledHitRegion = aState->ScaleRegionToOutsidePixels(mHitRegion);
+  mScaledMaybeHitRegion = aState->ScaleRegionToOutsidePixels(mMaybeHitRegion);
 }
 
 PaintedLayerData
 ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
                                     const nsIntRect& aVisibleRect,
                                     const nsIFrame* aAnimatedGeometryRoot,
                                     const nsPoint& aTopLeft,
                                     bool aShouldFixToViewport)
@@ -4011,17 +4029,17 @@ ContainerState::ProcessDisplayItems(nsDi
                                                   forceOwnLayer, [&]() {
           return NewPaintedLayerData(item, itemVisibleRect, animatedGeometryRoot,
                                      topLeft, shouldFixToViewport);
         });
 
       if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
         nsDisplayLayerEventRegions* eventRegions =
             static_cast<nsDisplayLayerEventRegions*>(item);
-        paintedLayerData->AccumulateEventRegions(eventRegions);
+        paintedLayerData->AccumulateEventRegions(this, eventRegions);
       } else {
         // check to see if the new item has rounded rect clips in common with
         // other items in the layer
         if (mManager->IsWidgetLayerManager()) {
           paintedLayerData->UpdateCommonClipCount(itemClip);
         }
         nsIntRegion opaquePixels = ComputeOpaqueRect(item,
             animatedGeometryRoot, paintedLayerData->mFixedPosFrameForLayerData,