Bug 1511740 - Use nsDisplayAsyncZoom items to insert zooming animations in WR. r=jrmuizel,botond
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 04 Mar 2019 20:55:46 +0000
changeset 520153 fa641ad0f4b8aeb31237ab51ef5ce5797ac56b82
parent 520152 adf5830d08b510ee37df21177ac71cd9c389660f
child 520154 774a5ee90bae16072134941ebefab18f203ffe74
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, botond
bugs1511740
milestone67.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 1511740 - Use nsDisplayAsyncZoom items to insert zooming animations in WR. r=jrmuizel,botond The way we control APZ zooming in WebRender is by inserting an animation property placeholder on a WR stacking context, and then having APZ update the animation transform value with the proper matrix at composite time. Previously, the stacking context being used was the rootmost stacking context in the content process. However this doesn't work for zoomable content in the UI process (e.g. about:support), and after recent changes, also wraps display items that should not be affected by zoom (e.g. scrollbars or the background color item). This patch moves the animation property placeholder so that it corresponds to the newly added nsDisplayAsyncZoom display item, which corrects both of the above problems and is conceptually in line with the desired behaviour. Differential Revision: https://phabricator.services.mozilla.com/D21795
gfx/layers/wr/WebRenderCommandBuilder.cpp
gfx/layers/wr/WebRenderCommandBuilder.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1434,31 +1434,24 @@ void WebRenderCommandBuilder::BuildWebRe
   mLastCanvasDatas.Clear();
   mLastAsr = nullptr;
   mBuilderDumpIndex = 0;
   mContainsSVGGroup = false;
   MOZ_ASSERT(mDumpIndent == 0);
   mClipManager.BeginBuild(mManager, aBuilder);
 
   {
-    if (!mZoomProp && gfxPrefs::APZAllowZooming() && XRE_IsContentProcess()) {
-      mZoomProp.emplace();
-      mZoomProp->effect_type = wr::WrAnimationType::Transform;
-      mZoomProp->id = AnimationHelper::GetNextCompositorAnimationsId();
-    }
-
     nsPresContext* presContext =
         aDisplayListBuilder->RootReferenceFrame()->PresContext();
     bool isTopLevelContent =
         presContext->Document()->IsTopLevelContentDocument();
 
     wr::StackingContextParams params;
     params.mFilters = std::move(aFilters.filters);
     params.mFilterDatas = std::move(aFilters.filter_datas);
-    params.animation = mZoomProp.ptrOr(nullptr);
     params.cache_tiles = isTopLevelContent;
     params.clip =
         wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
 
     StackingContextHelper pageRootSc(sc, nullptr, nullptr, nullptr, aBuilder,
                                      params);
     if (ShouldDumpDisplayList(aDisplayListBuilder)) {
       mBuilderDumpIndex =
@@ -1467,19 +1460,16 @@ void WebRenderCommandBuilder::BuildWebRe
     CreateWebRenderCommandsFromDisplayList(aDisplayList, nullptr,
                                            aDisplayListBuilder, pageRootSc,
                                            aBuilder, aResourceUpdates);
   }
 
   // Make a "root" layer data that has everything else as descendants
   mLayerScrollData.emplace_back();
   mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
-  if (mZoomProp) {
-    mLayerScrollData.back().SetZoomAnimationId(mZoomProp->id);
-  }
   auto callback =
       [&aScrollData](ScrollableLayerGuid::ViewID aScrollId) -> bool {
     return aScrollData.HasMetadataFor(aScrollId).isSome();
   };
   if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata(
           aDisplayListBuilder, mManager, ContainerLayerParameters(),
           callback)) {
     mLayerScrollData.back().AppendScrollMetadata(aScrollData,
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -189,20 +189,16 @@ class WebRenderCommandBuilder {
   WebRenderUserDataRefTable mWebRenderUserDatas;
 
   // Store of WebRenderCanvasData objects for use in empty transactions
   CanvasDataSet mLastCanvasDatas;
 
   wr::usize mBuilderDumpIndex;
   wr::usize mDumpIndent;
 
-  // When zooming is enabled, this stores the animation property that we use
-  // to manipulate the zoom from APZ.
-  Maybe<wr::WrAnimationProperty> mZoomProp;
-
  public:
   // Whether consecutive inactive display items should be grouped into one
   // blob image.
   bool mDoGrouping;
   Maybe<nsRect> mClippedGroupBounds;
 
   // True if we're currently within an opacity:0 container, and only
   // plugin and hit test items should be considered.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6355,16 +6355,20 @@ bool nsDisplayOwnLayer::IsScrollThumbLay
          layers::ScrollbarLayerType::Thumb;
 }
 
 bool nsDisplayOwnLayer::IsScrollbarContainer() const {
   return mScrollbarData.mScrollbarLayerType ==
          layers::ScrollbarLayerType::Container;
 }
 
+bool nsDisplayOwnLayer::IsZoomingLayer() const {
+  return GetType() == DisplayItemType::TYPE_ASYNC_ZOOM;
+}
+
 bool nsDisplayOwnLayer::ShouldBuildLayerEvenIfInvisible(
     nsDisplayListBuilder* aBuilder) const {
   // Render scroll thumb layers even if they are invisible, because async
   // scrolling might bring them into view.
   return IsScrollThumbLayer();
 }
 
 // nsDisplayOpacity uses layers for rendering
@@ -6387,20 +6391,22 @@ already_AddRefed<Layer> nsDisplayOwnLaye
 }
 
 bool nsDisplayOwnLayer::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc, RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
   Maybe<wr::WrAnimationProperty> prop;
-  if (aManager->LayerManager()->AsyncPanZoomEnabled() && IsScrollThumbLayer()) {
-    // APZ is enabled and this is a scroll thumb, so we need to create and
-    // set an animation id. That way APZ can move this scrollthumb around as
-    // needed.
+  bool needsProp = aManager->LayerManager()->AsyncPanZoomEnabled() &&
+                   (IsScrollThumbLayer() || IsZoomingLayer());
+  if (needsProp) {
+    // APZ is enabled and this is a scroll thumb or zooming layer, so we need
+    // to create and set an animation id. That way APZ can adjust the position/
+    // zoom of this content asynchronously as needed.
     RefPtr<WebRenderAnimationData> animationData =
         aManager->CommandBuilder()
             .CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
     AnimationInfo& animationInfo = animationData->GetAnimationInfo();
     animationInfo.EnsureAnimationsId();
     mWrAnimationId = animationInfo.GetCompositorAnimationsId();
 
     prop.emplace();
@@ -6418,35 +6424,44 @@ bool nsDisplayOwnLayer::CreateWebRenderC
   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
   return true;
 }
 
 bool nsDisplayOwnLayer::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
     mozilla::layers::WebRenderLayerScrollData* aLayerData) {
-  bool ret = false;
-
-  if (IsScrollThumbLayer() || IsScrollbarContainer()) {
-    ret = true;
-    if (aLayerData) {
-      aLayerData->SetScrollbarData(mScrollbarData);
-      if (IsScrollThumbLayer()) {
-        aLayerData->SetScrollbarAnimationId(mWrAnimationId);
-        LayoutDeviceRect bounds = LayoutDeviceIntRect::FromAppUnits(
-            mBounds, mFrame->PresContext()->AppUnitsPerDevPixel());
-        // Assume a resolution of 1.0 for now because this is a WebRender
-        // codepath and we don't really handle resolution on the Gecko side
-        LayerIntRect layerBounds =
-            RoundedOut(bounds * LayoutDeviceToLayerScale(1.0f));
-        aLayerData->SetVisibleRegion(LayerIntRegion(layerBounds));
-      }
-    }
-  }
-  return ret;
+  bool isRelevantToApz =
+      (IsScrollThumbLayer() || IsScrollbarContainer() || IsZoomingLayer());
+  if (!isRelevantToApz) {
+    return false;
+  }
+
+  if (!aLayerData) {
+    return true;
+  }
+
+  if (IsZoomingLayer()) {
+    aLayerData->SetZoomAnimationId(mWrAnimationId);
+    return true;
+  }
+
+  aLayerData->SetScrollbarData(mScrollbarData);
+  if (IsScrollThumbLayer()) {
+    aLayerData->SetScrollbarAnimationId(mWrAnimationId);
+    LayoutDeviceRect bounds = LayoutDeviceIntRect::FromAppUnits(
+        mBounds, mFrame->PresContext()->AppUnitsPerDevPixel());
+    // We use a resolution of 1.0 because this is a WebRender codepath which
+    // always uses containerless scrolling, and so resolution doesn't apply to
+    // scrollbars.
+    LayerIntRect layerBounds =
+        RoundedOut(bounds * LayoutDeviceToLayerScale(1.0f));
+    aLayerData->SetVisibleRegion(LayerIntRegion(layerBounds));
+  }
+  return true;
 }
 
 void nsDisplayOwnLayer::WriteDebugInfo(std::stringstream& aStream) {
   aStream << nsPrintfCString(" (flags 0x%x) (scrolltarget %" PRIu64 ")",
                              (int)mFlags, mScrollbarData.mTargetViewId)
                  .get();
 }
 
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -5722,16 +5722,17 @@ class nsDisplayOwnLayer : public nsDispl
   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
     return false;
   }
 
   void WriteDebugInfo(std::stringstream& aStream) override;
   nsDisplayOwnLayerFlags GetFlags() { return mFlags; }
   bool IsScrollThumbLayer() const;
   bool IsScrollbarContainer() const;
+  bool IsZoomingLayer() const;
 
  protected:
   nsDisplayOwnLayerFlags mFlags;
 
   /**
    * If this nsDisplayOwnLayer represents a scroll thumb layer or a
    * scrollbar container layer, mScrollbarData stores information
    * about the scrollbar. Otherwise, mScrollbarData will be