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 247931 f88dedd047aed1171270aa3d3eef8e6225d6a36b
parent 247930 5faeb9df6fc2031f9629826563e60875958ba099
child 247932 26dd6674c459719ba2cd74f28e541a1c4806127f
push id698
push userjlund@mozilla.com
push dateMon, 23 Mar 2015 22:08:11 +0000
treeherdermozilla-release@b0c0ae7b02a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1101974
milestone37.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 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