Bug 1477919 [wpt PR 12154] - url: DecodeURLEscapeSequences() should not apply UTF...
[gecko.git] / widget / VsyncDispatcher.cpp
blob244959f95c1daaf5850985d1f377bb2dc78c33f9
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;
16 namespace mozilla {
18 CompositorVsyncDispatcher::CompositorVsyncDispatcher()
19 : mCompositorObserverLock("CompositorObserverLock")
20 , mDidShutdown(false)
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
32 void
33 CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
35 // In vsync thread
36 layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
38 MutexAutoLock lock(mCompositorObserverLock);
39 if (mCompositorVsyncObserver) {
40 mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
44 void
45 CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
47 MOZ_ASSERT(NS_IsMainThread());
48 MOZ_ASSERT(XRE_IsParentProcess());
49 if (mDidShutdown) {
50 return;
53 if (aEnable) {
54 gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
55 } else {
56 gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
60 void
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
65 // thread.
66 MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
68 { // scope lock
69 MutexAutoLock lock(mCompositorObserverLock);
70 mCompositorVsyncObserver = aVsyncObserver;
73 bool observeVsync = aVsyncObserver != nullptr;
74 nsCOMPtr<nsIRunnable> vsyncControl =
75 NewRunnableMethod<bool>("CompositorVsyncDispatcher::ObserveVsync",
76 this,
77 &CompositorVsyncDispatcher::ObserveVsync,
78 observeVsync);
79 NS_DispatchToMainThread(vsyncControl);
82 void
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());
90 ObserveVsync(false);
91 mDidShutdown = true;
92 { // scope lock
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());
111 void
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);
125 void
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;
134 UpdateVsyncStatus();
137 void
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);
148 UpdateVsyncStatus();
151 void
152 RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
154 { // scope lock - called on pbackground thread
155 MutexAutoLock lock(mRefreshTimersLock);
156 MOZ_ASSERT(aVsyncObserver);
157 mChildRefreshTimers.RemoveElement(aVsyncObserver);
160 UpdateVsyncStatus();
163 void
164 RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
166 if (!NS_IsMainThread()) {
167 NS_DispatchToMainThread(
168 NewRunnableMethod("RefreshTimerVsyncDispatcher::UpdateVsyncStatus",
169 this,
170 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
171 return;
174 gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
175 display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
178 bool
179 RefreshTimerVsyncDispatcher::NeedsVsync()
181 MOZ_ASSERT(NS_IsMainThread());
182 MutexAutoLock lock(mRefreshTimersLock);
183 return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
186 } // namespace mozilla