Bug 1274663 - Expose API to trigger device reset. r=dvander
authordomfarolino@gmail.com <domfarolino@gmail.com>
Thu, 15 Jun 2017 14:34:00 -0400
changeset 364209 db5cc36763c1dff6c285011f30ded88304ca42b9
parent 364208 e886bf1ba8fceb67c705b3951bd2da2c72af1a59
child 364210 03681158d59c708f6f68328e2f6a576be50f851e
push id91501
push userryanvm@gmail.com
push dateFri, 16 Jun 2017 00:19:17 +0000
treeherdermozilla-inbound@50f92f81d4da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1274663
milestone56.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 1274663 - Expose API to trigger device reset. r=dvander
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
gfx/ipc/GPUChild.cpp
gfx/ipc/GPUProcessHost.h
gfx/ipc/GPUProcessManager.cpp
gfx/ipc/GPUProcessManager.h
gfx/ipc/InProcessCompositorSession.cpp
gfx/ipc/InProcessCompositorSession.h
gfx/ipc/RemoteCompositorSession.cpp
gfx/ipc/RemoteCompositorSession.h
gfx/layers/client/ClientLayerManager.cpp
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/windows/nsWindowGfx.cpp
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -79,16 +79,17 @@
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/IDBMutableFileBinding.h"
 #include "mozilla/dom/IDBMutableFile.h"
 #include "mozilla/dom/IndexedDatabaseManager.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/dom/quota/QuotaManager.h"
+#include "mozilla/dom/ContentChild.h"
 #include "mozilla/layers/FrameUniformityData.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "nsPrintfCString.h"
 #include "nsViewportInfo.h"
 #include "nsIFormControl.h"
 #include "nsIScriptError.h"
 //#include "nsWidgetsCID.h"
 #include "FrameLayerBuilder.h"
