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 : mVsyncSource(gfxPlatform::GetPlatform()->GetHardwareVsync()),
20 mCompositorObserverLock("CompositorObserverLock"),
22 MOZ_ASSERT(XRE_IsParentProcess());
23 MOZ_ASSERT(NS_IsMainThread());
25 mVsyncSource
->RegisterCompositorVsyncDispatcher(this);
28 CompositorVsyncDispatcher::CompositorVsyncDispatcher(
29 RefPtr
<gfx::VsyncSource
> aVsyncSource
)
30 : mVsyncSource(std::move(aVsyncSource
)),
31 mCompositorObserverLock("CompositorObserverLock"),
33 MOZ_ASSERT(XRE_IsParentProcess());
34 MOZ_ASSERT(NS_IsMainThread());
36 mVsyncSource
->RegisterCompositorVsyncDispatcher(this);
39 CompositorVsyncDispatcher::~CompositorVsyncDispatcher() {
40 MOZ_ASSERT(XRE_IsParentProcess());
41 // We auto remove this vsync dispatcher from the vsync source in the
45 void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent
& aVsync
) {
47 layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync
.mTime
);
49 MutexAutoLock
lock(mCompositorObserverLock
);
50 if (mCompositorVsyncObserver
) {
51 mCompositorVsyncObserver
->NotifyVsync(aVsync
);
55 void CompositorVsyncDispatcher::MoveToSource(
56 const RefPtr
<gfx::VsyncSource
>& aVsyncSource
) {
57 MOZ_ASSERT(NS_IsMainThread());
58 MOZ_ASSERT(XRE_IsParentProcess());
59 mVsyncSource
= aVsyncSource
;
62 void CompositorVsyncDispatcher::ObserveVsync(bool aEnable
) {
63 MOZ_ASSERT(NS_IsMainThread());
64 MOZ_ASSERT(XRE_IsParentProcess());
70 mVsyncSource
->EnableCompositorVsyncDispatcher(this);
72 mVsyncSource
->DisableCompositorVsyncDispatcher(this);
76 void CompositorVsyncDispatcher::SetCompositorVsyncObserver(
77 VsyncObserver
* aVsyncObserver
) {
78 // When remote compositing or running gtests, vsync observation is
79 // initiated on the main thread. Otherwise, it is initiated from the
81 MOZ_ASSERT(NS_IsMainThread() ||
82 CompositorThreadHolder::IsInCompositorThread());
85 MutexAutoLock
lock(mCompositorObserverLock
);
86 mCompositorVsyncObserver
= aVsyncObserver
;
89 bool observeVsync
= aVsyncObserver
!= nullptr;
90 nsCOMPtr
<nsIRunnable
> vsyncControl
= NewRunnableMethod
<bool>(
91 "CompositorVsyncDispatcher::ObserveVsync", this,
92 &CompositorVsyncDispatcher::ObserveVsync
, observeVsync
);
93 NS_DispatchToMainThread(vsyncControl
);
96 void CompositorVsyncDispatcher::Shutdown() {
97 // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget
98 // shuts down. Otherwise, we would get dead vsync notifications between when
99 // the nsBaseWidget shuts down and the CompositorBridgeParent shuts down.
100 MOZ_ASSERT(XRE_IsParentProcess());
101 MOZ_ASSERT(NS_IsMainThread());
102 MOZ_ASSERT(!mDidShutdown
);
106 MutexAutoLock
lock(mCompositorObserverLock
);
107 mCompositorVsyncObserver
= nullptr;
109 mVsyncSource
->DeregisterCompositorVsyncDispatcher(this);
110 mVsyncSource
= nullptr;
113 RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher(
114 gfx::VsyncSource
* aVsyncSource
)
115 : mVsyncSource(aVsyncSource
),
116 mVsyncObservers("RefreshTimerVsyncDispatcher::mVsyncObservers") {
117 MOZ_ASSERT(XRE_IsParentProcess());
118 MOZ_ASSERT(NS_IsMainThread());
121 RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() {
122 MOZ_ASSERT(XRE_IsParentProcess());
123 MOZ_ASSERT(NS_IsMainThread());
126 void RefreshTimerVsyncDispatcher::MoveToSource(gfx::VsyncSource
* aVsyncSource
) {
127 MOZ_ASSERT(NS_IsMainThread());
128 mVsyncSource
= aVsyncSource
;
131 void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent
& aVsync
) {
132 auto observers
= mVsyncObservers
.Lock();
134 for (const auto& observer
: *observers
) {
135 observer
->NotifyVsync(aVsync
);
139 void RefreshTimerVsyncDispatcher::AddVsyncObserver(
140 VsyncObserver
* aVsyncObserver
) {
141 MOZ_ASSERT(aVsyncObserver
);
142 { // scope lock - called on PBackground thread or main thread
143 auto observers
= mVsyncObservers
.Lock();
144 if (!observers
->Contains(aVsyncObserver
)) {
145 observers
->AppendElement(aVsyncObserver
);
152 void RefreshTimerVsyncDispatcher::RemoveVsyncObserver(
153 VsyncObserver
* aVsyncObserver
) {
154 MOZ_ASSERT(aVsyncObserver
);
155 { // scope lock - called on PBackground thread or main thread
156 auto observers
= mVsyncObservers
.Lock();
157 observers
->RemoveElement(aVsyncObserver
);
163 void RefreshTimerVsyncDispatcher::UpdateVsyncStatus() {
164 if (!NS_IsMainThread()) {
165 NS_DispatchToMainThread(NewRunnableMethod(
166 "RefreshTimerVsyncDispatcher::UpdateVsyncStatus", this,
167 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus
));
171 mVsyncSource
->NotifyRefreshTimerVsyncStatus(NeedsVsync());
174 bool RefreshTimerVsyncDispatcher::NeedsVsync() {
175 MOZ_ASSERT(NS_IsMainThread());
176 auto observers
= mVsyncObservers
.Lock();
177 return !observers
->IsEmpty();
180 } // namespace mozilla