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/Compositor.h"
11 #include "mozilla/layers/CompositorBridgeParent.h"
12 #include "mozilla/layers/CompositorThread.h"
14 using namespace mozilla::layers
;
18 CompositorVsyncDispatcher::CompositorVsyncDispatcher()
19 : mCompositorObserverLock("CompositorObserverLock")
22 MOZ_ASSERT(XRE_IsParentProcess());
23 MOZ_ASSERT(NS_IsMainThread());
26 CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
28 MOZ_ASSERT(XRE_IsParentProcess());
29 // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
33 CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp
)
36 layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp
);
38 MutexAutoLock
lock(mCompositorObserverLock
);
39 if (mCompositorVsyncObserver
) {
40 mCompositorVsyncObserver
->NotifyVsync(aVsyncTimestamp
);
45 CompositorVsyncDispatcher::ObserveVsync(bool aEnable
)
47 MOZ_ASSERT(NS_IsMainThread());
48 MOZ_ASSERT(XRE_IsParentProcess());
54 gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
56 gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
61 CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver
* aVsyncObserver
)
63 // When remote compositing or running gtests, vsync observation is
64 // initiated on the main thread. Otherwise, it is initiated from the compositor
66 MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
69 MutexAutoLock
lock(mCompositorObserverLock
);
70 mCompositorVsyncObserver
= aVsyncObserver
;
73 bool observeVsync
= aVsyncObserver
!= nullptr;
74 nsCOMPtr
<nsIRunnable
> vsyncControl
=
75 NewRunnableMethod
<bool>("CompositorVsyncDispatcher::ObserveVsync",
77 &CompositorVsyncDispatcher::ObserveVsync
,
79 NS_DispatchToMainThread(vsyncControl
);
83 CompositorVsyncDispatcher::Shutdown()
85 // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
86 // Otherwise, we would get dead vsync notifications between when the nsBaseWidget
87 // shuts down and the CompositorBridgeParent shuts down.
88 MOZ_ASSERT(XRE_IsParentProcess());
89 MOZ_ASSERT(NS_IsMainThread());
93 MutexAutoLock
lock(mCompositorObserverLock
);
94 mCompositorVsyncObserver
= nullptr;
98 RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
99 : mRefreshTimersLock("RefreshTimers lock")
101 MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
102 MOZ_ASSERT(NS_IsMainThread());
105 RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
107 MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
108 MOZ_ASSERT(NS_IsMainThread());
112 RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp
)
114 MutexAutoLock
lock(mRefreshTimersLock
);
116 for (size_t i
= 0; i
< mChildRefreshTimers
.Length(); i
++) {
117 mChildRefreshTimers
[i
]->NotifyVsync(aVsyncTimestamp
);
120 if (mParentRefreshTimer
) {
121 mParentRefreshTimer
->NotifyVsync(aVsyncTimestamp
);
126 RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver
* aVsyncObserver
)
128 MOZ_ASSERT(NS_IsMainThread());
129 { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
130 MutexAutoLock
lock(mRefreshTimersLock
);
131 mParentRefreshTimer
= aVsyncObserver
;
138 RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver
* aVsyncObserver
)
140 { // scope lock - called on pbackground thread
141 MutexAutoLock
lock(mRefreshTimersLock
);
142 MOZ_ASSERT(aVsyncObserver
);
143 if (!mChildRefreshTimers
.Contains(aVsyncObserver
)) {
144 mChildRefreshTimers
.AppendElement(aVsyncObserver
);
152 RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver
* aVsyncObserver
)
154 { // scope lock - called on pbackground thread
155 MutexAutoLock
lock(mRefreshTimersLock
);
156 MOZ_ASSERT(aVsyncObserver
);
157 mChildRefreshTimers
.RemoveElement(aVsyncObserver
);
164 RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
166 if (!NS_IsMainThread()) {
167 NS_DispatchToMainThread(
168 NewRunnableMethod("RefreshTimerVsyncDispatcher::UpdateVsyncStatus",
170 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus
));
174 gfx::VsyncSource::Display
& display
= gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
175 display
.NotifyRefreshTimerVsyncStatus(NeedsVsync());
179 RefreshTimerVsyncDispatcher::NeedsVsync()
181 MOZ_ASSERT(NS_IsMainThread());
182 MutexAutoLock
lock(mRefreshTimersLock
);
183 return (mParentRefreshTimer
!= nullptr) || !mChildRefreshTimers
.IsEmpty();
186 } // namespace mozilla