Bug 1118841 - Implement the RefreshTimerVsyncDispatcher. r=kats
authorJerryShih <hshih@mozilla.com>
Wed, 07 Jan 2015 18:17:36 -0800
changeset 222587 6d8e998d62122ef75626c0889f9185977b229cc1
parent 222586 83f3a7efed212ef4e7d1acf58cccce2e91f44880
child 222588 88492808aea554d9c0e6222874a2fb971a391589
push id28068
push usercbook@mozilla.com
push dateThu, 08 Jan 2015 13:16:34 +0000
treeherdermozilla-central@2880e05d5e32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1118841
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 1118841 - Implement the RefreshTimerVsyncDispatcher. r=kats
gfx/thebes/VsyncSource.cpp
widget/VsyncDispatcher.cpp
widget/VsyncDispatcher.h
--- a/gfx/thebes/VsyncSource.cpp
+++ b/gfx/thebes/VsyncSource.cpp
@@ -2,16 +2,17 @@
  * 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 "VsyncSource.h"
 #include "gfxPlatform.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/VsyncDispatcher.h"
+#include "MainThreadUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 void
 VsyncSource::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/widget/VsyncDispatcher.cpp
+++ b/widget/VsyncDispatcher.cpp
@@ -1,73 +1,121 @@
 /* -*- 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 "MainThreadUtils.h"
 #include "VsyncDispatcher.h"
-#include "mozilla/ClearOnShutdown.h"
+#include "VsyncSource.h"
+#include "gfxPlatform.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 {
 
 CompositorVsyncDispatcher::CompositorVsyncDispatcher()
   : mCompositorObserverLock("CompositorObserverLock")
 {
   MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
   gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
 }
 
 CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
 {
+  MOZ_ASSERT(XRE_IsParentProcess());
   // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 void
 CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
 {
   // In hardware vsync thread
 #ifdef MOZ_ENABLE_PROFILER_SPS
     if (profiler_is_active()) {
-        CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
+        layers::CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
     }
 #endif
 
   MutexAutoLock lock(mCompositorObserverLock);
-  if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver) {
+  if (mCompositorVsyncObserver) {
     mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
   }
 }
 
 void
 CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
 {
-  MOZ_ASSERT(CompositorParent::IsInCompositorThread());
+  MOZ_ASSERT(layers::CompositorParent::IsInCompositorThread());
   MutexAutoLock lock(mCompositorObserverLock);
   mCompositorVsyncObserver = aVsyncObserver;
 }
 
 void
 CompositorVsyncDispatcher::Shutdown()
 {
   // Need to explicitly remove CompositorVsyncDispatcher 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()->RemoveCompositorVsyncDispatcher(this);
 }
+
+RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
+  : mRefreshTimersLock("RefreshTimers lock")
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+void
+RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
+{
+  MutexAutoLock lock(mRefreshTimersLock);
+
+  for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
+    mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
+  }
+
+  if (mParentRefreshTimer) {
+    mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
+  }
+}
+
+void
+RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+  MutexAutoLock lock(mRefreshTimersLock);
+  mParentRefreshTimer = aVsyncObserver;
+}
+
+void
+RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+  MutexAutoLock lock(mRefreshTimersLock);
+  MOZ_ASSERT(aVsyncObserver);
+  if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
+    mChildRefreshTimers.AppendElement(aVsyncObserver);
+  }
+}
+
+void
+RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+  MutexAutoLock lock(mRefreshTimersLock);
+  MOZ_ASSERT(aVsyncObserver);
+  mChildRefreshTimers.RemoveElement(aVsyncObserver);
+}
+
 } // namespace mozilla
--- a/widget/VsyncDispatcher.h
+++ b/widget/VsyncDispatcher.h
@@ -1,46 +1,46 @@
 /* -*- 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 "mozilla/TimeStamp.h"
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
-#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
+#include "nsRefPtr.h"
 
 namespace mozilla {
-class TimeStamp;
-
-namespace layers {
-class CompositorVsyncObserver;
-}
 
 class 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
+  // In general, this vsync notification will occur on the hardware vsync
+  // thread from VsyncSource. But it might also be called on PVsync ipc thread
+  // if this notification is cross process. Thus all observer should check the
+  // thread model before handling the real task.
   virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
 
 protected:
   VsyncObserver() {}
   virtual ~VsyncObserver() {}
 }; // VsyncObserver
 
+// Used to dispatch vsync events in the parent process to compositors
 class CompositorVsyncDispatcher MOZ_FINAL
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncDispatcher)
+
 public:
   CompositorVsyncDispatcher();
 
   // 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
@@ -48,15 +48,46 @@ public:
   void NotifyVsync(TimeStamp aVsyncTimestamp);
 
   // Compositor vsync observers must be added/removed on the compositor thread
   void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
   void Shutdown();
 
 private:
   virtual ~CompositorVsyncDispatcher();
+
   Mutex mCompositorObserverLock;
   nsRefPtr<VsyncObserver> mCompositorVsyncObserver;
 };
 
+// Dispatch vsync event to ipc actor parent and chrome RefreshTimer.
+class RefreshTimerVsyncDispatcher MOZ_FINAL
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefreshTimerVsyncDispatcher)
+
+public:
+  RefreshTimerVsyncDispatcher();
+
+  // Please check CompositorVsyncDispatcher::NotifyVsync().
+  void NotifyVsync(TimeStamp aVsyncTimestamp);
+
+  // Set chrome process's RefreshTimer to this dispatcher.
+  // This function can be called from any thread.
+  void SetParentRefreshTimer(VsyncObserver* aVsyncObserver);
+
+  // Add or remove the content process' RefreshTimer to this dispatcher. This
+  // 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();
+
+  Mutex mRefreshTimersLock;
+  nsRefPtr<VsyncObserver> mParentRefreshTimer;
+  nsTArray<nsRefPtr<VsyncObserver>> mChildRefreshTimers;
+};
+
 } // namespace mozilla
 
-#endif // __mozilla_widget_VsyncDispatcher_h
+#endif // mozilla_widget_VsyncDispatcher_h