Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/widget/VsyncDispatcher.cpp
Line
Count
Source (jump to first uncovered line)
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
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
19
  : mCompositorObserverLock("CompositorObserverLock")
20
  , mDidShutdown(false)
21
0
{
22
0
  MOZ_ASSERT(XRE_IsParentProcess());
23
0
  MOZ_ASSERT(NS_IsMainThread());
24
0
}
25
26
CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
27
0
{
28
0
  MOZ_ASSERT(XRE_IsParentProcess());
29
0
  // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
30
0
}
31
32
void
33
CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
34
0
{
35
0
  // In vsync thread
36
0
  layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
37
0
38
0
  MutexAutoLock lock(mCompositorObserverLock);
39
0
  if (mCompositorVsyncObserver) {
40
0
    mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
41
0
  }
42
0
}
43
44
void
45
CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
46
0
{
47
0
  MOZ_ASSERT(NS_IsMainThread());
48
0
  MOZ_ASSERT(XRE_IsParentProcess());
49
0
  if (mDidShutdown) {
50
0
    return;
51
0
  }
52
0
53
0
  if (aEnable) {
54
0
    gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
55
0
  } else {
56
0
    gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
57
0
  }
58
0
}
59
60
void
61
CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
62
0
{
63
0
  // When remote compositing or running gtests, vsync observation is
64
0
  // initiated on the main thread. Otherwise, it is initiated from the compositor
65
0
  // thread.
66
0
  MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
67
0
68
0
  { // scope lock
69
0
    MutexAutoLock lock(mCompositorObserverLock);
70
0
    mCompositorVsyncObserver = aVsyncObserver;
71
0
  }
72
0
73
0
  bool observeVsync = aVsyncObserver != nullptr;
74
0
  nsCOMPtr<nsIRunnable> vsyncControl =
75
0
    NewRunnableMethod<bool>("CompositorVsyncDispatcher::ObserveVsync",
76
0
                            this,
77
0
                            &CompositorVsyncDispatcher::ObserveVsync,
78
0
                            observeVsync);
79
0
  NS_DispatchToMainThread(vsyncControl);
80
0
}
81
82
void
83
CompositorVsyncDispatcher::Shutdown()
84
0
{
85
0
  // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
86
0
  // Otherwise, we would get dead vsync notifications between when the nsBaseWidget
87
0
  // 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
0
  { // scope lock
93
0
    MutexAutoLock lock(mCompositorObserverLock);
94
0
    mCompositorVsyncObserver = nullptr;
95
0
  }
96
0
}
97
98
RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
99
  : mRefreshTimersLock("RefreshTimers lock")
100
0
{
101
0
  MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
102
0
  MOZ_ASSERT(NS_IsMainThread());
103
0
}
104
105
RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
106
0
{
107
0
  MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
108
0
  MOZ_ASSERT(NS_IsMainThread());
109
0
}
110
111
void
112
RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
113
0
{
114
0
  MutexAutoLock lock(mRefreshTimersLock);
115
0
116
0
  for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
117
0
    mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
118
0
  }
119
0
120
0
  if (mParentRefreshTimer) {
121
0
    mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
122
0
  }
123
0
}
124
125
void
126
RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
127
0
{
128
0
  MOZ_ASSERT(NS_IsMainThread());
129
0
  { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
130
0
    MutexAutoLock lock(mRefreshTimersLock);
131
0
    mParentRefreshTimer = aVsyncObserver;
132
0
  }
133
0
134
0
  UpdateVsyncStatus();
135
0
}
136
137
void
138
RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
139
0
{
140
0
  { // scope lock - called on pbackground thread
141
0
    MutexAutoLock lock(mRefreshTimersLock);
142
0
    MOZ_ASSERT(aVsyncObserver);
143
0
    if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
144
0
      mChildRefreshTimers.AppendElement(aVsyncObserver);
145
0
    }
146
0
  }
147
0
148
0
  UpdateVsyncStatus();
149
0
}
150
151
void
152
RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
153
0
{
154
0
  { // scope lock - called on pbackground thread
155
0
    MutexAutoLock lock(mRefreshTimersLock);
156
0
    MOZ_ASSERT(aVsyncObserver);
157
0
    mChildRefreshTimers.RemoveElement(aVsyncObserver);
158
0
  }
159
0
160
0
  UpdateVsyncStatus();
161
0
}
162
163
void
164
RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
165
0
{
166
0
  if (!NS_IsMainThread()) {
167
0
    NS_DispatchToMainThread(
168
0
      NewRunnableMethod("RefreshTimerVsyncDispatcher::UpdateVsyncStatus",
169
0
                        this,
170
0
                        &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
171
0
    return;
172
0
  }
173
0
174
0
  gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
175
0
  display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
176
0
}
177
178
bool
179
RefreshTimerVsyncDispatcher::NeedsVsync()
180
0
{
181
0
  MOZ_ASSERT(NS_IsMainThread());
182
0
  MutexAutoLock lock(mRefreshTimersLock);
183
0
  return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
184
0
}
185
186
} // namespace mozilla