Bug 1101974. Part 1. Move VsyncDispatcher to CompositorParent. r=roc
☠☠ backed out by 5b2f62c1faf9 ☠ ☠
authorMason Chang <mchang@mozilla.com>
Fri, 21 Nov 2014 09:16:19 -0800
changeset 216941 82e94c16732d3c4d8e7a0abe7444e7a36a993993
parent 216940 c080f66ed9d2ed0515677c99828310434ec18ecd
child 216942 08df10804c35859cb99a5637a45de0af467c7ca2
push id27868
push userkwierso@gmail.com
push dateSat, 22 Nov 2014 00:36:06 +0000
treeherdermozilla-central@7ab92d922d19 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1101974
milestone36.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 1. Move VsyncDispatcher to CompositorParent. r=roc
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
widget/VsyncDispatcher.cpp
widget/VsyncDispatcher.h
widget/gonk/HwcComposer2D.cpp
widget/moz.build
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -58,17 +58,16 @@
 #include "mozilla/ipc/ProtocolTypes.h"
 #include "mozilla/unused.h"
 #include "mozilla/Hal.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/StaticPtr.h"
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "ProfilerMarkers.h"
 #endif
-#include "mozilla/VsyncDispatcher.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "GeckoTouchDispatcher.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
@@ -190,131 +189,139 @@ static Thread* CompositorThread() {
   return sCompositorThreadHolder ? sCompositorThreadHolder->GetCompositorThread() : nullptr;
 }
 
 static void SetThreadPriority()
 {
   hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
 }
 
-CompositorVsyncObserver::CompositorVsyncObserver(CompositorParent* aCompositorParent)
+StaticRefPtr<VsyncDispatcher> sVsyncDispatcher;
+VsyncDispatcher::VsyncDispatcher(CompositorParent* aCompositorParent, VsyncSource* aVsyncSource)
   : mNeedsComposite(false)
   , mIsObservingVsync(false)
   , mCompositorParent(aCompositorParent)
+  , mVsyncSource(aVsyncSource)
   , mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
   , mCurrentCompositeTask(nullptr)
 {
-
+  sVsyncDispatcher = this;
 }
 
-CompositorVsyncObserver::~CompositorVsyncObserver()
+VsyncDispatcher::~VsyncDispatcher()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  UnobserveVsync();
+  sVsyncDispatcher = nullptr;
+  DisableVsync();
   mCompositorParent = nullptr;
   mNeedsComposite = false;
   CancelCurrentCompositeTask();
 }
 
 /**
  * TODO Potential performance heuristics:
  * If a composite takes 17 ms, do we composite ASAP or wait until next vsync?
  * If a layer transaction comes after vsync, do we composite ASAP or wait until
  * next vsync?
  * How many skipped vsync events until we stop listening to vsync events?
  */
 void
-CompositorVsyncObserver::SetNeedsComposite(bool aNeedsComposite)
+VsyncDispatcher::SetNeedsComposite(bool aNeedsComposite)
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread());
   mNeedsComposite = aNeedsComposite;
 
   if (!mIsObservingVsync && mNeedsComposite) {
-    ObserveVsync();
+    EnableVsync();
   }
 }
 
-bool
-CompositorVsyncObserver::NotifyVsync(TimeStamp aVsyncTimestamp)
+/* static*/ void
+VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
+{
+  // Called from the vsync dispatch thread
+  MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  if (sVsyncDispatcher) {
+    sVsyncDispatcher->RunVsync(aVsyncTimestamp);
+  }
+}
+
+void
+VsyncDispatcher::RunVsync(TimeStamp aVsyncTimestamp)
 {
   // Called from the vsync dispatch thread
   MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
   MOZ_ASSERT(!NS_IsMainThread());
 
   MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
   if (mCurrentCompositeTask == nullptr) {
     mCurrentCompositeTask = NewRunnableMethod(this,
-                                              &CompositorVsyncObserver::Composite,
+                                              &VsyncDispatcher::Composite,
                                               aVsyncTimestamp);
     CompositorParent::CompositorLoop()->PostTask(FROM_HERE, mCurrentCompositeTask);
   }
-  return true;
 }
 
 void
-CompositorVsyncObserver::CancelCurrentCompositeTask()
+VsyncDispatcher::CancelCurrentCompositeTask()
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
   MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
   if (mCurrentCompositeTask) {
     mCurrentCompositeTask->Cancel();
     mCurrentCompositeTask = nullptr;
   }
 }
 
 void
