Bug 1384181 - Reorganize the WebRenderScrollData code to work with layers-free transactions. r=jrmuizel
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 26 Jul 2017 14:47:48 -0400
changeset 422242 b12122c2c75d2da2007333d08f8b7acd346ea393
parent 422241 e61f5fc8ed7330a6e4ca5f9efebee86769e3a3af
child 422243 b298cd21c0f1850caabd581b3d34b003d05384b8
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1384181
milestone56.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 1384181 - Reorganize the WebRenderScrollData code to work with layers-free transactions. r=jrmuizel Until now WebRenderScrollData was only used with "layers" WR transactions, but we want to use it with layers-free transactions as well. As such, we need to allow collecting information from display items instead of layers. This restructures the code a little bit to allow that. This patch should not have any functional effect on the "layers" codepath, but on the "layers-free" codepath it is now actually populating some rudimentary data into the WebRenderScrollData before sending it across. This will be fleshed out in future patches. MozReview-Commit-ID: BROqpsHPRND
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
gfx/layers/wr/WebRenderScrollData.cpp
gfx/layers/wr/WebRenderScrollData.h
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -233,48 +233,38 @@ WebRenderLayerManager::CreateWebRenderCo
       aDisplayList->AppendToBottom(itemSameCoordinateSystemChildren);
       item->~nsDisplayItem();
       continue;
     }
 
     savedItems.AppendToTop(item);
 
     if (apzEnabled) {
+      bool forceNewLayerData = false;
+
+      // For some types of display items we want to force a new
+      // WebRenderLayerScrollData object, to ensure we preserve the APZ-relevant
+      // data that is in the display item.
+      switch (itemType) {
+      case nsDisplayItem::TYPE_SCROLL_INFO_LAYER:
+        forceNewLayerData = true;
+        break;
+      default:
+        break;
+      }
+
+      // Anytime the ASR changes we also want to force a new layer data because
+      // the stack of scroll metadata is going to be different for this
+      // display item than previously, so we can't squash the display items
+      // into the same "layer".
       const ActiveScrolledRoot* asr = item->GetActiveScrolledRoot();
-      // The ASR check here is just an optimization to avoid doing any unnecessary
-      // work in a common case, where adjacent items in the display list have
-      // the same ASR.
-      if (asr && asr != lastAsr) {
+      if (forceNewLayerData || asr != lastAsr) {
         lastAsr = asr;
-        FrameMetrics::ViewID id = nsLayoutUtils::ViewIDForASR(asr);
-        if (mScrollMetadata.find(id) == mScrollMetadata.end()) {
-          // We pass null here for the display item clip because we don't need
-          // the clip to be in the ScrollMetadata here; we will push the clip
-          // information into the WR display list directly.
-          Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
-              nullptr, item->ReferenceFrame(),
-              ContainerLayerParameters(), nullptr);
-          MOZ_ASSERT(metadata);
-          mScrollMetadata[id] = *metadata;
-        }
-      }
-      if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
-        // we should only really get one scroll info layer per scroll id, so
-        // it's not worth trying to get the ViewID and checking to see if we
-        // already have it in mScrollMetadata before doing the work of computing
-        // the metadata.
-        nsDisplayScrollInfoLayer* info = static_cast<nsDisplayScrollInfoLayer*>(item);
-        UniquePtr<ScrollMetadata> metadata = info->ComputeScrollMetadata(
-            nullptr, ContainerLayerParameters());
-        MOZ_ASSERT(metadata);
-        MOZ_ASSERT(metadata->GetMetrics().IsScrollInfoLayer());
-        FrameMetrics::ViewID id = metadata->GetMetrics().GetScrollId();
-        if (mScrollMetadata.find(id) == mScrollMetadata.end()) {
-          mScrollMetadata[id] = *metadata;
-        }
+        mLayerScrollData.emplace_back();
+        mLayerScrollData.back().Initialize(mScrollData, item);
       }
     }
 
     if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
                                        aDisplayListBuilder)) {
       PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
     }
   }
