Bumping manifests a=b2g-bump
[gecko.git] / widget / VsyncDispatcher.cpp
bloba5614e162e9b0e07ced7c40ab13d7db58519c058
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "MainThreadUtils.h"
7 #include "VsyncDispatcher.h"
8 #include "VsyncSource.h"
9 #include "gfxPlatform.h"
10 #include "mozilla/layers/CompositorParent.h"
12 #ifdef MOZ_ENABLE_PROFILER_SPS
13 #include "GeckoProfiler.h"
14 #include "ProfilerMarkers.h"
15 #endif
17 namespace mozilla {
19 CompositorVsyncDispatcher::CompositorVsyncDispatcher()
20 : mCompositorObserverLock("CompositorObserverLock")
21 , mDidShutdown(false)
23 MOZ_ASSERT(XRE_IsParentProcess());
24 MOZ_ASSERT(NS_IsMainThread());
27 CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
29 MOZ_ASSERT(XRE_IsParentProcess());
30 // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
31 MOZ_ASSERT(NS_IsMainThread());
34 void
35 CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
37 // In vsync thread
38 #ifdef MOZ_ENABLE_PROFILER_SPS
39 if (profiler_is_active()) {
40 layers::CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
42 #endif
44 MutexAutoLock lock(mCompositorObserverLock);
45 if (mCompositorVsyncObserver) {
46 mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
50 void
51 CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
53 MOZ_ASSERT(NS_IsMainThread());
54 MOZ_ASSERT(XRE_IsParentProcess());
55 if (mDidShutdown) {
56 return;
59 if (aEnable) {
60 gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
61 } else {
62 gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
66 void
67 CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
69 MOZ_ASSERT(layers::CompositorParent::IsInCompositorThread());
70 MutexAutoLock lock(mCompositorObserverLock);
71 mCompositorVsyncObserver = aVsyncObserver;
73 bool observeVsync = aVsyncObserver != nullptr;
74 nsCOMPtr<nsIRunnable> vsyncControl = NS_NewRunnableMethodWithArg<bool>(this,
75 &CompositorVsyncDispatcher::ObserveVsync,
76 observeVsync);
77 NS_DispatchToMainThread(vsyncControl);
80 void
81 CompositorVsyncDispatcher::Shutdown()
83 // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
84 // Otherwise, we would get dead vsync notifications between when the nsBaseWidget
85 // shuts down and the CompositorParent shuts down.
86 MOZ_ASSERT(XRE_IsParentProcess());
87 MOZ_ASSERT(NS_IsMainThread());
88 ObserveVsync(false);
89 mDidShutdown = true;
90 { // scope lock
91 MutexAutoLock lock(mCompositorObserverLock);
92 mCompositorVsyncObserver = nullptr;
96 RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
97 : mRefreshTimersLock("RefreshTimers lock")
99 MOZ_ASSERT(XRE_IsParentProcess());
100 MOZ_ASSERT(NS_IsMainThread());
103 RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
105 MOZ_ASSERT(XRE_IsParentProcess());
106 MOZ_ASSERT(NS_IsMainThread());
109 void
110 RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
112 MutexAutoLock lock(mRefreshTimersLock);
114 for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
115 mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
118 if (mParentRefreshTimer) {
119 mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
123 void
124 RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
126 MOZ_ASSERT(NS_IsMainThread());
127 { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
128 MutexAutoLock lock(mRefreshTimersLock);
129 mParentRefreshTimer = aVsyncObserver;
132 UpdateVsyncStatus();
135 void
136 RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
138 { // scope lock - called on pbackground thread
139 MutexAutoLock lock(mRefreshTimersLock);
140 MOZ_ASSERT(aVsyncObserver);
141 if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
142 mChildRefreshTimers.AppendElement(aVsyncObserver);
146 UpdateVsyncStatus();
149 void
150 RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
152 { // scope lock - called on pbackground thread
153 MutexAutoLock lock(mRefreshTimersLock);
154 MOZ_ASSERT(aVsyncObserver);
155 mChildRefreshTimers.RemoveElement(aVsyncObserver);
158 UpdateVsyncStatus();
161 void
162 RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
164 if (!NS_IsMainThread()) {
165 nsCOMPtr<nsIRunnable> vsyncControl = NS_NewRunnableMethod(this,
166 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus);
167 NS_DispatchToMainThread(vsyncControl);
168 return;
171 gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
172 display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
175 bool
176 RefreshTimerVsyncDispatcher::NeedsVsync()
178 MOZ_ASSERT(NS_IsMainThread());
179 MutexAutoLock lock(mRefreshTimersLock);
180 return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
183 } // namespace mozilla