Bug 1389143 - Send event regions items over to APZ in layers-free mode. r?jrmuizel draft
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 18 Aug 2017 13:06:31 -0400
changeset 649104 5dca1076ddeaf18a98ae049215309b93864da823
parent 649103 1ee8e595ff1f965207d8d3d112063960c343c317
child 649105 4174fab94110736b3264433a901fe3b539617667
push id74954
push userkgupta@mozilla.com
push dateFri, 18 Aug 2017 17:07:08 +0000
reviewersjrmuizel
bugs1389143
milestone57.0a1
Bug 1389143 - Send event regions items over to APZ in layers-free mode. r?jrmuizel This patch collapses the data from event regions display items that have the same ASR. However, it only does so if there's no other display items interleaved in between that forced their own scroll layer data. MozReview-Commit-ID: IkQSISc2bwc
gfx/layers/LayersTypes.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderScrollData.h
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -152,25 +152,54 @@ struct EventRegions {
   {
     mHitRegion.Transform(aTransform);
     mDispatchToContentHitRegion.Transform(aTransform);
     mNoActionRegion.Transform(aTransform);
     mHorizontalPanRegion.Transform(aTransform);
     mVerticalPanRegion.Transform(aTransform);
   }
 
+  void OrWith(const EventRegions& aOther)
+  {
+    mHitRegion.OrWith(aOther.mHitRegion);
+    mDispatchToContentHitRegion.OrWith(aOther.mDispatchToContentHitRegion);
+    // See the comment in nsDisplayList::AddFrame, where the touch action regions
+    // are handled. The same thing applies here.
+    bool alreadyHadRegions = !mNoActionRegion.IsEmpty() ||
+        !mHorizontalPanRegion.IsEmpty() ||
+        !mVerticalPanRegion.IsEmpty();
+    mNoActionRegion.OrWith(aOther.mNoActionRegion);
+    mHorizontalPanRegion.OrWith(aOther.mHorizontalPanRegion);
+    mVerticalPanRegion.OrWith(aOther.mVerticalPanRegion);
+    if (alreadyHadRegions) {
+      nsIntRegion combinedActionRegions;
+      combinedActionRegions.Or(mHorizontalPanRegion, mVerticalPanRegion);
+      combinedActionRegions.OrWith(mNoActionRegion);
+      mDispatchToContentHitRegion.OrWith(combinedActionRegions);
+    }
+  }
+
   bool IsEmpty() const
   {
     return mHitRegion.IsEmpty()
         && mDispatchToContentHitRegion.IsEmpty()
         && mNoActionRegion.IsEmpty()
         && mHorizontalPanRegion.IsEmpty()
         && mVerticalPanRegion.IsEmpty();
   }
 
+  void SetEmpty()
+  {
+    mHitRegion.SetEmpty();
+    mDispatchToContentHitRegion.SetEmpty();
+    mNoActionRegion.SetEmpty();
+    mHorizontalPanRegion.SetEmpty();
+    mVerticalPanRegion.SetEmpty();
+  }
+
   nsCString ToString() const
   {
     nsCString result = mHitRegion.ToString();
     result.AppendLiteral(";dispatchToContent=");
     result.Append(mDispatchToContentHitRegion.ToString());
     return result;
   }
 };
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -194,16 +194,17 @@ PopulateScrollData(WebRenderScrollData& 
 
 void
 WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
                                                               nsDisplayListBuilder* aDisplayListBuilder,
                                                               const StackingContextHelper& aSc,
                                                               wr::DisplayListBuilder& aBuilder)
 {
   bool apzEnabled = AsyncPanZoomEnabled();
+  EventRegions eventRegions;
 
   nsDisplayList savedItems;
   nsDisplayItem* item;
   while ((item = aDisplayList->RemoveBottom()) != nullptr) {
     DisplayItemType itemType = item->GetType();
 
     // If the item is a event regions item, but is empty (has no regions in it)
     // then we should just throw it out
@@ -253,16 +254,54 @@ WebRenderLayerManager::CreateWebRenderCo
       // display item than previously, so we can't squash the display items
       // into the same "layer".
       const ActiveScrolledRoot* asr = item->GetActiveScrolledRoot();
       if (asr != mLastAsr) {
         mLastAsr = asr;
         forceNewLayerData = true;
       }
 
+      // If we're creating a new layer data then flush whatever event regions
+      // we've collected onto the old layer.
+      if (forceNewLayerData && !eventRegions.IsEmpty()) {
+        // If eventRegions is non-empty then we must have a layer data already,
+        // because we (below) force one if we encounter an event regions item
+        // with an empty layer data list. Additionally, the most recently
+        // created layer data must have been created from an item whose ASR
+        // is the same as the ASR on the event region items that were collapsed
+        // into |eventRegions|. This is because any ASR change causes us to force
+        // a new layer data which flushes the eventRegions.
+        MOZ_ASSERT(!mLayerScrollData.empty());
+        mLayerScrollData.back().AddEventRegions(eventRegions);
+        eventRegions.SetEmpty();
+      }
+
+      // Collapse event region data into |eventRegions|, which will either be
+      // empty, or filled with stuff from previous display items with the same
+      // ASR.
+      if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
+        nsDisplayLayerEventRegions* regionsItem =
+            static_cast<nsDisplayLayerEventRegions*>(item);
+        int32_t auPerDevPixel = item->Frame()->PresContext()->AppUnitsPerDevPixel();
+        EventRegions regions(
+            regionsItem->HitRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel),
+            regionsItem->MaybeHitRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel),
+            regionsItem->DispatchToContentHitRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel),
+            regionsItem->NoActionRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel),
+            regionsItem->HorizontalPanRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel),
+            regionsItem->VerticalPanRegion().ScaleToOutsidePixels(1.0f, 1.0f, auPerDevPixel));
+
+        eventRegions.OrWith(regions);
+        if (mLayerScrollData.empty()) {
+          // If we don't have a layer data yet then create one because we will
+          // need it to store this event region information.
+          forceNewLayerData = true;
+        }
+      }
+
       // If we're going to create a new layer data for this item, stash the
       // ASR so that if we recurse into a sublist they will know where to stop
       // walking up their ASR chain when building scroll metadata.
       if (forceNewLayerData) {
         mAsrStack.push_back(asr);
       }
     }
 
