Line data Source code
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/. */
5 :
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"
13 :
14 : using namespace mozilla::layers;
15 :
16 : namespace mozilla {
17 :
18 1 : CompositorVsyncDispatcher::CompositorVsyncDispatcher()
19 : : mCompositorObserverLock("CompositorObserverLock")
20 1 : , mDidShutdown(false)
21 : {
22 1 : MOZ_ASSERT(XRE_IsParentProcess());
23 1 : MOZ_ASSERT(NS_IsMainThread());
24 1 : }
25 :
26 0 : CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
27 : {
28 0 : MOZ_ASSERT(XRE_IsParentProcess());
29 : // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
30 0 : }
31 :
32 : void
33 296 : CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
34 : {
35 : // In vsync thread
36 296 : layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
37 :
38 592 : MutexAutoLock lock(mCompositorObserverLock);
39 296 : if (mCompositorVsyncObserver) {
40 142 : mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
41 : }
42 296 : }
43 :
44 : void
45 16 : CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
46 : {
47 16 : MOZ_ASSERT(NS_IsMainThread());
48 16 : MOZ_ASSERT(XRE_IsParentProcess());
49 16 : if (mDidShutdown) {
50 0 : return;
51 : }
52 :
53 16 : if (aEnable) {
54 8 : gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
55 : } else {
56 8 : gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
57 : }
58 : }
59 :
60 : void
61 17 : CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
62 : {
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 17 : MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
67 :
68 : { // scope lock
69 34 : MutexAutoLock lock(mCompositorObserverLock);
70 17 : mCompositorVsyncObserver = aVsyncObserver;
71 : }
72 :
73 17 : bool observeVsync = aVsyncObserver != nullptr;
74 : nsCOMPtr<nsIRunnable> vsyncControl =
75 34 : NewRunnableMethod<bool>("CompositorVsyncDispatcher::ObserveVsync",
76 : this,
77 : &CompositorVsyncDispatcher::ObserveVsync,
78 34 : observeVsync);
79 17 : NS_DispatchToMainThread(vsyncControl);
80 17 : }
81 :
82 : void
83 0 : CompositorVsyncDispatcher::Shutdown()
84 : {
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 0 : MOZ_ASSERT(XRE_IsParentProcess());
89 0 : MOZ_ASSERT(NS_IsMainThread());
90 0 : ObserveVsync(false);
91 0 : mDidShutdown = true;
92 : { // scope lock
93 0 : MutexAutoLock lock(mCompositorObserverLock);
94 0 : mCompositorVsyncObserver = nullptr;
95 : }
96 0 : }
97 :
98 1 : RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
99 1 : : mRefreshTimersLock("RefreshTimers lock")
100 : {
101 1 : MOZ_ASSERT(XRE_IsParentProcess());
102 1 : MOZ_ASSERT(NS_IsMainThread());
103 1 : }
104 :
105 0 : RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
106 : {
107 0 : MOZ_ASSERT(XRE_IsParentProcess());
108 0 : MOZ_ASSERT(NS_IsMainThread());
109 0 : }
110 :
111 : void
112 510 : RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
113 : {
114 1020 : MutexAutoLock lock(mRefreshTimersLock);
115 :
116 554 : for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
117 44 : mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
118 : }
119 :
120 510 : if (mParentRefreshTimer) {
121 508 : mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
122 : }
123 510 : }
124 :
125 : void
126 9 : RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
127 : {
128 9 : MOZ_ASSERT(NS_IsMainThread());
129 : { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
130 18 : MutexAutoLock lock(mRefreshTimersLock);
131 9 : mParentRefreshTimer = aVsyncObserver;
132 : }
133 :
134 9 : UpdateVsyncStatus();
135 9 : }
136 :
137 : void
138 2 : RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
139 : {
140 : { // scope lock - called on pbackground thread
141 4 : MutexAutoLock lock(mRefreshTimersLock);
142 2 : MOZ_ASSERT(aVsyncObserver);
143 2 : if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
144 2 : mChildRefreshTimers.AppendElement(aVsyncObserver);
145 : }
146 : }
147 :
148 2 : UpdateVsyncStatus();
149 2 : }
150 :
151 : void
152 2 : RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
153 : {
154 : { // scope lock - called on pbackground thread
155 4 : MutexAutoLock lock(mRefreshTimersLock);
156 2 : MOZ_ASSERT(aVsyncObserver);
157 2 : mChildRefreshTimers.RemoveElement(aVsyncObserver);
158 : }
159 :
160 2 : UpdateVsyncStatus();
161 2 : }
162 :
163 : void
164 16 : RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
165 : {
166 16 : if (!NS_IsMainThread()) {
167 8 : NS_DispatchToMainThread(
168 8 : NewRunnableMethod("RefreshTimerVsyncDispatcher::UpdateVsyncStatus",
169 : this,
170 4 : &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
171 4 : return;
172 : }
173 :
174 12 : gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
175 12 : display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
176 : }
177 :
178 : bool
179 12 : RefreshTimerVsyncDispatcher::NeedsVsync()
180 : {
181 12 : MOZ_ASSERT(NS_IsMainThread());
182 24 : MutexAutoLock lock(mRefreshTimersLock);
183 24 : return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
184 : }
185 :
186 9 : } // namespace mozilla
|