diff --git a/widget/VsyncDispatcher.cpp b/widget/VsyncDispatcher.cpp index 44168766e72b..5aa8c5322ca6 100644 --- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -7,6 +7,8 @@ #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" @@ -21,97 +23,51 @@ using namespace mozilla::layers; namespace mozilla { -StaticRefPtr 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); + MutexAutoLock lock(mCompositorObserverLock); + if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver) { + mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp); } - - DispatchTouchEvents(notifiedCompositors, aVsyncTimestamp); -} - -bool -VsyncDispatcher::NotifyVsyncObservers(TimeStamp aVsyncTimestamp, nsTArray>& 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) +VsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver) { MOZ_ASSERT(CompositorParent::IsInCompositorThread()); MutexAutoLock lock(mCompositorObserverLock); - if (!mCompositorObservers.Contains(aVsyncObserver)) { - mCompositorObservers.AppendElement(aVsyncObserver); - } + mCompositorVsyncObserver = aVsyncObserver; } void -VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver) +VsyncDispatcher::Shutdown() { - 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"); - } + // 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 diff --git a/widget/VsyncDispatcher.h b/widget/VsyncDispatcher.h index 797a0b426b82..2a38f4707707 100644 --- a/widget/VsyncDispatcher.h +++ b/widget/VsyncDispatcher.h @@ -12,8 +12,6 @@ #include "nsTArray.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h" -class MessageLoop; - namespace mozilla { class TimeStamp; @@ -21,23 +19,10 @@ 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. @@ -55,7 +40,8 @@ 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 @@ -63,24 +49,15 @@ public: // 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>& aObservers); - - // Can have multiple compositors. On desktop, this is 1 compositor per window Mutex mCompositorObserverLock; - nsTArray> mCompositorObservers; - nsRefPtr mVsyncSource; + nsRefPtr mCompositorVsyncObserver; }; // VsyncDispatcher } // namespace mozilla