Fix vsync sometimes not firing after the GPU process crashes. (bug 1305628, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Fri, 30 Sep 2016 01:23:52 -0700
changeset 316041 7eaccbb8e8d39e301aa050db97b7034ec2bc45a1
parent 316040 0d3ad9d3943ab9360eb4df8f0615a34e7e32ae76
child 316042 5262594e0f3f2e700532e3c1f7d5c2b884150c3e
push id30759
push userphilringnalda@gmail.com
push dateSat, 01 Oct 2016 06:25:09 +0000
treeherdermozilla-central@fcc62bbf09ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1305628
milestone52.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
Fix vsync sometimes not firing after the GPU process crashes. (bug 1305628, r=mattwoodrow)
gfx/ipc/RemoteCompositorSession.cpp
widget/InProcessCompositorWidget.cpp
widget/gtk/InProcessX11CompositorWidget.cpp
widget/nsBaseWidget.cpp
widget/windows/InProcessWinCompositorWidget.cpp
--- a/gfx/ipc/RemoteCompositorSession.cpp
+++ b/gfx/ipc/RemoteCompositorSession.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "RemoteCompositorSession.h"
+#include "mozilla/VsyncDispatcher.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
 #include "nsBaseWidget.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
--- a/widget/InProcessCompositorWidget.cpp
+++ b/widget/InProcessCompositorWidget.cpp
@@ -122,15 +122,16 @@ nsIWidget*
 InProcessCompositorWidget::RealWidget()
 {
   return mWidget;
 }
 
 void
 InProcessCompositorWidget::ObserveVsync(VsyncObserver* aObserver)
 {
-  RefPtr<CompositorVsyncDispatcher> cvd = mWidget->GetCompositorVsyncDispatcher();
-  cvd->SetCompositorVsyncObserver(aObserver);
+  if (RefPtr<CompositorVsyncDispatcher> cvd = mWidget->GetCompositorVsyncDispatcher()) {
+    cvd->SetCompositorVsyncObserver(aObserver);
+  }
 }
 
 } // namespace widget
 } // namespace mozilla
 
--- a/widget/gtk/InProcessX11CompositorWidget.cpp
+++ b/widget/gtk/InProcessX11CompositorWidget.cpp
@@ -20,14 +20,15 @@ InProcessX11CompositorWidget::InProcessX
                                                            nsWindow* aWindow)
   : X11CompositorWidget(aInitData, aWindow)
 {
 }
 
 void
 InProcessX11CompositorWidget::ObserveVsync(VsyncObserver* aObserver)
 {
-  RefPtr<CompositorVsyncDispatcher> cvd = mWidget->GetCompositorVsyncDispatcher();
-  cvd->SetCompositorVsyncObserver(aObserver);
+  if (RefPtr<CompositorVsyncDispatcher> cvd = mWidget->GetCompositorVsyncDispatcher()) {
+    cvd->SetCompositorVsyncObserver(aObserver);
+  }
 }
 
 } // namespace widget
 } // namespace mozilla
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -255,16 +255,25 @@ nsBaseWidget::Shutdown()
     delete sPluginWidgetList;
     sPluginWidgetList = nullptr;
   }
 #endif
 }
 
 void nsBaseWidget::DestroyCompositor()
 {
+  // We release this before releasing the compositor, since it may hold the
+  // last reference to our ClientLayerManager. ClientLayerManager's dtor can
+  // trigger a paint, creating a new compositor, and we don't want to re-use
+  // the old vsync dispatcher.
+  if (mCompositorVsyncDispatcher) {
+    mCompositorVsyncDispatcher->Shutdown();
+    mCompositorVsyncDispatcher = nullptr;
+  }
+
   // The compositor shutdown sequence looks like this:
   //  1. CompositorSession calls CompositorBridgeChild::Destroy.
   //  2. CompositorBridgeChild synchronously sends WillClose.
   //  3. CompositorBridgeParent releases some resources (such as the layer
   //     manager, compositor, and widget).
   //  4. CompositorBridgeChild::Destroy returns.
   //  5. Asynchronously, CompositorBridgeParent::ActorDestroy will fire on the
   //     compositor thread when the I/O thread closes the IPC channel.
@@ -279,23 +288,16 @@ void nsBaseWidget::DestroyCompositor()
     mCompositorWidgetDelegate = nullptr;
     mCompositorBridgeChild = nullptr;
 
     // XXX CompositorBridgeChild and CompositorBridgeParent might be re-created in
     // ClientLayerManager destructor. See bug 1133426.
     RefPtr<CompositorSession> session = mCompositorSession.forget();
     session->Shutdown();
   }
-
-  // Can have base widgets that are things like tooltips
-  // which don't have CompositorVsyncDispatchers
-  if (mCompositorVsyncDispatcher) {
-    mCompositorVsyncDispatcher->Shutdown();
-    mCompositorVsyncDispatcher = nullptr;
-  }
 }
 
 void nsBaseWidget::ReleaseContentController()
 {
   if (mRootContentController) {
     mRootContentController->Destroy();
     mRootContentController = nullptr;
   }
--- a/widget/windows/InProcessWinCompositorWidget.cpp
+++ b/widget/windows/InProcessWinCompositorWidget.cpp
@@ -27,14 +27,15 @@ nsIWidget*
 InProcessWinCompositorWidget::RealWidget()
 {
   return mWindow;
 }
 
 void
 InProcessWinCompositorWidget::ObserveVsync(VsyncObserver* aObserver)
 {
-  RefPtr<CompositorVsyncDispatcher> cvd = mWindow->GetCompositorVsyncDispatcher();
-  cvd->SetCompositorVsyncObserver(aObserver);
+  if (RefPtr<CompositorVsyncDispatcher> cvd = mWindow->GetCompositorVsyncDispatcher()) {
+    cvd->SetCompositorVsyncObserver(aObserver);
+  }
 }
 
 } // namespace widget
 } // namespace mozilla