@@ -4126,16 +4127,32 @@ nsDOMWindowUtils::EnterChaosMode()
 NS_IMETHODIMP
 nsDOMWindowUtils::LeaveChaosMode()
 {
   ChaosMode::leaveChaosMode();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::TriggerDeviceReset()
+{
+  ContentChild* cc = ContentChild::GetSingleton();
+  if (cc) {
+    cc->SendDeviceReset();
+    return NS_OK;
+  }
+
+  GPUProcessManager* pm = GPUProcessManager::Get();
+  if (pm) {
+    pm->TriggerDeviceResetForTesting();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::ForceUseCounterFlush(nsIDOMNode *aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode)) {
     mozilla::css::ImageLoader* loader = doc->StyleImageLoader();
     loader->FlushUseCounters();
 
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -915,17 +915,17 @@ interface nsIDOMWindowUtils : nsISupport
    * @param aLeftSize How much to expand left the rectangle
    * @param aIgnoreRootScrollFrame whether or not to ignore the root scroll
    *        frame when retrieving the element. If false, this method returns
    *        null for coordinates outside of the viewport.
    * @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
    */
   nsIDOMNodeList nodesFromRect(in float aX,
                                in float aY,
-                               in float aTopSize, 
+                               in float aTopSize,
                                in float aRightSize,
                                in float aBottomSize,
                                in float aLeftSize,
                                in boolean aIgnoreRootScrollFrame,
                                in boolean aFlushLayout);
 
 
   /**
@@ -1403,17 +1403,17 @@ interface nsIDOMWindowUtils : nsISupport
   void resumeTimeouts();
 
   /**
    * What type of layer manager the widget associated with this window is
    * using. "Basic" is unaccelerated; other types are accelerated. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute AString layerManagerType;
-  
+
   /**
    * True if the layer manager for the widget associated with this window is
    * forwarding layers to a remote compositor, false otherwise. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute boolean layerManagerRemote;
 
   /**
@@ -1589,17 +1589,17 @@ interface nsIDOMWindowUtils : nsISupport
 
   /**
    * Checks the layer tree for this window and returns true
    * if all layers have transforms that are translations by integers,
    * no leaf layers overlap, and the union of the leaf layers is exactly
    * the bounds of the window. Always returns true in non-DEBUG builds.
    */
   boolean leafLayersPartitionWindow();
- 
+
   /**
    * Check if any PaintedLayer painting has been done for this element,
    * clears the painted flags if they have.
    */
   boolean checkAndClearPaintedState(in nsIDOMElement aElement);
 
   /**
    * Check whether all display items of the primary frame of aElement have been
@@ -1724,17 +1724,17 @@ interface nsIDOMWindowUtils : nsISupport
 
   const unsigned long AGENT_SHEET = 0;
   const unsigned long USER_SHEET = 1;
   const unsigned long AUTHOR_SHEET = 2;
   /**
    * Synchronously loads a style sheet from |sheetURI| and adds it to the list
    * of additional style sheets of the document.
    *
-   * These additional style sheets are very much like user/agent sheets loaded 
+   * These additional style sheets are very much like user/agent sheets loaded
    * with loadAndRegisterSheet. The only difference is that they are applied only
    * on the document owned by this window.
    *
    * Sheets added via this API take effect immediately on the document.
    */
   void loadSheet(in nsIURI sheetURI, in unsigned long type);
 
   /**
@@ -1747,17 +1747,17 @@ interface nsIDOMWindowUtils : nsISupport
    *
    * Style sheets can be preloaded with nsIStyleSheetService.preloadSheet.
    *
    * Sheets added via this API take effect immediately on the document.
    */
   void addSheet(in nsIPreloadedStyleSheet sheet, in unsigned long type);
 
   /**
-   * Remove the document style sheet at |sheetURI| from the list of additional 
+   * Remove the document style sheet at |sheetURI| from the list of additional
    * style sheets of the document.  The removal takes effect immediately.
    */
   void removeSheet(in nsIURI sheetURI, in unsigned long type);
 
   /**
    * Same as the above method but allows passing the URI as a string.
    */
   void removeSheetUsingURIString(in ACString sheetURI, in unsigned long type);
@@ -1929,16 +1929,21 @@ interface nsIDOMWindowUtils : nsISupport
   void enterChaosMode();
 
   /**
    * Decrease the chaos mode activation level. See enterChaosMode().
    */
   void leaveChaosMode();
 
   /**
+   * Alerts Gecko of a device reset
+   */
+  void triggerDeviceReset();
+
+  /**
    * Returns whether the document's style set's rule processor for the
    * specified level of the cascade is shared by multiple style sets.
    * (Used by tests to ensure that certain optimizations do not regress.)
    *
    * @param aSheetType One of the nsIStyleSheetService.*_SHEET constants.
    */
   bool hasRuleProcessorUsedByMultipleStyleSets(in unsigned long aSheetType);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5373,8 +5373,19 @@ ContentParent::CanCommunicateWith(Conten
 
 mozilla::ipc::IPCResult
 ContentParent::RecvMaybeReloadPlugins()
 {
   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
   pluginHost->ReloadPlugins();
   return IPC_OK();
 }
+
+mozilla::ipc::IPCResult
+ContentParent::RecvDeviceReset()
+{
+  GPUProcessManager* pm = GPUProcessManager::Get();
+  if (pm) {
+    pm->TriggerDeviceResetForTesting();
+  }
+
+  return IPC_OK();
+}
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1056,16 +1056,18 @@ private:
                                                   const uint32_t& aColNumber,
                                                   const uint32_t& aFlags,
                                                   const nsCString& aCategory) override;
 
   virtual mozilla::ipc::IPCResult RecvPrivateDocShellsExist(const bool& aExist) override;
 
   virtual mozilla::ipc::IPCResult RecvFirstIdle() override;
 
+  virtual mozilla::ipc::IPCResult RecvDeviceReset() override;
+
   virtual mozilla::ipc::IPCResult RecvKeywordToURI(const nsCString& aKeyword,
                                                    nsString* aProviderName,
                                                    OptionalIPCStream* aPostData,
                                                    OptionalURIParams* aURI) override;
 
   virtual mozilla::ipc::IPCResult RecvNotifyKeywordSearchLoading(const nsString &aProvider,
                                                                  const nsString &aKeyword) override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -834,16 +834,18 @@ parent:
         returns (bool showPassword);
 
     // Notify the parent of the presence or absence of private docshells
     async PrivateDocShellsExist(bool aExist);
 
     // Tell the parent that the child has gone idle for the first time.
     async FirstIdle();
 
+    async DeviceReset();
+
     sync KeywordToURI(nsCString keyword)
         returns (nsString providerName, OptionalIPCStream postData, OptionalURIParams uri);
 
     sync NotifyKeywordSearchLoading(nsString providerName, nsString keyword);
 
     async CopyFavicon(URIParams oldURI, URIParams newURI, Principal aLoadingPrincipal, bool isPrivate);
 
     // Tell the compositor to allocate a layer tree id for nested remote mozbrowsers.
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -197,17 +197,17 @@ GPUChild::RecvRecordChildEvents(nsTArray
   TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
 {
   gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
-  mHost->mListener->OnProcessDeviceReset(mHost);
+  mHost->mListener->OnRemoteProcessDeviceReset(mHost);
   return IPC_OK();
 }
 
 bool
 GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
                                   const bool& aAnonymize,
                                   const bool& aMinimizeMemoryUsage,
                                   const MaybeFileDesc& aDMDFile)
--- a/gfx/ipc/GPUProcessHost.h
+++ b/gfx/ipc/GPUProcessHost.h
@@ -38,17 +38,17 @@ public:
     {}
 
     // The GPUProcessHost has unexpectedly shutdown or had its connection
     // severed. This is not called if an error occurs after calling
     // Shutdown().
     virtual void OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
     {}
 
-    virtual void OnProcessDeviceReset(GPUProcessHost* aHost)
+    virtual void OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
     {}
   };
 
 public:
   explicit GPUProcessHost(Listener* listener);
   ~GPUProcessHost();
 
   // Launch the subprocess asynchronously. On failure, false is returned.
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -349,17 +349,17 @@ GPUProcessManager::OnProcessLaunchComple
     NS_LITERAL_CSTRING("Running"));
 #endif
 }
 
 static bool
 ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
 {
   // We decide to limit by comparing the amount of resets that have happened
-  // and time since the last reset to two prefs. 
+  // and time since the last reset to two prefs.
   int32_t timeLimit = gfxPrefs::DeviceResetThresholdMilliseconds();
   int32_t countLimit = gfxPrefs::DeviceResetLimitCount();
 
   bool hasTimeLimit = timeLimit >= 0;
   bool hasCountLimit = countLimit >= 0;
 
   bool triggeredTime = deltaMilliseconds < timeLimit;
   bool triggeredCount = count > (uint32_t)countLimit;
@@ -373,17 +373,34 @@ ShouldLimitDeviceResets(uint32_t count, 
   } else if (hasCountLimit) {
     return triggeredCount;
   }
 
   return false;
 }
 
 void
