Bug 1095242. Part 5: Unobserve vsync in RefreshTimerVsyncDispatcher. r=kats
authorMason Chang <mchang@mozilla.com>
Tue, 20 Jan 2015 08:31:26 -0800
changeset 239161 7baad81da308226248009a7f33b6a3f298ba4e12
parent 239160 cfbc31d1d04ffcc427e5f4b1cc0dfccedda0e5a3
child 239162 491f9b6be0eecec3db1ba90d6bb792a3482710dc
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-esr52@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1095242
milestone38.0a1
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