-CompositorVsyncObserver::Composite(TimeStamp aVsyncTimestamp)
+VsyncDispatcher::Composite(TimeStamp aVsyncTimestamp)
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread());
   {
     MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
     mCurrentCompositeTask = nullptr;
   }
 
   if (mNeedsComposite && mCompositorParent) {
     mNeedsComposite = false;
     mCompositorParent->CompositeCallback(aVsyncTimestamp);
   } else {
-    // We're getting vsync notifications but we don't need to composite so
-    // unregister the vsync.
-    UnobserveVsync();
+    DisableVsync();
   }
 
   DispatchTouchEvents(aVsyncTimestamp);
 }
 
 bool
-CompositorVsyncObserver::NeedsComposite()
+VsyncDispatcher::NeedsComposite()
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread());
   return mNeedsComposite;
 }
 
-/**
- * Since the vsync thread has its own locks before notifying us of vsync
- * we can't register/unregister from the vsync thread. Any other thread is fine
- */
 void
-CompositorVsyncObserver::ObserveVsync()
+VsyncDispatcher::EnableVsync()
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread());
-  VsyncDispatcher::GetInstance()->AddCompositorVsyncObserver(this);
   mIsObservingVsync = true;
+  mVsyncSource->EnableVsync();
 }
 
 void
-CompositorVsyncObserver::UnobserveVsync()
+VsyncDispatcher::DisableVsync()
 {
   MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
-  VsyncDispatcher::GetInstance()->RemoveCompositorVsyncObserver(this);
   mIsObservingVsync = false;
+  mVsyncSource->DisableVsync();
 }
 
 void
-CompositorVsyncObserver::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
+VsyncDispatcher::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
 {
 #ifdef MOZ_WIDGET_GONK
   if (gfxPrefs::TouchResampling()) {
     GeckoTouchDispatcher::NotifyVsync(aVsyncTimestamp);
   }
 #endif
 }
 
@@ -378,21 +385,22 @@ CompositorParent::CompositorParent(nsIWi
 
   mRootLayerTreeID = AllocateLayerTreeId();
   sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
 
   if (gfxPrefs::AsyncPanZoomEnabled()) {
     mApzcTreeManager = new APZCTreeManager();
   }
 
+  gfxPlatform::GetPlatform()->ComputeTileSize();
+
   if (gfxPrefs::VsyncAlignedCompositor()) {
-    mCompositorVsyncObserver = new CompositorVsyncObserver(this);
+    nsRefPtr<VsyncSource> platformVsyncSource = gfxPlatform::GetPlatform()->GetVsyncSource();
+    mVsyncDispatcher = new VsyncDispatcher(this, platformVsyncSource.get());
   }
-
-  gfxPlatform::GetPlatform()->ComputeTileSize();
 }
 
 bool
 CompositorParent::IsInCompositorThread()
 {
   return CompositorThread() && CompositorThread()->thread_id() == PlatformThread::CurrentId();
 }
 
@@ -422,17 +430,17 @@ CompositorParent::Destroy()
   mCompositor = nullptr;
 
   mCompositionManager = nullptr;
   if (mApzcTreeManager) {
     mApzcTreeManager->ClearTree();
     mApzcTreeManager = nullptr;
   }
   sIndirectLayerTrees.erase(mRootLayerTreeID);
-  mCompositorVsyncObserver = nullptr;
+  mVsyncDispatcher = nullptr;
 }
 
 void
 CompositorParent::ForceIsFirstPaint()
 {
   mCompositionManager->ForceIsFirstPaint();
 }
 
@@ -504,18 +512,18 @@ CompositorParent::RecvMakeSnapshot(const
   RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
   ForceComposeToTarget(target, &aRect);
   return true;
 }
 
 bool
 CompositorParent::RecvFlushRendering()
 {
-  if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver->NeedsComposite()) {
-    mCompositorVsyncObserver->SetNeedsComposite(false);
+  if (gfxPrefs::VsyncAlignedCompositor() && mVsyncDispatcher->NeedsComposite()) {
+    mVsyncDispatcher->SetNeedsComposite(false);
     CancelCurrentCompositeTask();
     ForceComposeToTarget(nullptr);
   } else if (mCurrentCompositeTask) {
     // If we're waiting to do a composite, then cancel it
     // and do it immediately instead.
     CancelCurrentCompositeTask();
     ForceComposeToTarget(nullptr);
   }
@@ -642,17 +650,17 @@ CompositorParent::ForceComposition()
   mForceCompositionTask = nullptr;
   ScheduleRenderOnCompositorThread();
 }
 
 void
 CompositorParent::CancelCurrentCompositeTask()
 {
   if (gfxPrefs::VsyncAlignedCompositor()) {
-    mCompositorVsyncObserver->CancelCurrentCompositeTask();
+    mVsyncDispatcher->CancelCurrentCompositeTask();
   } else if (mCurrentCompositeTask) {
     mCurrentCompositeTask->Cancel();
     mCurrentCompositeTask = nullptr;
   }
 }
 
 void
 CompositorParent::SetEGLSurfaceSize(int width, int height)
