diff --git a/widget/VsyncDispatcher.cpp b/widget/VsyncDispatcher.cpp index 67ba7b0b5813..a5614e162e9b 100644 --- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -123,26 +123,61 @@ RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) void RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver) { - MutexAutoLock lock(mRefreshTimersLock); - mParentRefreshTimer = aVsyncObserver; + MOZ_ASSERT(NS_IsMainThread()); + { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock + MutexAutoLock lock(mRefreshTimersLock); + mParentRefreshTimer = aVsyncObserver; + } + + UpdateVsyncStatus(); } void RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver) { - MutexAutoLock lock(mRefreshTimersLock); - MOZ_ASSERT(aVsyncObserver); - if (!mChildRefreshTimers.Contains(aVsyncObserver)) { - mChildRefreshTimers.AppendElement(aVsyncObserver); + { // scope lock - called on pbackground thread + MutexAutoLock lock(mRefreshTimersLock); + MOZ_ASSERT(aVsyncObserver); + if (!mChildRefreshTimers.Contains(aVsyncObserver)) { + mChildRefreshTimers.AppendElement(aVsyncObserver); + } } + + UpdateVsyncStatus(); } void RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver) { + { // scope lock - called on pbackground thread + MutexAutoLock lock(mRefreshTimersLock); + MOZ_ASSERT(aVsyncObserver); + mChildRefreshTimers.RemoveElement(aVsyncObserver); + } + + UpdateVsyncStatus(); +} + +void +RefreshTimerVsyncDispatcher::UpdateVsyncStatus() +{ + if (!NS_IsMainThread()) { + nsCOMPtr vsyncControl = NS_NewRunnableMethod(this, + &RefreshTimerVsyncDispatcher::UpdateVsyncStatus); + NS_DispatchToMainThread(vsyncControl); + return; + } + + gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay(); + display.NotifyRefreshTimerVsyncStatus(NeedsVsync()); +} + +bool +RefreshTimerVsyncDispatcher::NeedsVsync() +{ + MOZ_ASSERT(NS_IsMainThread()); MutexAutoLock lock(mRefreshTimersLock); - MOZ_ASSERT(aVsyncObserver); - mChildRefreshTimers.RemoveElement(aVsyncObserver); + return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty(); } } // namespace mozilla diff --git a/widget/VsyncDispatcher.h b/widget/VsyncDispatcher.h index 5ac475f4e072..193a6ac53055 100644 --- a/widget/VsyncDispatcher.h +++ b/widget/VsyncDispatcher.h @@ -79,6 +79,8 @@ public: private: virtual ~RefreshTimerVsyncDispatcher(); + void UpdateVsyncStatus(); + bool NeedsVsync(); Mutex mRefreshTimersLock; nsRefPtr mParentRefreshTimer;