Bug 1589022 - Partial support for moving a tab between windows with different APZ enablement. r=nika,tnikkel
authorBotond Ballo <botond@mozilla.com>
Mon, 18 Nov 2019 23:13:55 +0000
changeset 502510 408a199d1d47d782a0a6f43991d72a00a7a7da49
parent 502509 e6305a1457f025d598507456b87945036b49bbab
child 502511 081aa9877fc18f4ff43201375a12f77bdf4becfb
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika, tnikkel
bugs1589022
milestone72.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 1589022 - Partial support for moving a tab between windows with different APZ enablement. r=nika,tnikkel This involves two new IPC messages (both async) to propagate the change in compositor options (of which APZ enablement is one) from the GPU process to the parent process (via PCompositorBridge) and on to the content process (via PBrowser). The support is only partial, in that going from non-APZ to APZ is only supported if APZ was enabled at the time the window was created. Depends on D51467 Differential Revision: https://phabricator.services.mozilla.com/D51468
dom/ipc/BrowserChild.cpp
dom/ipc/BrowserChild.h
dom/ipc/PBrowser.ipdl
gfx/ipc/CompositorOptions.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/PCompositorBridge.ipdl
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -1226,16 +1226,37 @@ mozilla::ipc::IPCResult BrowserChild::Re
     const TextureFactoryIdentifier& aTextureFactoryIdentifier,
     const layers::LayersId& aLayersId,
     const CompositorOptions& aCompositorOptions, const bool& aLayersConnected) {
   mLayersConnected = Some(aLayersConnected);
   InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult BrowserChild::RecvCompositorOptionsChanged(
+    const CompositorOptions& aNewOptions) {
+  MOZ_ASSERT(mCompositorOptions);
+
+  // The only compositor option we currently support changing is APZ
+  // enablement. Even that is only partially supported for now:
+  //   * Going from APZ to non-APZ is fine - we just flip the stored flag.
+  //     Note that we keep the actors (mApzcTreeManager, and the APZChild
+  //     created in InitAPZState()) around (read on for why).
+  //   * Going from non-APZ to APZ is only supported if we were using
+  //     APZ initially (at InitRendering() time) and we are transitioning
+  //     back. In this case, we just reuse the actors which we kept around.
+  //     Fully supporting a non-APZ to APZ transition (i.e. even in cases
+  //     where we initialized as non-APZ) would require setting up the actors
+  //     here. (In that case, we would also have the options of destroying
+  //     the actors in the APZ --> non-APZ case, and always re-creating them
+  //     during a non-APZ --> APZ transition).
+  mCompositorOptions->SetUseAPZ(aNewOptions.UseAPZ());
+  return IPC_OK();
+}
+
 mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
     const DimensionInfo& aDimensionInfo) {
   // When recording/replaying we need to make sure the dimensions are up to
   // date on the compositor used in this process.
   if (mLayersConnected.isNothing() && !recordreplay::IsRecordingOrReplaying()) {
     return IPC_OK();
   }
 
--- a/dom/ipc/BrowserChild.h
+++ b/dom/ipc/BrowserChild.h
@@ -273,16 +273,19 @@ class BrowserChild final : public nsMess
                                    const nsSizeMode& aSizeMode);
 
   mozilla::ipc::IPCResult RecvInitRendering(
       const TextureFactoryIdentifier& aTextureFactoryIdentifier,
       const layers::LayersId& aLayersId,
       const mozilla::layers::CompositorOptions& aCompositorOptions,
       const bool& aLayersConnected);
 
+  mozilla::ipc::IPCResult RecvCompositorOptionsChanged(
+      const mozilla::layers::CompositorOptions& aNewOptions);
+
   mozilla::ipc::IPCResult RecvUpdateDimensions(
       const mozilla::dom::DimensionInfo& aDimensionInfo);
   mozilla::ipc::IPCResult RecvSizeModeChanged(const nsSizeMode& aSizeMode);
 
   mozilla::ipc::IPCResult RecvChildToParentMatrix(
       const mozilla::Maybe<mozilla::gfx::Matrix4x4>& aMatrix,
       const mozilla::ScreenRect& aRemoteDocumentRect);
 
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -731,16 +731,18 @@ child:
                bool parentIsActive,
                nsSizeMode sizeMode);
 
     async InitRendering(TextureFactoryIdentifier textureFactoryIdentifier,
                         LayersId layersId,
                         CompositorOptions compositorOptions,
                         bool layersConnected);
 
+    async CompositorOptionsChanged(CompositorOptions newOptions);
+
     async LoadURL(nsCString uri, ShowInfo info);
 
     async ResumeLoad(uint64_t pendingSwitchID, ShowInfo info);
 
     async UpdateDimensions(DimensionInfo dimensions) compressall;
 
     async SizeModeChanged(nsSizeMode sizeMode);
 
