Handle in-process device resets by recreating the entire rendering stack. (bug 1363126 part 2, r=rhunt)
authorDavid Anderson <dvander@alliedmods.net>
Thu, 11 May 2017 22:44:27 -0700
changeset 357940 ff60b177a442a1b0c73286c51f60ac014685f787
parent 357939 063adb4deaf5efe3ef4f80635dd68e15a7a0325e
child 357941 b8d1153cb94122c768648e7db8c4142f13b099b4
push id90244
push userdanderson@mozilla.com
push dateFri, 12 May 2017 05:46:11 +0000
treeherdermozilla-inbound@c78b979c5c59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhunt
bugs1363126
milestone55.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
Handle in-process device resets by recreating the entire rendering stack. (bug 1363126 part 2, r=rhunt)
dom/ipc/ContentParent.h
gfx/ipc/RemoteCompositorSession.cpp
gfx/ipc/RemoteCompositorSession.h
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/windows/nsWindowGfx.cpp
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -655,26 +655,27 @@ public:
   // This function is called when we are about to load a document from an
   // HTTP(S), FTP or wyciwyg channel for a content process.  It is a useful
   // place to start to kick off work as early as possible in response to such
   // document loads.
   nsresult AboutToLoadHttpFtpWyciwygDocumentForChild(nsIChannel* aChannel);
 
   nsresult TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal);
 
+  void OnCompositorDeviceReset() override;
+
 protected:
   void OnChannelConnected(int32_t pid) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool ShouldContinueFromReplyTimeout() override;
 
   void OnVarChanged(const GfxVarUpdate& aVar) override;
   void OnCompositorUnexpectedShutdown() override;
-  void OnCompositorDeviceReset() override;
 
 private:
   /**
    * A map of the remote content process type to a list of content parents
    * currently available to host *new* tabs/frames of that type.
    *
    * If a content process is identified as troubled or dead, it will be
    * removed from this list, but will still be in the sContentParents list for
--- a/gfx/ipc/RemoteCompositorSession.cpp
+++ b/gfx/ipc/RemoteCompositorSession.cpp
@@ -40,23 +40,16 @@ RemoteCompositorSession::~RemoteComposit
   // This should have been shutdown first.
   MOZ_ASSERT(!mCompositorBridgeChild);
 #if defined(MOZ_WIDGET_ANDROID)
   MOZ_ASSERT(!mUiCompositorControllerChild);
 #endif //defined(MOZ_WIDGET_ANDROID)
 }
 
 void
-RemoteCompositorSession::NotifyDeviceReset(uint64_t aSeqNo)
-{
-  MOZ_ASSERT(mWidget);
-  mWidget->OnRenderingDeviceReset(aSeqNo);
-}
-
-void
 RemoteCompositorSession::NotifySessionLost()
 {
   // Re-entrancy should be impossible: when we are being notified of a lost
   // session, we have by definition not shut down yet. We will shutdown, but
   // then will be removed from the notification list.
   MOZ_ASSERT(mWidget);
   mWidget->NotifyRemoteCompositorSessionLost(this);
 }
--- a/gfx/ipc/RemoteCompositorSession.h
+++ b/gfx/ipc/RemoteCompositorSession.h
@@ -28,17 +28,16 @@ public:
   GeckoContentController* GetContentController();
   nsIWidget* GetWidget();
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
   bool Reset(const nsTArray<LayersBackend>& aBackendHints,
              uint64_t aSeqNo,
              TextureFactoryIdentifier* aOutIdentifier) override;
   void Shutdown() override;
 
-  void NotifyDeviceReset(uint64_t aSeqNo);
   void NotifySessionLost();
 
 private:
   nsBaseWidget* mWidget;
   RefPtr<APZCTreeManagerChild> mAPZ;
   RefPtr<GeckoContentController> mContentController;
 };
 
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -311,52 +311,19 @@ void nsBaseWidget::DestroyLayerManager()
   if (mLayerManager) {
     mLayerManager->Destroy();
     mLayerManager = nullptr;
   }
   DestroyCompositor();
 }
 
 void
-nsBaseWidget::OnRenderingDeviceReset(uint64_t aSeqNo)
+nsBaseWidget::OnRenderingDeviceReset()
 {
-  if (!mLayerManager || !mCompositorSession) {
-    return;
-  }
-
-  nsTArray<LayersBackend> backendHints;
-  gfxPlatform::GetPlatform()->GetCompositorBackends(ComputeShouldAccelerate(), backendHints);
-
-  // If the existing compositor does not use acceleration, and this widget
-  // should not be accelerated, then there's no point in resetting.
-  //
-  // Note that if this widget should be accelerated, but instead has a basic
-  // compositor, we still reset just in case we're now in the position to get
-  // accelerated layers again.
-  RefPtr<ClientLayerManager> clm = mLayerManager->AsClientLayerManager();
-  if (!ComputeShouldAccelerate() &&
-      clm->GetCompositorBackendType() == LayersBackend::LAYERS_BASIC)
-  {
-    return;
-  }
-
-  // Recreate the compositor.
-  TextureFactoryIdentifier identifier;
-  if (!mCompositorSession->Reset(backendHints, aSeqNo, &identifier)) {
-    // No action was taken, so we don't have to do anything.
-    return;
-  }
-
-  // Invalidate all layers.
-  FrameLayerBuilder::InvalidateAllLayers(mLayerManager);
-
-  // Update the texture factory identifier.
-  clm->UpdateTextureFactoryIdentifier(identifier, aSeqNo);
-  ImageBridgeChild::IdentifyCompositorTextureHost(identifier);
-  gfx::VRManagerChild::IdentifyTextureHost(identifier);
+  DestroyLayerManager();
 }
 
 void
 nsBaseWidget::FreeShutdownObserver()
 {
   if (mShutdownObserver) {
     mShutdownObserver->Unregister();
   }
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -581,17 +581,17 @@ protected:
   virtual void WindowUsesOMTC() {}
   virtual void RegisterTouchWindow() {}
 
   nsIDocument* GetDocument() const;
 
   void EnsureTextEventDispatcher();
 
   // Notify the compositor that a device reset has occurred.
-  void OnRenderingDeviceReset(uint64_t aSeqNo);
+  void OnRenderingDeviceReset();
 
   bool UseAPZ();
 
   /**
    * For widgets that support synthesizing native touch events, this function
    * can be used to manage the current state of synthetic pointers. Each widget
    * must maintain its own MultiTouchInput instance and pass it in as the state,
    * along with the desired parameters for the changes. This function returns
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -174,20 +174,25 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
     return false;
 
   DeviceResetReason resetReason = DeviceResetReason::OK;
   if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset(&resetReason)) {
     gfxCriticalNote << "(nsWindow) Detected device reset: " << (int)resetReason;
 
     gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
 
-    uint64_t resetSeqNo = GPUProcessManager::Get()->GetNextDeviceResetSequenceNumber();
     nsTArray<nsWindow*> windows = EnumAllWindows();
     for (nsWindow* window : windows) {
-      window->OnRenderingDeviceReset(resetSeqNo);
+      window->OnRenderingDeviceReset();
+    }
+
+    nsTArray<mozilla::dom::ContentParent*> children;
+    mozilla::dom::ContentParent::GetAll(children);
+    for (const auto& child : children) {
+      child->OnCompositorDeviceReset();
     }
 
     gfxCriticalNote << "(nsWindow) Finished device reset.";
     return false;
   }
 
   // After we CallUpdateWindow to the child, occasionally a WM_PAINT message
   // is posted to the parent event loop with an empty update rect. Do a