@@ -792,17 +800,17 @@ CompositorParent::ScheduleSoftwareTimerC
   }
 }
 
 void
 CompositorParent::ScheduleComposition()
 {
   MOZ_ASSERT(IsInCompositorThread());
   if (gfxPrefs::VsyncAlignedCompositor()) {
-    mCompositorVsyncObserver->SetNeedsComposite(true);
+    mVsyncDispatcher->SetNeedsComposite(true);
   } else {
     ScheduleSoftwareTimerComposition();
   }
 }
 
 void
 CompositorParent::CompositeCallback(TimeStamp aScheduleTime)
 {
@@ -1013,17 +1021,17 @@ CompositorParent::ShadowLayersUpdated(La
     // values to avoid race conditions when calling GetAnimationTransform etc.
     // (since the above SetShadowProperties will remove animation effects).
     // However, we only do this update when a composite operation is already
     // scheduled in order to better match the behavior under regular sampling
     // conditions.
     bool needTestComposite = mIsTesting && root &&
                              (mCurrentCompositeTask ||
                              (gfxPrefs::VsyncAlignedCompositor() &&
-                              mCompositorVsyncObserver->NeedsComposite()));
+                              mVsyncDispatcher->NeedsComposite()));
     if (needTestComposite) {
       AutoResolveRefLayers resolve(mCompositionManager);
       bool requestNextFrame =
         mCompositionManager->TransformShadowTree(mTestTime);
       if (!requestNextFrame) {
         CancelCurrentCompositeTask();
         // Pretend we composited in case someone is waiting for this event.
         DidComposite();
@@ -1047,17 +1055,17 @@ CompositorParent::SetTestSampleTime(Laye
     return false;
   }
 
   mIsTesting = true;
   mTestTime = aTime;
 
   bool testComposite = mCompositionManager && (mCurrentCompositeTask ||
                                                (gfxPrefs::VsyncAlignedCompositor()
-                                               && mCompositorVsyncObserver->NeedsComposite()));
+                                               && mVsyncDispatcher->NeedsComposite()));
 
   // Update but only if we were already scheduled to animate
   if (testComposite) {
     AutoResolveRefLayers resolve(mCompositionManager);
     bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime);
     if (!requestNextFrame) {
       CancelCurrentCompositeTask();
       // Pretend we composited in case someone is wating for this event.
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -30,17 +30,16 @@
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "mozilla/layers/PCompositorParent.h"
 #include "mozilla/layers/ShadowLayersManager.h" // for ShadowLayersManager
 #include "mozilla/layers/APZTestData.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"
 #include "nsSize.h"                     // for nsIntSize
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
-#include "mozilla/VsyncDispatcher.h"
 
 class CancelableTask;
 class MessageLoop;
 class gfxContext;
 class nsIWidget;
 
 namespace mozilla {
 namespace gfx {
@@ -84,55 +83,73 @@ private:
   base::Thread* const mCompositorThread;
 
   static base::Thread* CreateCompositorThread();
   static void DestroyCompositorThread(base::Thread* aCompositorThread);
 
   friend class CompositorParent;
 };
 
+// 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
+
 /**
  * Manages the vsync (de)registration and tracking on behalf of the
  * compositor when it need to paint.
  * Turns vsync notifications into scheduled composites.
  **/
 
-class CompositorVsyncObserver MOZ_FINAL : public VsyncObserver
+class VsyncDispatcher MOZ_FINAL
 {
+  // Cleaned up on main thread along with the compositor. This has the same lifetime
+  // as the CompositorParent
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VsyncDispatcher)
   friend class CompositorParent;
 
 public:
-  CompositorVsyncObserver(CompositorParent* aCompositorParent);
-  virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) MOZ_OVERRIDE;
+  VsyncDispatcher(CompositorParent* aCompositorParent, VsyncSource* aVsyncSource);
+  static void NotifyVsync(TimeStamp aVsyncTimestamp);
+  void RunVsync(TimeStamp aVsyncTimestamp);
   void SetNeedsComposite(bool aSchedule);
   bool NeedsComposite();
   void CancelCurrentCompositeTask();
- 
+
 private:
-  virtual ~CompositorVsyncObserver();
+  virtual ~VsyncDispatcher();
 
   void Composite(TimeStamp aVsyncTimestamp);
   void NotifyCompositeTaskExecuted();
-  void ObserveVsync();
-  void UnobserveVsync();
+  void EnableVsync();
+  void DisableVsync();
   void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
 
   bool mNeedsComposite;
   bool mIsObservingVsync;
   nsRefPtr<CompositorParent> mCompositorParent;
+  nsRefPtr<VsyncSource> mVsyncSource;
 
   mozilla::Monitor mCurrentCompositeTaskMonitor;
   CancelableTask* mCurrentCompositeTask;
 };
 
 class CompositorParent MOZ_FINAL : public PCompositorParent,
                                    public ShadowLayersManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
