diff --git a/gfx/thebes/VsyncSource.cpp b/gfx/thebes/VsyncSource.cpp index 6b4643379547..f9bd3bd584c9 100644 --- a/gfx/thebes/VsyncSource.cpp +++ b/gfx/thebes/VsyncSource.cpp @@ -7,6 +7,7 @@ #include "gfxPlatform.h" #include "mozilla/TimeStamp.h" #include "mozilla/VsyncDispatcher.h" +#include "MainThreadUtils.h" using namespace mozilla; using namespace mozilla::gfx; diff --git a/widget/VsyncDispatcher.cpp b/widget/VsyncDispatcher.cpp index 25710cfce957..f3f82bd9460c 100644 --- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -3,35 +3,30 @@ * 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 "mozilla/layers/CompositorParent.h" -#include "gfxPrefs.h" -#include "gfxPlatform.h" #include "VsyncSource.h" +#include "gfxPlatform.h" +#include "mozilla/layers/CompositorParent.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()); } @@ -42,12 +37,12 @@ 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); } } @@ -55,7 +50,7 @@ CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) void CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver) { - MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + MOZ_ASSERT(layers::CompositorParent::IsInCompositorThread()); MutexAutoLock lock(mCompositorObserverLock); mCompositorVsyncObserver = aVsyncObserver; } @@ -70,4 +65,57 @@ CompositorVsyncDispatcher::Shutdown() 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 diff --git a/widget/VsyncDispatcher.h b/widget/VsyncDispatcher.h index 188fc44046d8..56d3edc20ac1 100644 --- a/widget/VsyncDispatcher.h +++ b/widget/VsyncDispatcher.h @@ -6,18 +6,13 @@ #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 { @@ -25,7 +20,10 @@ class 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: @@ -33,9 +31,11 @@ protected: 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(); @@ -53,10 +53,41 @@ public: private: virtual ~CompositorVsyncDispatcher(); + Mutex mCompositorObserverLock; nsRefPtr 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 mParentRefreshTimer; + nsTArray> mChildRefreshTimers; +}; + } // namespace mozilla -#endif // __mozilla_widget_VsyncDispatcher_h +#endif // mozilla_widget_VsyncDispatcher_h