Bug 1397426 - Make TabParent's assume they're rendering layers by default on construction. r?billm draft
authorMike Conley <mconley@mozilla.com>
Mon, 20 Nov 2017 11:41:11 -0500
changeset 702121 2768b7f3a726c1a717751f564ccf27780810b9af
parent 702120 464840beb1f8c56e75a45d70906e22e577be5677
child 702122 c254635e7461e8053f74d5140b8184456eb3f32e
push id90385
push userbmo:mconley@mozilla.com
push dateWed, 22 Nov 2017 19:08:31 +0000
reviewersbillm
bugs1397426
milestone59.0a1
Bug 1397426 - Make TabParent's assume they're rendering layers by default on construction. r?billm This assumption also mirrors how non-remote browsers have their docShells active by default. In order to do this, I also have to increase the initial epoch's for the TabParent and TabChild, as if a RenderLayers has been called. Originally, since the epochs initted at 0, and the epochs stored by the [Layer|WebRender]TransactionParent were also initted at 0, we'd hit this branch: https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/gfx/layers/ipc/LayerTransactionParent.cpp#703 and then we'd never alert the TabParent about the layer upload. MozReview-Commit-ID: 6PP1eCnisYK
browser/base/content/tabbrowser.xml
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4467,18 +4467,17 @@
               window.addEventListener("TabRemotenessChange", this);
               window.addEventListener("sizemodechange", this);
               window.addEventListener("occlusionstatechange", this);
               window.addEventListener("SwapDocShells", this, true);
               window.addEventListener("EndSwapDocShells", this, true);
 
               let tab = this.requestedTab;
               let browser = tab.linkedBrowser;
-              let tabIsLoaded = !browser.isRemoteBrowser ||
-                                browser.frameLoader.tabParent.hasPresented;
+              let tabIsLoaded = browser.renderingLayers;
 
               if (!this.minimizedOrFullyOccluded) {
                 this.log("Initial tab is loaded?: " + tabIsLoaded);
                 this.setTabState(tab, tabIsLoaded ? this.STATE_LOADED
                                                   : this.STATE_LOADING);
               }
               for (let ppBrowser of this.tabbrowser._printPreviewBrowsers) {
                 let ppTab = this.tabbrowser.getTabForBrowser(ppBrowser);
@@ -4890,16 +4889,23 @@
               this.loadTimer = null;
               this.loadingTab = null;
               this.postActions();
             },
 
             // Fires when the layers become available for a tab.
             onLayersReady(browser) {
               let tab = this.tabbrowser.getTabForBrowser(browser);
+              if (!tab) {
+                // We probably got a layer update from a tab that got before
+                // the switcher was created, or for browser that's not being
+                // tracked by the async tab switcher (like the preloaded about:newtab).
+                return;
+              }
+
               this.logState(`onLayersReady(${tab._tPos}, ${browser.isRemoteBrowser})`);
 
               this.assert(this.getTabState(tab) == this.STATE_LOADING ||
                           this.getTabState(tab) == this.STATE_LOADED);
               this.setTabState(tab, this.STATE_LOADED);
 
               if (this.loadingTab === tab) {
                 this.clearTimer(this.loadTimer);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -424,17 +424,17 @@ TabChild::TabChild(nsIContentChild* aMan
   , mUniqueId(aTabId)
   , mIsTransparent(false)
   , mIPCOpen(false)
   , mParentIsActive(false)
   , mDidSetRealShowInfo(false)
   , mDidLoadURLInit(false)
   , mAwaitingLA(false)
   , mSkipKeyPress(false)
-  , mLayerObserverEpoch(0)
+  , mLayerObserverEpoch(1)
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   , mNativeWindowHandle(0)
 #endif
 #if defined(ACCESSIBILITY)
   , mTopLevelDocAccessibleChild(nullptr)
 #endif
   , mPendingDocShellIsActive(false)
   , mPendingDocShellReceivedMessage(false)
@@ -2933,16 +2933,19 @@ TabChild::InitRenderingState(const Textu
     }
 
     if (success) {
       MOZ_ASSERT(mLayersConnected == Some(true));
       // Succeeded to create "remote" layer manager
       ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
       gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
       InitAPZState();
+      RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
+      MOZ_ASSERT(lm);
+      lm->SetLayerObserverEpoch(mLayerObserverEpoch);
     } else {
       NS_WARNING("Fallback to BasicLayerManager");
       mLayersConnected = Some(false);
     }
 
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
 
@@ -3046,17 +3049,24 @@ TabChild::MakeVisible()
 
 void
 TabChild::MakeHidden()
 {
   if (!IsVisible()) {
     return;
   }
 
-  ClearCachedResources();
+  // Due to the nested event loop in ContentChild::ProvideWindowCommon,
+  // it's possible to be told to become hidden before we're finished
+  // setting up a layer manager. We should skip clearing cached layers
+  // in that case, since doing so might accidentally put is into
+  // BasicLayers mode.
+  if (mPuppetWidget && mPuppetWidget->HasLayerManager()) {
+    ClearCachedResources();
+  }
 
   // Hide all plugins in this tab.
   if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
     if (nsPresContext* presContext = shell->GetPresContext()) {
       nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
       nsIFrame* rootFrame = shell->FrameConstructor()->GetRootFrame();
       rootPresContext->ComputePluginGeometryUpdates(rootFrame, nullptr, nullptr);
       rootPresContext->ApplyPluginGeometryUpdates();
@@ -3551,17 +3561,17 @@ TabChild::GetOuterRect()
   LayoutDeviceIntRect outerRect =
     RoundedToInt(mUnscaledOuterRect * mPuppetWidget->GetDefaultScale());
   return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
 }
 
 void
 TabChild::ForcePaint(uint64_t aLayerObserverEpoch)
 {
-  if (!IPCOpen()) {
+  if (!IPCOpen() || !mPuppetWidget || !mPuppetWidget->HasLayerManager()) {
     // Don't bother doing anything now. Better to wait until we receive the
     // message on the PContent channel.
     return;
   }
 
   nsAutoScriptBlocker scriptBlocker;
   RecvRenderLayers(true, aLayerObserverEpoch);
 }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -166,19 +166,19 @@ TabParent::TabParent(nsIContentParent* a
   , mTabId(aTabId)
   , mCreatingWindow(false)
   , mCursor(eCursorInvalid)
   , mTabSetsCursor(false)
   , mHasContentOpener(false)
 #ifdef DEBUG
   , mActiveSupressDisplayportCount(0)
 #endif
-  , mLayerTreeEpoch(0)
+  , mLayerTreeEpoch(1)
   , mPreserveLayers(false)
-  , mRenderLayers(false)
+  , mRenderLayers(true)
   , mHasLayers(false)
   , mHasPresented(false)
   , mHasBeforeUnload(false)
   , mIsMouseEnterIntoWidgetEventSuppressed(false)
 {
   MOZ_ASSERT(aManager);
   // When the input event queue is disabled, we don't need to handle the case
   // that some input events are dispatched before PBrowserConstructor.