-  friend class CompositorVsyncObserver;
+  friend class VsyncDispatcher;
 
 public:
   explicit CompositorParent(nsIWidget* aWidget,
                             bool aUseExternalSurfaceSize = false,
                             int aSurfaceWidth = -1, int aSurfaceHeight = -1);
 
   // IToplevelProtocol::CloneToplevel()
   virtual IToplevelProtocol*
@@ -383,17 +400,17 @@ protected:
   uint64_t mRootLayerTreeID;
 
   bool mOverrideComposeReadiness;
   CancelableTask* mForceCompositionTask;
 
   nsRefPtr<APZCTreeManager> mApzcTreeManager;
 
   nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
-  nsRefPtr<CompositorVsyncObserver> mCompositorVsyncObserver;
+  nsRefPtr<VsyncDispatcher> mVsyncDispatcher;
 
   DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
 };
 
 } // layers
 } // mozilla
 
 #endif // mozilla_layers_CompositorParent_h
deleted file mode 100644
--- a/widget/VsyncDispatcher.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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"
-
-#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")
-{
-
-}
-
-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
-}
-
-void
-VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
-{
-  bool notifiedCompositors = false;
-#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);
-  }
-}
-
-void
-VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
-{
-  MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
-  MutexAutoLock lock(mCompositorObserverLock);
-  if (mCompositorObservers.Contains(aVsyncObserver)) {
-    mCompositorObservers.RemoveElement(aVsyncObserver);
-  } else {
-    NS_WARNING("Could not delete a compositor vsync observer\n");
-  }
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/widget/VsyncDispatcher.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#ifndef mozilla_widget_VsyncDispatcher_h
-#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)
-
-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() {}
-  virtual ~VsyncObserver() {}
-}; // VsyncObserver
-
-// VsyncDispatcher is used to dispatch vsync events to the registered observers.
-class VsyncDispatcher
-{
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncDispatcher)
-
-public:
-  static VsyncDispatcher* GetInstance();
-  // 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);
-
-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;
-}; // VsyncDispatcher
-
-} // namespace mozilla
-
-#endif // __mozilla_widget_VsyncDispatcher_h
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -232,17 +232,17 @@ void
 HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp)
 {
     TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(aVsyncTimestamp);
     nsecs_t vsyncInterval = aVsyncTimestamp - mLastVsyncTime;
     if (vsyncInterval < 16000000 || vsyncInterval > 17000000) {
       LOGE("Non-uniform vsync interval: %lld\n", vsyncInterval);
     }
     mLastVsyncTime = aVsyncTimestamp;
-    VsyncDispatcher::GetInstance()->NotifyVsync(vsyncTime);
+    mozilla::layers::VsyncDispatcher::NotifyVsync(vsyncTime);
 }
 
 // Called on the "invalidator" thread (run from HAL).
 void
 HwcComposer2D::Invalidate()
 {
     if (!Initialized()) {
         LOGE("HwcComposer2D::Invalidate failed!");
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -118,17 +118,16 @@ EXPORTS.mozilla += [
     'EventClassList.h',
     'EventForwards.h',
     'LookAndFeel.h',
     'MiscEvents.h',
     'MouseEvents.h',
     'TextEvents.h',
     'TextRange.h',
     'TouchEvents.h',
-    'VsyncDispatcher.h',
     'WidgetUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'ContentHelper.cpp',
     'GfxDriverInfo.cpp',
     'GfxInfoBase.cpp',
     'GfxInfoCollector.cpp',
@@ -152,17 +151,16 @@ UNIFIED_SOURCES += [
     'nsScreenManagerProxy.cpp',
     'nsShmImage.cpp',
     'nsTransferable.cpp',
     'nsXPLookAndFeel.cpp',
     'PluginWidgetProxy.cpp',
     'PuppetWidget.cpp',
     'ScreenProxy.cpp',
     'SharedWidgetUtils.cpp',
-    'VsyncDispatcher.cpp',
     'WidgetEventImpl.cpp',
     'WidgetUtils.cpp',
 ]
 
 # nsBaseWidget.cpp needs to be built separately because of name clashes in the OS X headers
 SOURCES += [
     'nsBaseWidget.cpp',
 ]