@@ -532,66 +522,77 @@ WebRenderLayerManager::EndTransactionInt
 
   if (mEndTransactionWithoutLayers) {
     // aDisplayList being null here means this is an empty transaction following a layers-free
     // transaction, so we reuse the previously built displaylist and scroll
     // metadata information
     if (aDisplayList && aDisplayListBuilder) {
       StackingContextHelper sc;
       mParentCommands.Clear();
-      mScrollMetadata.clear();
+      mScrollData = WebRenderScrollData();
+      MOZ_ASSERT(mLayerScrollData.empty());
 
       CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
 
       builder.Finalize(contentSize, mBuiltDisplayList);
+
+      // Append the WebRenderLayerScrollData items into WebRenderScrollData
+      // in reverse order, from topmost to bottommost. This is in keeping with
+      // the semantics of WebRenderScrollData.
+      for (auto i = mLayerScrollData.crbegin(); i != mLayerScrollData.crend(); i++) {
+        mScrollData.AddLayerData(*i);
+      }
+      mLayerScrollData.clear();
     }
 
     builder.PushBuiltDisplayList(mBuiltDisplayList);
     WrBridge()->AddWebRenderParentCommands(mParentCommands);
   } else {
+    mScrollData = WebRenderScrollData();
+
     mRoot->StartPendingAnimations(mAnimationReadyTime);
     StackingContextHelper sc;
 
     WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
+
+    // Need to do this after RenderLayer because the compositor animation IDs
+    // get populated during RenderLayer and we need those.
+    PopulateScrollData(mScrollData, mRoot.get());
   }
 
   mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
   WrBridge()->ClearReadLocks();
 
   // We can't finish this transaction so return. This usually
   // happens in an empty transaction where we can't repaint a painted layer.
   // In this case, leave the transaction open and let a full transaction happen.
   if (mTransactionIncomplete) {
     DiscardLocalImages();
     WrBridge()->ProcessWebRenderParentCommands();
     return false;
   }
 
-  WebRenderScrollData scrollData;
   if (AsyncPanZoomEnabled()) {
-    scrollData.SetFocusTarget(mFocusTarget);
+    mScrollData.SetFocusTarget(mFocusTarget);
     mFocusTarget = FocusTarget();
 
     if (mIsFirstPaint) {
-      scrollData.SetIsFirstPaint();
+      mScrollData.SetIsFirstPaint();
       mIsFirstPaint = false;
     }
-    scrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
-    if (mRoot) {
-      PopulateScrollData(scrollData, mRoot.get());
-    }
+    mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
   }
 
   bool sync = mTarget != nullptr;
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
 
   {
     AutoProfilerTracing
       tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
-    WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, scrollData);
+    WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, mScrollData);
   }
 
   MakeSnapshotIfRequired(size);
   mNeedsComposite = false;
 
   ClearDisplayItemLayers();
 
   // this may result in Layers being deleted, which results in
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -1,23 +1,26 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_WEBRENDERLAYERMANAGER_H
 #define GFX_WEBRENDERLAYERMANAGER_H
 
+#include <vector>
+
 #include "gfxPrefs.h"
 #include "Layers.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/layers/APZTestData.h"
 #include "mozilla/layers/FocusTarget.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/TransactionIdAllocator.h"
