Bug 1527719 [wpt PR 15359] - KV storage: make backingStore return the same frozen...
[gecko.git] / widget / VsyncDispatcher.cpp
blobe73a8abb909dc3dd30cafd1dcbfa7ce079672256
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"), mDidShutdown(false) {
20 MOZ_ASSERT(XRE_IsParentProcess());
21 MOZ_ASSERT(NS_IsMainThread());
24 CompositorVsyncDispatcher::~CompositorVsyncDispatcher() {
25 MOZ_ASSERT(XRE_IsParentProcess());
26 // We auto remove this vsync dispatcher from the vsync source in the
27 // nsBaseWidget
30 void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
31 // In vsync thread
32 layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync.mTime);
34 MutexAutoLock lock(mCompositorObserverLock);
35 if (mCompositorVsyncObserver) {
36 mCompositorVsyncObserver->NotifyVsync(aVsync);
40 void CompositorVsyncDispatcher::ObserveVsync(bool aEnable) {
41 MOZ_ASSERT(NS_IsMainThread());
42 MOZ_ASSERT(XRE_IsParentProcess());
43 if (mDidShutdown) {
44 return;
47 if (aEnable) {
48 gfxPlatform::GetPlatform()
49 ->GetHardwareVsync()
50 ->AddCompositorVsyncDispatcher(this);
51 } else {
52 gfxPlatform::GetPlatform()
53 ->GetHardwareVsync()
54 ->RemoveCompositorVsyncDispatcher(this);
58 void CompositorVsyncDispatcher::SetCompositorVsyncObserver(
59 VsyncObserver* aVsyncObserver) {
60 // When remote compositing or running gtests, vsync observation is
61 // initiated on the main thread. Otherwise, it is initiated from the
62 // compositor thread.
63 MOZ_ASSERT(NS_IsMainThread() ||
64 CompositorThreadHolder::IsInCompositorThread());
66 { // scope lock
67 MutexAutoLock lock(mCompositorObserverLock);
68 mCompositorVsyncObserver = aVsyncObserver;
71 bool observeVsync = aVsyncObserver != nullptr;
72 nsCOMPtr<nsIRunnable> vsyncControl = NewRunnableMethod<bool>(
73 "CompositorVsyncDispatcher::ObserveVsync", this,
74 &CompositorVsyncDispatcher::ObserveVsync, observeVsync);
75 NS_DispatchToMainThread(vsyncControl);
78 void CompositorVsyncDispatcher::Shutdown() {
79 // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget
80 // shuts down. Otherwise, we would get dead vsync notifications between when
81 // the nsBaseWidget shuts down and the CompositorBridgeParent shuts down.
82 MOZ_ASSERT(XRE_IsParentProcess());
83 MOZ_ASSERT(NS_IsMainThread());
84 ObserveVsync(false);
85 mDidShutdown = true;
86 { // scope lock
87 MutexAutoLock lock(mCompositorObserverLock);
88 mCompositorVsyncObserver = nullptr;
92 RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
93 : mRefreshTimersLock("RefreshTimers lock") {
94 MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
95 MOZ_ASSERT(NS_IsMainThread());
98 RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() {
99 MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
100 MOZ_ASSERT(NS_IsMainThread());
103 void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
104 MutexAutoLock lock(mRefreshTimersLock);
106 for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
107 mChildRefreshTimers[i]->NotifyVsync(aVsync);
110 if (mParentRefreshTimer) {
111 mParentRefreshTimer->NotifyVsync(aVsync);
115 void RefreshTimerVsyncDispatcher::SetParentRefreshTimer(
116 VsyncObserver* aVsyncObserver) {
117 MOZ_ASSERT(NS_IsMainThread());
118 { // lock scope because UpdateVsyncStatus runs on main thread and will
119 // deadlock
120 MutexAutoLock lock(mRefreshTimersLock);
121 mParentRefreshTimer = aVsyncObserver;
124 UpdateVsyncStatus();
127 void RefreshTimerVsyncDispatcher::AddChildRefreshTimer(
128 VsyncObserver* aVsyncObserver) {
129 { // scope lock - called on pbackground thread
130 MutexAutoLock lock(mRefreshTimersLock);
131 MOZ_ASSERT(aVsyncObserver);
132 if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
133 mChildRefreshTimers.AppendElement(aVsyncObserver);
137 UpdateVsyncStatus();
140 void RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(
141 VsyncObserver* aVsyncObserver) {
142 { // scope lock - called on pbackground thread
143 MutexAutoLock lock(mRefreshTimersLock);
144 MOZ_ASSERT(aVsyncObserver);
145 mChildRefreshTimers.RemoveElement(aVsyncObserver);
148 UpdateVsyncStatus();
151 void RefreshTimerVsyncDispatcher::UpdateVsyncStatus() {
152 if (!NS_IsMainThread()) {
153 NS_DispatchToMainThread(NewRunnableMethod(
154 "RefreshTimerVsyncDispatcher::UpdateVsyncStatus", this,
155 &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
156 return;
159 gfx::VsyncSource::Display& display =
160 gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
161 display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
164 bool RefreshTimerVsyncDispatcher::NeedsVsync() {
165 MOZ_ASSERT(NS_IsMainThread());
166 MutexAutoLock lock(mRefreshTimersLock);
167 return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
170 } // namespace mozilla