--- a/gfx/ipc/CompositorOptions.h
+++ b/gfx/ipc/CompositorOptions.h
@@ -41,16 +41,18 @@ class CompositorOptions {
         mUseAdvancedLayers(false),
         mInitiallyPaused(false) {}
 
   bool UseAPZ() const { return mUseAPZ; }
   bool UseWebRender() const { return mUseWebRender; }
   bool UseAdvancedLayers() const { return mUseAdvancedLayers; }
   bool InitiallyPaused() const { return mInitiallyPaused; }
 
+  void SetUseAPZ(bool aUseAPZ) { mUseAPZ = aUseAPZ; }
+
   void SetUseAdvancedLayers(bool aUseAdvancedLayers) {
     mUseAdvancedLayers = aUseAdvancedLayers;
   }
 
   void SetInitiallyPaused(bool aPauseAtStartup) {
     mInitiallyPaused = aPauseAtStartup;
   }
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -834,16 +834,28 @@ mozilla::ipc::IPCResult CompositorBridge
 
   if (RefPtr<dom::BrowserParent> tab =
           dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) {
     tab->LayerTreeUpdate(aEpoch, aActive);
   }
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvCompositorOptionsChanged(
+    const LayersId& aLayersId, const CompositorOptions& aNewOptions) {
+  MOZ_ASSERT(aLayersId.IsValid());
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  if (RefPtr<dom::BrowserParent> tab =
+          dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) {
+    Unused << tab->SendCompositorOptionsChanged(aNewOptions);
+  }
+  return IPC_OK();
+}
+
 void CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(
     TextureClient* aClient) {
   if (!aClient) {
     return;
   }
 
   bool waitNotifyNotUsed =
       aClient->GetFlags() & TextureFlags::RECYCLE ||
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -293,16 +293,19 @@ class CompositorBridgeChild final : publ
       const ViewID& aId, const uint32_t& aAPZCId);
 
   mozilla::ipc::IPCResult RecvRemotePaintIsReady();
 
   mozilla::ipc::IPCResult RecvObserveLayersUpdate(
       const LayersId& aLayersId, const LayersObserverEpoch& aEpoch,
       const bool& aActive);
 
+  mozilla::ipc::IPCResult RecvCompositorOptionsChanged(
+      const LayersId& aLayersId, const CompositorOptions& aNewOptions);
+
   uint64_t GetNextResourceId();
 
   void ClearSharedFrameMetricsData(LayersId aLayersId);
 
   // Class used to store the shared FrameMetrics, mutex, and APZCId  in a hash
   // table
   class SharedFrameMetricsData final {
    public:
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1755,16 +1755,17 @@ static CompositorOptionsChangeKind Class
   return CompositorOptionsChangeKind::eUnsupported;
 }
 
 mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
     const LayersId& child) {
   RefPtr<APZUpdater> oldApzUpdater;
   APZCTreeManagerParent* parent;
   bool scheduleComposition = false;
+  bool apzEnablementChanged = false;
   RefPtr<ContentCompositorBridgeParent> cpcp;
   RefPtr<WebRenderBridgeParent> childWrBridge;
 
   // Before adopting the child, save the old compositor's root content
   // controller. We may need this to clear old layer transforms associated
   // with the child.
   // This is outside the lock because GetGeckoContentControllerForRoot()
   // does its own locking.
@@ -1789,16 +1790,17 @@ mozilla::ipc::IPCResult CompositorBridge
                      "unexpected ways");
           break;
         }
         case CompositorOptionsChangeKind::eBestEffort: {
           NS_WARNING(
               "Moving tab between windows with different APZ enablement. "
               "This is supported on a best-effort basis, but some things may "
               "break.");
+          apzEnablementChanged = true;
           break;
         }
         case CompositorOptionsChangeKind::eSupported: {
           // The common case, no action required.
           break;
         }
       }
       oldApzUpdater = sIndirectLayerTrees[child].mParent->mApzUpdater;
@@ -1859,16 +1861,19 @@ mozilla::ipc::IPCResult CompositorBridge
   if (mApzUpdater) {
     if (parent) {
       MOZ_ASSERT(mApzcTreeManager);
       parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
     }
     mApzUpdater->NotifyLayerTreeAdopted(
         WRRootId(child, gfxUtils::GetContentRenderRoot()), oldApzUpdater);
   }
+  if (apzEnablementChanged) {
+    Unused << SendCompositorOptionsChanged(child, mOptions);
+  }
   return IPC_OK();
 }
 
 PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent(
     const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize& aSize) {
   MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
   MOZ_ASSERT(!mWrBridge);
   MOZ_ASSERT(!mCompositor);
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -150,16 +150,18 @@ child:
    * widget.
    */
   async HideAllPlugins(uintptr_t aParentWidget);
 
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
   async ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive);
 
+  async CompositorOptionsChanged(LayersId id, CompositorOptions newOptions);
+
 parent:
   async __delete__();
 
   // Must be called before Initialize().
   async PCompositorWidget(CompositorWidgetInitData aInitData);
 
   // When out-of-process, this must be called to finish initialization.
   sync Initialize(LayersId rootLayerTreeId);