void VsyncSource::Display::UpdateVsyncStatus() { MOZ_ASSERT(NS_IsMainThread()); // WARNING: This function SHOULD NOT BE CALLED WHILE HOLDING LOCKS // NotifyVsync grabs a lock to dispatch vsync events // When disabling vsync, we wait for the underlying thread to stop on some platforms // We can deadlock if we wait for the underlying vsync thread to stop // while the vsync thread is in NotifyVsync. bool enableVsync = false; { // scope lock MutexAutoLock lock(mDispatcherLock); enableVsync = !mCompositorVsyncDispatchers.IsEmpty() || mRefreshTimerNeedsVsync; } if (enableVsync) { EnableVsync(); } else { DisableVsync(); } if (IsVsyncEnabled() != enableVsync) { NS_WARNING("Vsync status did not change."); } }
void SoftwareDisplay::DisableVsync() { MOZ_ASSERT(NS_IsMainThread()); if (!IsVsyncEnabled()) { return; } MOZ_ASSERT(mVsyncThread->IsRunning()); { // scope lock mozilla::MonitorAutoLock lock(mCurrentTaskMonitor); mVsyncEnabled = false; if (mCurrentVsyncTask) { mCurrentVsyncTask->Cancel(); mCurrentVsyncTask = nullptr; } } mVsyncThread->Stop(); }
void SoftwareDisplay::EnableVsync() { MOZ_ASSERT(NS_IsMainThread()); if (IsVsyncEnabled()) { return; } { // scope lock mozilla::MonitorAutoLock lock(mCurrentTaskMonitor); mVsyncEnabled = true; MOZ_ASSERT(!mVsyncThread->IsRunning()); MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread"); mCurrentVsyncTask = NewRunnableMethod(this, &SoftwareDisplay::NotifyVsync, mozilla::TimeStamp::Now()); mVsyncThread->message_loop()->PostTask(FROM_HERE, mCurrentVsyncTask); } }