Bug 1101974. Part 5 - Refactor VsyncDispatcher to use VsyncSource. r=kats
authorMason Chang <mchang@mozilla.com>
Thu, 18 Dec 2014 08:30:06 -0800
changeset 233660 f88dedd047aed1171270aa3d3eef8e6225d6a36b
parent 233659 5faeb9df6fc2031f9629826563e60875958ba099
child 233661 26dd6674c459719ba2cd74f28e541a1c4806127f
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-esr52@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1101974
milestone37.0a1
Bug 1101974. Part 5 - Refactor VsyncDispatcher to use VsyncSource. r=kats
widget/VsyncDispatcher.cpp
widget/VsyncDispatcher.h
--- a/widget/VsyncDispatcher.cpp
+++ b/widget/VsyncDispatcher.cpp
@@ -2,116 +2,72 @@
 /* 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 "VsyncDispatcher.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "gfxPrefs.h"
+#include "gfxPlatform.h"
+#include "VsyncSource.h"
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "GeckoProfiler.h"
 #include "ProfilerMarkers.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "GeckoTouchDispatcher.h"
 #endif
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 
-StaticRefPtr<VsyncDispatcher> sVsyncDispatcher;
-
-/*static*/ VsyncDispatcher*
-VsyncDispatcher::GetInstance()
-{
-  if (!sVsyncDispatcher) {
-    sVsyncDispatcher = new VsyncDispatcher();
-    ClearOnShutdown(&sVsyncDispatcher);
-  }
-
-  return sVsyncDispatcher;
-}
-
 VsyncDispatcher::VsyncDispatcher()
   : mCompositorObserverLock("CompositorObserverLock")
 {
-
+  MOZ_ASSERT(XRE_IsParentProcess());
+  gfxPlatform::GetPlatform()->GetHardwareVsync()->AddVsyncDispatcher(this);
 }
 
 VsyncDispatcher::~VsyncDispatcher()
 {
-  MutexAutoLock lock(mCompositorObserverLock);
-  mCompositorObservers.Clear();
-}
-
-void
-VsyncDispatcher::SetVsyncSource(VsyncSource* aVsyncSource)
-{
-  mVsyncSource = aVsyncSource;
-}
-
-void
-VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime)
-{
-  // Touch events can sometimes start a composite, so make sure we dispatch touches
-  // even if we don't composite
-#ifdef MOZ_WIDGET_GONK
-  if (!aNotifiedCompositors && gfxPrefs::TouchResampling()) {
-    GeckoTouchDispatcher::NotifyVsync(aVsyncTime);
-  }
-#endif
+  // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
+  MOZ_ASSERT(NS_IsMainThread());
 }
 
 void
 VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
 {
-  bool notifiedCompositors = false;
+  // In hardware vsync thread
 #ifdef MOZ_ENABLE_PROFILER_SPS
     if (profiler_is_active()) {
         CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
     }
 #endif
 
-  if (gfxPrefs::VsyncAlignedCompositor()) {
-    MutexAutoLock lock(mCompositorObserverLock);
-    notifiedCompositors = NotifyVsyncObservers(aVsyncTimestamp, mCompositorObservers);
-  }
-
-  DispatchTouchEvents(notifiedCompositors, aVsyncTimestamp);
-}
-
-bool
-VsyncDispatcher::NotifyVsyncObservers(TimeStamp aVsyncTimestamp, nsTArray<nsRefPtr<VsyncObserver>>& aObservers)
-{
-  // Callers should lock the respective lock for the aObservers before calling this function
-  for (size_t i = 0; i < aObservers.Length(); i++) {
-    aObservers[i]->NotifyVsync(aVsyncTimestamp);
- }
- return !aObservers.IsEmpty();
-}
-
-void
-VsyncDispatcher::AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
-{
-  MOZ_ASSERT(CompositorParent::IsInCompositorThread());
   MutexAutoLock lock(mCompositorObserverLock);
-  if (!mCompositorObservers.Contains(aVsyncObserver)) {
-    mCompositorObservers.AppendElement(aVsyncObserver);
+  if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver) {
+    mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
   }
 }
 
 void
-VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
+VsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
 {
-  MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
+  MOZ_ASSERT(CompositorParent::IsInCompositorThread());
   MutexAutoLock lock(mCompositorObserverLock);
-  if (mCompositorObservers.Contains(aVsyncObserver)) {
-    mCompositorObservers.RemoveElement(aVsyncObserver);
-  } else {
-    NS_WARNING("Could not delete a compositor vsync observer\n");
-  }
+  mCompositorVsyncObserver = aVsyncObserver;
 }
 
+void
+VsyncDispatcher::Shutdown()
+{
+  // Need to explicitly remove VsyncDispatcher when the nsBaseWidget shuts down.
+  // Otherwise, we would get dead vsync notifications between when the nsBaseWidget
+  // shuts down and the CompositorParent shuts down.
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+  gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveVsyncDispatcher(this);
+}
 } // namespace mozilla
--- a/widget/VsyncDispatcher.h
+++ b/widget/VsyncDispatcher.h
@@ -7,42 +7,27 @@
 #define mozilla_widget_VsyncDispatcher_h
 
 #include "base/message_loop.h"
 #include "mozilla/Mutex.h"
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
-class MessageLoop;
-
 namespace mozilla {
 class TimeStamp;
 
 namespace layers {
 class CompositorVsyncObserver;
 }
 
-// Controls how and when to enable/disable vsync.
-class VsyncSource
-{
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource)
-  virtual void EnableVsync() = 0;
-  virtual void DisableVsync() = 0;
-  virtual bool IsVsyncEnabled() = 0;
-
-protected:
-  virtual ~VsyncSource() {}
-}; // VsyncSource
-
 class VsyncObserver
 {
   // Must be destroyed on main thread since the compositor is as well
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VsyncObserver)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver)
 
 public:
   // The method called when a vsync occurs. Return true if some work was done.
   // Vsync notifications will occur on the hardware vsync thread
   virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
 
 protected:
   VsyncObserver() {}
@@ -50,39 +35,31 @@ protected:
 }; // VsyncObserver
 
 // VsyncDispatcher is used to dispatch vsync events to the registered observers.
 class VsyncDispatcher
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncDispatcher)
 
 public:
-  static VsyncDispatcher* GetInstance();
+  VsyncDispatcher();
+
   // Called on the vsync thread when a hardware vsync occurs
   // The aVsyncTimestamp can mean different things depending on the platform:
   // b2g - The vsync timestamp of the previous frame that was just displayed
   // OSX - The vsync timestamp of the upcoming frame
   // TODO: Windows / Linux. DOCUMENT THIS WHEN IMPLEMENTING ON THOSE PLATFORMS
   // Android: TODO
   void NotifyVsync(TimeStamp aVsyncTimestamp);
-  void SetVsyncSource(VsyncSource* aVsyncSource);
 
   // Compositor vsync observers must be added/removed on the compositor thread
-  void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
-  void RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
+  void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
+  void Shutdown();
 
 private:
-  VsyncDispatcher();
   virtual ~VsyncDispatcher();
-  void DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime);
-
-  // Called on the vsync thread. Returns true if observers were notified
-  bool NotifyVsyncObservers(TimeStamp aVsyncTimestamp, nsTArray<nsRefPtr<VsyncObserver>>& aObservers);
-
-  // Can have multiple compositors. On desktop, this is 1 compositor per window
   Mutex mCompositorObserverLock;
-  nsTArray<nsRefPtr<VsyncObserver>> mCompositorObservers;
-  nsRefPtr<VsyncSource> mVsyncSource;
+  nsRefPtr<VsyncObserver> mCompositorVsyncObserver;
 }; // VsyncDispatcher
 
 } // namespace mozilla
 
 #endif // __mozilla_widget_VsyncDispatcher_h