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"
19 CompositorVsyncDispatcher::CompositorVsyncDispatcher()
20 : mCompositorObserverLock("CompositorObserverLock")
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());
35 CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp
)
38 #ifdef MOZ_ENABLE_PROFILER_SPS
39 if (profiler_is_active()) {
40 layers::CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp
);
44 MutexAutoLock
lock(mCompositorObserverLock
);
45 if (mCompositorVsyncObserver
) {
46 mCompositorVsyncObserver
->NotifyVsync(aVsyncTimestamp
);
51 CompositorVsyncDispatcher::ObserveVsync(bool aEnable
)
53 MOZ_ASSERT(NS_IsMainThread());
54 MOZ_ASSERT(XRE_IsParentProcess());
60 gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
62 gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
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
,
77 NS_DispatchToMainThread(vsyncControl
);
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());
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());
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
);
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
;
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
);
150 RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver
* aVsyncObserver
)
152 { // scope lock - called on pbackground thread
153 MutexAutoLock
lock(mRefreshTimersLock
);
154 MOZ_ASSERT(aVsyncObserver
);
155 mChildRefreshTimers
.RemoveElement(aVsyncObserver
);
162 RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
164 if (!NS_IsMainThread()) {
165 nsCOMPtr
<nsIRunnable
> vsyncControl
= NS_NewRunnableMethod(this,
166 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus
);
167 NS_DispatchToMainThread(vsyncControl
);
171 gfx::VsyncSource::Display
& display
= gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
172 display
.NotifyRefreshTimerVsyncStatus(NeedsVsync());
176 RefreshTimerVsyncDispatcher::NeedsVsync()
178 MOZ_ASSERT(NS_IsMainThread());
179 MutexAutoLock
lock(mRefreshTimersLock
);
180 return (mParentRefreshTimer
!= nullptr) || !mChildRefreshTimers
.IsEmpty();
183 } // namespace mozilla