-GPUProcessManager::OnProcessDeviceReset(GPUProcessHost* aHost)
+GPUProcessManager::TriggerDeviceResetForTesting()
+{
+  if (mProcess) {
+    OnRemoteProcessDeviceReset(mProcess);
+  } else {
+    OnInProcessDeviceReset();
+  }
+}
+
+void
+GPUProcessManager::OnInProcessDeviceReset()
+{
+  RebuildInProcessSessions();
+  NotifyListenersOnCompositeDeviceReset();
+}
+
+void
+GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
 {
   // Detect whether the device is resetting too quickly or too much
   // indicating that we should give up and use software
   mDeviceResetCount++;
 
   auto newTime = TimeStamp::Now();
   auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
   mDeviceResetLastTime = newTime;
@@ -392,17 +409,22 @@ GPUProcessManager::OnProcessDeviceReset(
     DestroyProcess();
     DisableGPUProcess("GPU processed experienced too many device resets");
 
     HandleProcessLost();
     return;
   }
 
   RebuildRemoteSessions();
+  NotifyListenersOnCompositeDeviceReset();
+}
 
+void
+GPUProcessManager::NotifyListenersOnCompositeDeviceReset()
+{
   for (const auto& listener : mListeners) {
     listener->OnCompositorDeviceReset();
   }
 }
 
 void
 GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
 {
@@ -490,17 +512,17 @@ GPUProcessManager::HandleProcessLost()
   //      in the same window, additional tabs will simply return the already-
   //      established compositor.
   //
   //      Finally, this step serves one other crucial function: tabs must be
   //      associated with a window compositor or else they can't forward
   //      layer transactions. So this step both ensures that a compositor
   //      exists, and that the tab can forward layers.
   //
-  //  (8) Last, if the window had no remote tabs, step (7) will not have 
+  //  (8) Last, if the window had no remote tabs, step (7) will not have
   //      applied, and the window will not have a new compositor just yet.
   //      The next refresh tick and paint will ensure that one exists, again
   //      via nsIWidget::GetLayerManager.
   RebuildRemoteSessions();
 
   // Notify content. This will ensure that each content process re-establishes
   // a connection to the compositor thread (whether it's in-process or in a
   // newly launched GPU process).
@@ -522,16 +544,33 @@ GPUProcessManager::RebuildRemoteSessions
   // Notify each widget that we have lost the GPU process. This will ensure
   // that each widget destroys its layer manager and CompositorBridgeChild.
   for (const auto& session : sessions) {
     session->NotifySessionLost();
   }
 }
 
 void
