Bug 1095242. Part 5: Unobserve vsync in RefreshTimerVsyncDispatcher. r=kats
authorMason Chang <mchang@mozilla.com>
Tue, 20 Jan 2015 08:31:26 -0800
changeset 224726 7baad81da308226248009a7f33b6a3f298ba4e12
parent 224725 cfbc31d1d04ffcc427e5f4b1cc0dfccedda0e5a3
child 224727 491f9b6be0eecec3db1ba90d6bb792a3482710dc
push id28143
push userryanvm@gmail.com
push dateWed, 21 Jan 2015 03:14:12 +0000
treeherdermozilla-central@540077a30866 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1095242
milestone38.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 1095242. Part 5: Unobserve vsync in RefreshTimerVsyncDispatcher. r=kats
widget/VsyncDispatcher.cpp
widget/VsyncDispatcher.h
--- a/widget/VsyncDispatcher.cpp
+++ b/widget/VsyncDispatcher.cpp
@@ -118,31 +118,66 @@ RefreshTimerVsyncDispatcher::NotifyVsync
   if (mParentRefreshTimer) {
     mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
   }
 }
 
 void
 RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
 {
-  MutexAutoLock lock(mRefreshTimersLock);
-  mParentRefreshTimer = aVsyncObserver;
+  MOZ_ASSERT(NS_IsMainThread());
+  { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
+    MutexAutoLock lock(mRefreshTimersLock);
+    mParentRefreshTimer = aVsyncObserver;
+  }
+
+  UpdateVsyncStatus();
 }
 
 void
 RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
 {
-  MutexAutoLock lock(mRefreshTimersLock);
-  MOZ_ASSERT(aVsyncObserver);
-  if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
-    mChildRefreshTimers.AppendElement(aVsyncObserver);
+  { // scope lock - called on pbackground thread
+    MutexAutoLock lock(mRefreshTimersLock);
+    MOZ_ASSERT(aVsyncObserver);
+    if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
+      mChildRefreshTimers.AppendElement(aVsyncObserver);
+    }
   }
+
+  UpdateVsyncStatus();
 }
 
 void
 RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
 {
+  { // scope lock - called on pbackground thread
+    MutexAutoLock lock(mRefreshTimersLock);
+    MOZ_ASSERT(aVsyncObserver);
+    mChildRefreshTimers.RemoveElement(aVsyncObserver);
+  }
+
+  UpdateVsyncStatus();
+}
+
+void
+RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
+{
+  if (!NS_IsMainThread()) {
+    nsCOMPtr<nsIRunnable> vsyncControl = NS_NewRunnableMethod(this,
+                                           &RefreshTimerVsyncDispatcher::UpdateVsyncStatus);
+    NS_DispatchToMainThread(vsyncControl);
+    return;
+  }
+
+  gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
+  display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
+}
+
+bool
+RefreshTimerVsyncDispatcher::NeedsVsync()
+{
+  MOZ_ASSERT(NS_IsMainThread());
   MutexAutoLock lock(mRefreshTimersLock);
-  MOZ_ASSERT(aVsyncObserver);
-  mChildRefreshTimers.RemoveElement(aVsyncObserver);
+  return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
 }
 
 } // namespace mozilla
--- a/widget/VsyncDispatcher.h
+++ b/widget/VsyncDispatcher.h
@@ -74,16 +74,18 @@ public:
   // will be a no-op for AddChildRefreshTimer() if the observer is already
   // registered.
   // These functions can be called from any thread.
   void AddChildRefreshTimer(VsyncObserver* aVsyncObserver);
   void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver);
 
 private:
   virtual ~RefreshTimerVsyncDispatcher();
+  void UpdateVsyncStatus();
+  bool NeedsVsync();
 
   Mutex mRefreshTimersLock;
   nsRefPtr<VsyncObserver> mParentRefreshTimer;
   nsTArray<nsRefPtr<VsyncObserver>> mChildRefreshTimers;
 };
 
 } // namespace mozilla