123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /* -*- 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 "VsyncSource.h"
- #include "gfxPlatform.h"
- #include "mozilla/layers/Compositor.h"
- #include "mozilla/layers/CompositorBridgeParent.h"
- #include "mozilla/layers/CompositorThread.h"
- namespace mozilla {
- CompositorVsyncDispatcher::CompositorVsyncDispatcher()
- : mCompositorObserverLock("CompositorObserverLock")
- , mDidShutdown(false)
- {
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- }
- CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
- {
- MOZ_ASSERT(XRE_IsParentProcess());
- // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
- }
- void
- CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
- {
- MutexAutoLock lock(mCompositorObserverLock);
- if (mCompositorVsyncObserver) {
- mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
- }
- }
- void
- CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
- {
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(XRE_IsParentProcess());
- if (mDidShutdown) {
- return;
- }
- if (aEnable) {
- gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
- } else {
- gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
- }
- }
- void
- CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
- {
- // When remote compositing or running gtests, vsync observation is
- // initiated on the main thread. Otherwise, it is initiated from the compositor
- // thread.
- MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
- { // scope lock
- MutexAutoLock lock(mCompositorObserverLock);
- mCompositorVsyncObserver = aVsyncObserver;
- }
- bool observeVsync = aVsyncObserver != nullptr;
- nsCOMPtr<nsIRunnable> vsyncControl = NewRunnableMethod<bool>(this,
- &CompositorVsyncDispatcher::ObserveVsync,
- observeVsync);
- NS_DispatchToMainThread(vsyncControl);
- }
- 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 CompositorBridgeParent shuts down.
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- ObserveVsync(false);
- mDidShutdown = true;
- { // scope lock
- MutexAutoLock lock(mCompositorObserverLock);
- mCompositorVsyncObserver = nullptr;
- }
- }
- 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)
- {
- 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)
- {
- { // 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()) {
- NS_DispatchToMainThread(NewRunnableMethod(this,
- &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
- return;
- }
- gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
- display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
- }
- bool
- RefreshTimerVsyncDispatcher::NeedsVsync()
- {
- MOZ_ASSERT(NS_IsMainThread());
- MutexAutoLock lock(mRefreshTimersLock);
- return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
- }
- } // namespace mozilla
|