+#include "mozilla/layers/WebRenderScrollData.h"
 #include "mozilla/layers/WebRenderUserData.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "nsDisplayList.h"
 
 class nsIWidget;
 
 namespace mozilla {
@@ -231,19 +234,22 @@ private:
 
   LayerRefArray mKeepAlive;
 
   // These fields are used to save a copy of the display list for
   // empty transactions in layers-free mode.
   wr::BuiltDisplayList mBuiltDisplayList;
   nsTArray<WebRenderParentCommand> mParentCommands;
 
-  // We need this for building scroll data for the compositor in
-  // layers-free mode
-  std::unordered_map<FrameMetrics::ViewID, ScrollMetadata> mScrollMetadata;
+  // This holds the scroll data that we need to send to the compositor for
+  // APZ to do it's job
+  WebRenderScrollData mScrollData;
+  // We use this as a temporary data structure while building the mScrollData
+  // inside a layers-free transaction.
+  std::vector<WebRenderLayerScrollData> mLayerScrollData;
 
   // Layers that have been mutated. If we have an empty transaction
   // then a display item layer will no longer be valid
   // if it was a mutated layers.
   void AddMutatedLayer(Layer* aLayer);
   void ClearMutatedLayers();
   LayerRefArray mMutatedLayers;
   bool mTransactionIncomplete;
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -11,16 +11,22 @@
 #include "nsTArray.h"
 #include "UnitTransforms.h"
 
 namespace mozilla {
 namespace layers {
 
 WebRenderLayerScrollData::WebRenderLayerScrollData()
   : mDescendantCount(-1)
+  , mTransformIsPerspective(false)
+  , mEventRegionsOverride(EventRegionsOverride::NoOverride)
+  , mScrollbarAnimationId(0)
+  , mScrollbarTargetContainerId(FrameMetrics::NULL_SCROLL_ID)
+  , mIsScrollbarContainer(false)
+  , mFixedPosScrollContainerId(FrameMetrics::NULL_SCROLL_ID)
 {
 }
 
 WebRenderLayerScrollData::~WebRenderLayerScrollData()
 {
 }
 
 void
@@ -49,16 +55,41 @@ WebRenderLayerScrollData::Initialize(Web
       : EventRegionsOverride::NoOverride;
   mScrollThumbData = aLayer->GetScrollThumbData();
   mScrollbarAnimationId = aLayer->GetCompositorAnimationsId();
   mScrollbarTargetContainerId = aLayer->GetScrollbarTargetContainerId();
   mIsScrollbarContainer = aLayer->IsScrollbarContainer();
   mFixedPosScrollContainerId = aLayer->GetFixedPositionScrollContainerId();
 }
 
+void
+WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner,
+                                     nsDisplayItem* aItem)
+{
+  mDescendantCount = 0;
+
+  MOZ_ASSERT(aItem);
+  if (aItem->GetType() == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
+    nsDisplayScrollInfoLayer* info = static_cast<nsDisplayScrollInfoLayer*>(aItem);
+    UniquePtr<ScrollMetadata> metadata = info->ComputeScrollMetadata(
+        nullptr, ContainerLayerParameters());
+    MOZ_ASSERT(metadata);
+    MOZ_ASSERT(metadata->GetMetrics().IsScrollInfoLayer());
+    mScrollIds.AppendElement(aOwner.AddMetadata(*metadata));
+  }
+  for (const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot();
+       asr;
+       asr = asr->mParent) {
+    Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
+        nullptr, aItem->ReferenceFrame(), ContainerLayerParameters(), nullptr);
+    MOZ_ASSERT(metadata);
+    mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref()));
+  }
+}
+
 int32_t
 WebRenderLayerScrollData::GetDescendantCount() const
 {
   MOZ_ASSERT(mDescendantCount >= 0); // check that it was set
   return mDescendantCount;
 }
 
 size_t
@@ -108,16 +139,23 @@ size_t
 WebRenderScrollData::AddNewLayerData()
 {
   size_t len = mLayerScrollData.Length();
   Unused << mLayerScrollData.AppendElement();
   return len;
 }
 
 size_t
+WebRenderScrollData::AddLayerData(const WebRenderLayerScrollData& aData)
+{
+  mLayerScrollData.AppendElement(aData);
+  return mLayerScrollData.Length() - 1;
+}
+
+size_t
 WebRenderScrollData::GetLayerCount() const
 {
   return mLayerScrollData.Length();
 }
 
 WebRenderLayerScrollData*
 WebRenderScrollData::GetLayerDataMutable(size_t aIndex)
 {
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -36,16 +36,18 @@ public:
   ~WebRenderLayerScrollData();
 
   // Actually initialize the object. This is not done during the constructor
   // for optimization purposes (the call site is hard to write efficiently
   // if we do this in the constructor).
   void Initialize(WebRenderScrollData& aOwner,
                   Layer* aLayer,
                   int32_t aDescendantCount);
+  void Initialize(WebRenderScrollData& aOwner,
+                  nsDisplayItem* aItem);
 
   int32_t GetDescendantCount() const;
   size_t GetScrollMetadataCount() const;
 
   // Return the ScrollMetadata object that used to be on the original Layer
   // at the given index. Since we deduplicate the ScrollMetadata objects into
   // the array in the owning WebRenderScrollData object, we need to be passed
   // in a reference to that owner as well.
@@ -107,16 +109,19 @@ public:
   ~WebRenderScrollData();
 
   // Add the given ScrollMetadata if it doesn't already exist. Return an index
   // that can be used to look up the metadata later.
   size_t AddMetadata(const ScrollMetadata& aMetadata);
   // Add a new empty WebRenderLayerScrollData and return the index that can be
   // used to look it up via GetLayerData.
   size_t AddNewLayerData();
+  // Add the provided WebRenderLayerScrollData and return the index that can
+  // be used to look it up via GetLayerData.
+  size_t AddLayerData(const WebRenderLayerScrollData& aData);
 
   size_t GetLayerCount() const;
 
   // Return a pointer to the scroll data at the given index. Use with caution,
   // as the pointer may be invalidated if this WebRenderScrollData is mutated.
   WebRenderLayerScrollData* GetLayerDataMutable(size_t aIndex);
   const WebRenderLayerScrollData* GetLayerData(size_t aIndex) const;