@@ -286,16 +325,26 @@ WebRenderLayerManager::CreateWebRenderCo
 
       int32_t descendants = mLayerScrollData.size() - layerCountBeforeRecursing;
 
       mLayerScrollData.emplace_back();
       mLayerScrollData.back().Initialize(mScrollData, item, descendants, stopAtAsr);
     }
   }
   aDisplayList->AppendToTop(&savedItems);
+
+  // If we have any event region info left over we need to flush it before we
+  // return. Again, at this point the layer data list must be non-empty, and
+  // the most recently created layer data will have been created by an item
+  // with matching ASRs.
+  if (!eventRegions.IsEmpty()) {
+    MOZ_ASSERT(apzEnabled);
+    MOZ_ASSERT(!mLayerScrollData.empty());
+    mLayerScrollData.back().AddEventRegions(eventRegions);
+  }
 }
 
 void
 WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
                                                   nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
   mEndTransactionWithoutLayers = true;
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -64,17 +64,20 @@ public:
   const ScrollMetadata& GetScrollMetadata(const WebRenderScrollData& aOwner,
                                           size_t aIndex) const;
 
   void SetTransform(const gfx::Matrix4x4& aTransform) { mTransform = aTransform; }
   gfx::Matrix4x4 GetTransform() const { return mTransform; }
   CSSTransformMatrix GetTransformTyped() const;
   void SetTransformIsPerspective(bool aTransformIsPerspective) { mTransformIsPerspective = aTransformIsPerspective; }
   bool GetTransformIsPerspective() const { return mTransformIsPerspective; }
+
+  void AddEventRegions(const EventRegions& aRegions) { mEventRegions.OrWith(aRegions); }
   EventRegions GetEventRegions() const { return mEventRegions; }
+
   const LayerIntRegion& GetVisibleRegion() const { return mVisibleRegion; }
   void SetReferentId(uint64_t aReferentId) { mReferentId = Some(aReferentId); }
   Maybe<uint64_t> GetReferentId() const { return mReferentId; }
   EventRegionsOverride GetEventRegionsOverride() const { return mEventRegionsOverride; }
 
   void SetScrollThumbData(const ScrollThumbData& aData) { mScrollThumbData = aData; }
   const ScrollThumbData& GetScrollThumbData() const { return mScrollThumbData; }
   void SetScrollbarAnimationId(const uint64_t& aId) { mScrollbarAnimationId = aId; }