Bug 1326421 - Have content processes create WebRenderLayerManagers if and only if the compositor being used is WebRender. r?dvander draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 12 Jan 2017 15:08:01 -0500
changeset 460010 7f6dcdf9eb1fca063a58d586afbe933cd5b695db
parent 460009 ed3480ca04d2e3f166b5c059bfeaf53be43920a7
child 460011 7c01a61aaba94d897061f01f31bdcdd128ab39c3
push id41343
push userkgupta@mozilla.com
push dateThu, 12 Jan 2017 20:13:44 +0000
reviewersdvander
bugs1326421
milestone53.0a1
Bug 1326421 - Have content processes create WebRenderLayerManagers if and only if the compositor being used is WebRender. r?dvander Also guard against a scenario where RecvDocShellIsActive gets called before we have the layers id for the tab. Because we need to have the compositor options (which requires knowing the layers id) before we can create the layer manager, we need to avoid calling GetLayerManager() before we have the options. MozReview-Commit-ID: LIo1Q2peiY5
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
widget/PuppetWidget.cpp
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -420,16 +420,24 @@ TabChild::TabChild(nsIContentChild* aMan
     }
   }
 
   for (uint32_t idx = 0; idx < NUMBER_OF_AUDIO_CHANNELS; idx++) {
     mAudioChannelsActive.AppendElement(false);
   }
 }
 
+const CompositorOptions&
+TabChild::GetCompositorOptions() const
+{
+  // If you're calling this before mCompositorOptions is set, well.. don't.
+  MOZ_ASSERT(mCompositorOptions);
+  return mCompositorOptions.ref();
+}
+
 bool
 TabChild::AsyncPanZoomEnabled() const
 {
   // If we have received the CompositorOptions we can answer definitively. If
   // not, return a best guess based on gfxPlaform values.
   return mCompositorOptions ? mCompositorOptions->UseAPZ()
                             : gfxPlatform::AsyncPanZoomEnabled();
 }
@@ -2306,36 +2314,42 @@ TabChild::RecvSetDocShellIsActive(const 
   // channel and the PContent channel, we have an ordering problem. This code
   // ensures that we respect the order in which the requests were made and
   // ignore stale requests.
   if (mLayerObserverEpoch >= aLayerObserverEpoch) {
     return IPC_OK();
   }
   mLayerObserverEpoch = aLayerObserverEpoch;
 
-  MOZ_ASSERT(mPuppetWidget);
-  MOZ_ASSERT(mPuppetWidget->GetLayerManager());
-  MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
-          || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
-
   auto clearForcePaint = MakeScopeExit([&] {
     // We might force a paint, or we might already have painted and this is a
     // no-op. In either case, once we exit this scope, we need to alert the
     // ProcessHangMonitor that we've finished responding to what might have
     // been a request to force paint. This is so that the BackgroundHangMonitor
     // for force painting can be made to wait again.
     if (aIsActive) {
       ProcessHangMonitor::ClearForcePaint();
     }
   });
 
-  // We send the current layer observer epoch to the compositor so that
-  // TabParent knows whether a layer update notification corresponds to the
-  // latest SetDocShellIsActive request that was made.
-  mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
+  if (mCompositorOptions) {
+    // Note that |GetLayerManager()| has side-effects in that it creates a layer
+    // manager if one doesn't exist already. Calling it inside a debug-only
+    // assertion is generally bad but in this case we call it unconditionally
+    // just below so it's ok.
+    MOZ_ASSERT(mPuppetWidget);
+    MOZ_ASSERT(mPuppetWidget->GetLayerManager());
+    MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
+            || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
+
+    // We send the current layer observer epoch to the compositor so that
+    // TabParent knows whether a layer update notification corresponds to the
+    // latest SetDocShellIsActive request that was made.
+    mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
+  }
 
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !aIsActive;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   if (docShell) {
     bool wasActive;
     docShell->GetIsActive(&wasActive);
     if (aIsActive && wasActive) {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -613,16 +613,17 @@ public:
 
   bool IPCOpen() const { return mIPCOpen; }
 
   bool ParentIsActive() const
   {
     return mParentIsActive;
   }
 
+  const mozilla::layers::CompositorOptions& GetCompositorOptions() const;
   bool AsyncPanZoomEnabled() const;
 
   virtual ScreenIntSize GetInnerSize() override;
 
   // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
   void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                   const uint64_t& aLayersId,
                   PRenderFrameChild* aRenderFrame,
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -580,33 +580,33 @@ PuppetWidget::ExecuteNativeKeyBinding(Na
 }
 
 LayerManager*
 PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
                               LayersBackend aBackendHint,
                               LayerManagerPersistence aPersistence)
 {
   if (!mLayerManager) {
-    if (gfxPrefs::WebRenderEnabled()) {
+    if (mTabChild->GetCompositorOptions().UseWebRender()) {
       mLayerManager = new WebRenderLayerManager(this);
     } else {
       mLayerManager = new ClientLayerManager(this);
     }
   }
   ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder();
   if (lf && !lf->HasShadowManager() && aShadowManager) {
     lf->SetShadowManager(aShadowManager);
   }
   return mLayerManager;
 }
 
 LayerManager*
 PuppetWidget::RecreateLayerManager(PLayerTransactionChild* aShadowManager)
 {
-  if (gfxPrefs::WebRenderEnabled()) {
+  if (mTabChild->GetCompositorOptions().UseWebRender()) {
     mLayerManager = new WebRenderLayerManager(this);
   } else {
     mLayerManager = new ClientLayerManager(this);
   }
   if (ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder()) {
     lf->SetShadowManager(aShadowManager);
   }
   return mLayerManager;