+GPUProcessManager::RebuildInProcessSessions()
+{
+  // Build a list of sessions to notify, since notification might delete
+  // entries from the list.
+  nsTArray<RefPtr<InProcessCompositorSession>> sessions;
+  for (auto& session : mInProcessSessions) {
+    sessions.AppendElement(session);
+  }
+
+  // Notify each widget that we have lost the GPU process. This will ensure
+  // that each widget destroys its layer manager and CompositorBridgeChild.
+  for (const auto& session : sessions) {
+    session->NotifySessionLost();
+  }
+}
+
+void
 GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
 {
   if (!NS_IsMainThread()) {
     RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
       &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
     NS_DispatchToMainThread(task.forget());
     return;
   }
@@ -959,28 +998,40 @@ GPUProcessManager::EnsureVsyncIOThread()
 
 void
 GPUProcessManager::ShutdownVsyncIOThread()
 {
   mVsyncIOThread = nullptr;
 }
 
 void
-GPUProcessManager::RegisterSession(RemoteCompositorSession* aSession)
+GPUProcessManager::RegisterRemoteProcessSession(RemoteCompositorSession* aSession)
 {
   mRemoteSessions.AppendElement(aSession);
 }
 
 void
-GPUProcessManager::UnregisterSession(RemoteCompositorSession* aSession)
+GPUProcessManager::UnregisterRemoteProcessSession(RemoteCompositorSession* aSession)
 {
   mRemoteSessions.RemoveElement(aSession);
 }
 
 void
+GPUProcessManager::RegisterInProcessSession(InProcessCompositorSession* aSession)
+{
+  mInProcessSessions.AppendElement(aSession);
+}
+
+void
+GPUProcessManager::UnregisterInProcessSession(InProcessCompositorSession* aSession)
+{
+  mInProcessSessions.RemoveElement(aSession);
+}
+
+void
 GPUProcessManager::AddListener(GPUProcessListener* aListener)
 {
   mListeners.AppendElement(aListener);
 }
 
 void
 GPUProcessManager::RemoveListener(GPUProcessListener* aListener)
 {
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -27,16 +27,17 @@ namespace layers {
 class IAPZCTreeManager;
 class CompositorOptions;
 class CompositorSession;
 class CompositorUpdateObserver;
 class PCompositorBridgeChild;
 class PCompositorManagerChild;
 class PImageBridgeChild;
 class RemoteCompositorSession;
+class InProcessCompositorSession;
 class UiCompositorControllerChild;
 } // namespace layers
 namespace widget {
 class CompositorWidget;
 } // namespace widget
 namespace dom {
 class ContentParent;
 class TabParent;
@@ -54,26 +55,28 @@ class VsyncBridgeChild;
 class VsyncIOThreadHolder;
 
 // The GPUProcessManager is a singleton responsible for creating GPU-bound
 // objects that may live in another process. Currently, it provides access
 // to the compositor via CompositorBridgeParent.
 class GPUProcessManager final : public GPUProcessHost::Listener
 {
   friend class layers::RemoteCompositorSession;
+  friend class layers::InProcessCompositorSession;
 
   typedef layers::CompositorOptions CompositorOptions;
   typedef layers::CompositorSession CompositorSession;
   typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
   typedef layers::IAPZCTreeManager IAPZCTreeManager;
   typedef layers::LayerManager LayerManager;
   typedef layers::PCompositorBridgeChild PCompositorBridgeChild;
   typedef layers::PCompositorManagerChild PCompositorManagerChild;
   typedef layers::PImageBridgeChild PImageBridgeChild;
   typedef layers::RemoteCompositorSession RemoteCompositorSession;
+  typedef layers::InProcessCompositorSession InProcessCompositorSession;
   typedef layers::UiCompositorControllerChild UiCompositorControllerChild;
 
 public:
   static void Initialize();
   static void Shutdown();
   static GPUProcessManager* Get();
 
   ~GPUProcessManager();
@@ -136,17 +139,20 @@ public:
   bool AllocateAndConnectLayerTreeId(
     PCompositorBridgeChild* aCompositorBridge,
     base::ProcessId aOtherPid,
     uint64_t* aOutLayersId,
     CompositorOptions* aOutCompositorOptions);
 
   void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
   void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
-  void OnProcessDeviceReset(GPUProcessHost* aHost) override;
+  void TriggerDeviceResetForTesting();
+  void OnInProcessDeviceReset();
+  void OnRemoteProcessDeviceReset(GPUProcessHost* aHost) override;
+  void NotifyListenersOnCompositeDeviceReset();
 
   // Notify the GPUProcessManager that a top-level PGPU protocol has been
   // terminated. This may be called from any thread.
   void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
 
   void AddListener(GPUProcessListener* aListener);
   void RemoveListener(GPUProcessListener* aListener);
 
@@ -184,20 +190,26 @@ private:
                                 ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
   bool CreateContentVRManager(base::ProcessId aOtherProcess,
                               ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
   void CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
                                         ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndPoint);
 
   // Called from RemoteCompositorSession. We track remote sessions so we can
   // notify their owning widgets that the session must be restarted.
-  void RegisterSession(RemoteCompositorSession* aSession);
-  void UnregisterSession(RemoteCompositorSession* aSession);
+  void RegisterRemoteProcessSession(RemoteCompositorSession* aSession);
+  void UnregisterRemoteProcessSession(RemoteCompositorSession* aSession);
+
+  // Called from InProcessCompositorSession. We track in process sessino so we can
+  // notify their owning widgets that the session must be restarted
+  void RegisterInProcessSession(InProcessCompositorSession* aSession);
+  void UnregisterInProcessSession(InProcessCompositorSession* aSession);
 
   void RebuildRemoteSessions();
+  void RebuildInProcessSessions();
 
 private:
   GPUProcessManager();
 
   // Permanently disable the GPU process and record a message why.
   void DisableGPUProcess(const char* aMessage);
 
   // Shutdown the GPU process.
@@ -248,16 +260,17 @@ private:
   ipc::TaskFactory<GPUProcessManager> mTaskFactory;
   RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
   uint32_t mNextNamespace;
   uint32_t mIdNamespace;
   uint32_t mResourceId;
   uint32_t mNumProcessAttempts;
 
   nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions;
+  nsTArray<RefPtr<InProcessCompositorSession>> mInProcessSessions;
   nsTArray<GPUProcessListener*> mListeners;
 
   uint32_t mDeviceResetCount;
   TimeStamp mDeviceResetLastTime;
 
   // Fields that are associated with the current GPU process.
   GPUProcessHost* mProcess;
   MOZ_INIT_OUTSIDE_CTOR uint64_t mProcessToken;
--- a/gfx/ipc/InProcessCompositorSession.cpp
+++ b/gfx/ipc/InProcessCompositorSession.cpp
@@ -4,31 +4,35 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "InProcessCompositorSession.h"
 
 // so we can cast an APZCTreeManager to an IAPZCTreeManager
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
+#include "nsBaseWidget.h"
 
 namespace mozilla {
 namespace layers {
 
 InProcessCompositorSession::InProcessCompositorSession(widget::CompositorWidget* aWidget,
+                                                       nsBaseWidget* baseWidget,
                                                        CompositorBridgeChild* aChild,
                                                        CompositorBridgeParent* aParent)
  : CompositorSession(aWidget->AsDelegate(), aChild, aParent->RootLayerTreeId()),
+   mWidget(baseWidget),
    mCompositorBridgeParent(aParent),
    mCompositorWidget(aWidget)
 {
+  GPUProcessManager::Get()->RegisterInProcessSession(this);
 }
 
 /* static */ RefPtr<InProcessCompositorSession>
-InProcessCompositorSession::Create(nsIWidget* aWidget,
+InProcessCompositorSession::Create(nsBaseWidget* aWidget,
                                    LayerManager* aLayerManager,
                                    const uint64_t& aRootLayerTreeId,
                                    CSSToLayoutDeviceScale aScale,
                                    const CompositorOptions& aOptions,
                                    bool aUseExternalSurfaceSize,
                                    const gfx::IntSize& aSurfaceSize,
                                    uint32_t aNamespace)
 {
@@ -43,17 +47,23 @@ InProcessCompositorSession::Create(nsIWi
   MOZ_ASSERT(parent);
   parent->InitSameProcess(widget, aRootLayerTreeId);
 
   RefPtr<CompositorBridgeChild> child =
     CompositorManagerChild::CreateSameProcessWidgetCompositorBridge(aLayerManager,
                                                                     aNamespace);
   MOZ_ASSERT(child);
 
-  return new InProcessCompositorSession(widget, child, parent);
+  return new InProcessCompositorSession(widget, aWidget, child, parent);
+}
+
+void
+InProcessCompositorSession::NotifySessionLost()
+{
+  mWidget->NotifyCompositorSessionLost(this);
 }
 
 CompositorBridgeParent*
 InProcessCompositorSession::GetInProcessBridge() const
 {
   return mCompositorBridgeParent;
 }
 
@@ -64,16 +74,22 @@ InProcessCompositorSession::SetContentCo
 }
 
 RefPtr<IAPZCTreeManager>
 InProcessCompositorSession::GetAPZCTreeManager() const
 {
   return mCompositorBridgeParent->GetAPZCTreeManager(mRootLayerTreeId);
 }
 
+nsIWidget*
+InProcessCompositorSession::GetWidget() const
+{
+  return mWidget;
+}
+
 void
 InProcessCompositorSession::Shutdown()
 {
   // Destroy will synchronously wait for the parent to acknowledge shutdown,
   // at which point CBP will defer a Release on the compositor thread. We
   // can safely release our reference now, and let the destructor run on either
   // thread.
   mCompositorBridgeChild->Destroy();
@@ -81,12 +97,13 @@ InProcessCompositorSession::Shutdown()
   mCompositorBridgeParent = nullptr;
   mCompositorWidget = nullptr;
 #if defined(MOZ_WIDGET_ANDROID)
   if (mUiCompositorControllerChild) {
     mUiCompositorControllerChild->Destroy();
     mUiCompositorControllerChild = nullptr;
   }
 #endif //defined(MOZ_WIDGET_ANDROID)
+  GPUProcessManager::Get()->UnregisterInProcessSession(this);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/ipc/InProcessCompositorSession.h
+++ b/gfx/ipc/InProcessCompositorSession.h
@@ -16,36 +16,41 @@ namespace layers {
 class CompositorOptions;
 
 // A CompositorSession where both the child and parent CompositorBridge reside
 // in the same process.
 class InProcessCompositorSession final : public CompositorSession
 {
 public:
   static RefPtr<InProcessCompositorSession> Create(
-    nsIWidget* aWidget,
+    nsBaseWidget* baseWidget,
     LayerManager* aLayerManager,
     const uint64_t& aRootLayerTreeId,
     CSSToLayoutDeviceScale aScale,
     const CompositorOptions& aOptions,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize,
     uint32_t aNamespace);
 
   CompositorBridgeParent* GetInProcessBridge() const override;
   void SetContentController(GeckoContentController* aController) override;
+  nsIWidget* GetWidget() const;
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
   void Shutdown() override;
 
+  void NotifySessionLost();
+
 private:
   InProcessCompositorSession(widget::CompositorWidget* aWidget,
+                             nsBaseWidget* baseWidget,
                              CompositorBridgeChild* aChild,
                              CompositorBridgeParent* aParent);
 
 private:
+  nsBaseWidget* mWidget;
   RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
   RefPtr<CompositorWidget> mCompositorWidget;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // _include_mozilla_gfx_ipc_InProcessCompositorSession_h_
--- a/gfx/ipc/RemoteCompositorSession.cpp
+++ b/gfx/ipc/RemoteCompositorSession.cpp
@@ -24,17 +24,17 @@ RemoteCompositorSession::RemoteComposito
                                                  CompositorBridgeChild* aChild,
                                                  CompositorWidgetDelegate* aWidgetDelegate,
                                                  APZCTreeManagerChild* aAPZ,
                                                  const uint64_t& aRootLayerTreeId)
  : CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId),
    mWidget(aWidget),
    mAPZ(aAPZ)
 {
-  GPUProcessManager::Get()->RegisterSession(this);
+  GPUProcessManager::Get()->RegisterRemoteProcessSession(this);
   if (mAPZ) {
     mAPZ->SetCompositorSession(this);
   }
 }
 
 RemoteCompositorSession::~RemoteCompositorSession()
 {
   // This should have been shutdown first.
@@ -45,18 +45,17 @@ RemoteCompositorSession::~RemoteComposit
 }
 
 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);
+  mWidget->NotifyCompositorSessionLost(this);
 }
 
 CompositorBridgeParent*
 RemoteCompositorSession::GetInProcessBridge() const
 {
   return nullptr;
 }
 
@@ -69,17 +68,17 @@ RemoteCompositorSession::SetContentContr
 
 GeckoContentController*
 RemoteCompositorSession::GetContentController()
 {
   return mContentController.get();
 }
 
 nsIWidget*
-RemoteCompositorSession::GetWidget()
+RemoteCompositorSession::GetWidget() const
 {
   return mWidget;
 }
 
 RefPtr<IAPZCTreeManager>
 RemoteCompositorSession::GetAPZCTreeManager() const
 {
   return mAPZ;
@@ -97,13 +96,13 @@ RemoteCompositorSession::Shutdown()
   mCompositorWidgetDelegate = nullptr;
   mWidget = nullptr;
 #if defined(MOZ_WIDGET_ANDROID)
   if (mUiCompositorControllerChild) {
     mUiCompositorControllerChild->Destroy();
     mUiCompositorControllerChild = nullptr;
   }
 #endif //defined(MOZ_WIDGET_ANDROID)
-  GPUProcessManager::Get()->UnregisterSession(this);
+  GPUProcessManager::Get()->UnregisterRemoteProcessSession(this);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/ipc/RemoteCompositorSession.h
+++ b/gfx/ipc/RemoteCompositorSession.h
@@ -21,17 +21,17 @@ public:
                           CompositorWidgetDelegate* aWidgetDelegate,
                           APZCTreeManagerChild* aAPZ,
                           const uint64_t& aRootLayerTreeId);
   ~RemoteCompositorSession() override;
 
   CompositorBridgeParent* GetInProcessBridge() const override;
   void SetContentController(GeckoContentController* aController) override;
   GeckoContentController* GetContentController();
-  nsIWidget* GetWidget();
+  nsIWidget* GetWidget() const;
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
   void Shutdown() override;
 
   void NotifySessionLost();
 
 private:
   nsBaseWidget* mWidget;
   RefPtr<APZCTreeManagerChild> mAPZ;
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -112,19 +112,19 @@ ClientLayerManager::ClientLayerManager(n
 }
 
 
 ClientLayerManager::~ClientLayerManager()
 {
   mMemoryPressureObserver->Destroy();
   ClearCachedResources();
   // Stop receiveing AsyncParentMessage at Forwarder.
-  // After the call, the message is directly handled by LayerTransactionChild. 
+  // After the call, the message is directly handled by LayerTransactionChild.
   // Basically this function should be called in ShadowLayerForwarder's
-  // destructor. But when the destructor is triggered by 
+  // destructor. But when the destructor is triggered by
   // CompositorBridgeChild::Destroy(), the destructor can not handle it correctly.
   // See Bug 1000525.
   mForwarder->StopReceiveAsyncParentMessge();
   mRoot = nullptr;
 
   MOZ_COUNT_DTOR(ClientLayerManager);
 }
 
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1353,17 +1353,17 @@ void nsBaseWidget::CreateCompositor(int 
   bool getCompositorFromThisWindow = (mWindowType == eWindowType_toplevel);
 #endif
 
   if (getCompositorFromThisWindow) {
     gfxPlatform::GetPlatform()->NotifyCompositorCreated(mLayerManager->GetCompositorBackendType());
   }
 }
 
-void nsBaseWidget::NotifyRemoteCompositorSessionLost(CompositorSession* aSession)
+void nsBaseWidget::NotifyCompositorSessionLost(CompositorSession* aSession)
 {
   MOZ_ASSERT(aSession == mCompositorSession);
   DestroyLayerManager();
 }
 
 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
 {
   return gfxPlatform::UsesOffMainThreadCompositing();
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -197,17 +197,17 @@ public:
                                           LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
 
   // A remote compositor session tied to this window has been lost and IPC
   // messages will no longer work. The widget must clean up any lingering
   // resources and possibly schedule another paint.
   //
   // A reference to the session object is held until this function has
   // returned.
-  void NotifyRemoteCompositorSessionLost(mozilla::layers::CompositorSession* aSession);
+  void NotifyCompositorSessionLost(mozilla::layers::CompositorSession* aSession);
 
   mozilla::CompositorVsyncDispatcher* GetCompositorVsyncDispatcher();
   void            CreateCompositorVsyncDispatcher();
   virtual void            CreateCompositor();
   virtual void            CreateCompositor(int aWidth, int aHeight);
   virtual void            PrepareWindowEffects() override {}
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override {}
   virtual void            SetModal(bool aModal) override {}
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -174,26 +174,17 @@ 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();
 
-    nsTArray<nsWindow*> windows = EnumAllWindows();
-    for (nsWindow* window : windows) {
-      window->OnRenderingDeviceReset();
-    }
-
-    nsTArray<mozilla::dom::ContentParent*> children;
-    mozilla::dom::ContentParent::GetAll(children);
-    for (const auto& child : children) {
-      child->OnCompositorDeviceReset();
-    }
+    GPUProcessManager::Get()->OnInProcessDeviceReset();
 
     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
   // dummy paint so that Windows stops dispatching WM_PAINT in an inifinite
@@ -676,17 +667,17 @@ HBITMAP nsWindowGfx::DataToBitmap(uint8_
   head.biPlanes = 1;
   head.biBitCount = (WORD)aDepth;
   head.biCompression = BI_RGB;
   head.biSizeImage = 0; // Uncompressed
   head.biXPelsPerMeter = 0;
   head.biYPelsPerMeter = 0;
   head.biClrUsed = 0;
   head.biClrImportant = 0;
-  
+
   BITMAPINFO& bi = *(BITMAPINFO*)reserved_space;
 
   if (aDepth == 1) {
     RGBQUAD black = { 0, 0, 0, 0 };
     RGBQUAD white = { 255, 255, 255, 0 };
 
     bi.bmiColors[0] = white;
     bi.bmiColors[1] = black;