Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/thebes/VsyncSource.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 "VsyncSource.h"
7
#include "nsThreadUtils.h"
8
#include "nsXULAppAPI.h"
9
#include "mozilla/VsyncDispatcher.h"
10
#include "MainThreadUtils.h"
11
12
namespace mozilla {
13
namespace gfx {
14
15
void
16
VsyncSource::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
17
0
{
18
0
  MOZ_ASSERT(XRE_IsParentProcess());
19
0
  MOZ_ASSERT(NS_IsMainThread());
20
0
  // Just use the global display until we have enough information to get the
21
0
  // corresponding display for compositor.
22
0
  GetGlobalDisplay().AddCompositorVsyncDispatcher(aCompositorVsyncDispatcher);
23
0
}
24
25
void
26
VsyncSource::RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
27
0
{
28
0
  MOZ_ASSERT(XRE_IsParentProcess());
29
0
  MOZ_ASSERT(NS_IsMainThread());
30
0
  // See also AddCompositorVsyncDispatcher().
31
0
  GetGlobalDisplay().RemoveCompositorVsyncDispatcher(aCompositorVsyncDispatcher);
32
0
}
33
34
RefPtr<RefreshTimerVsyncDispatcher>
35
VsyncSource::GetRefreshTimerVsyncDispatcher()
36
0
{
37
0
  MOZ_ASSERT(XRE_IsParentProcess());
38
0
  // See also AddCompositorVsyncDispatcher().
39
0
  return GetGlobalDisplay().GetRefreshTimerVsyncDispatcher();
40
0
}
41
42
VsyncSource::Display::Display()
43
  : mDispatcherLock("display dispatcher lock")
44
  , mRefreshTimerNeedsVsync(false)
45
0
{
46
0
  MOZ_ASSERT(NS_IsMainThread());
47
0
  mRefreshTimerVsyncDispatcher = new RefreshTimerVsyncDispatcher();
48
0
}
49
50
VsyncSource::Display::~Display()
51
0
{
52
0
  MOZ_ASSERT(NS_IsMainThread());
53
0
  MutexAutoLock lock(mDispatcherLock);
54
0
  mRefreshTimerVsyncDispatcher = nullptr;
55
0
  mCompositorVsyncDispatchers.Clear();
56
0
}
57
58
void
59
VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp)
60
0
{
61
0
  // Called on the vsync thread
62
0
  MutexAutoLock lock(mDispatcherLock);
63
0
64
0
  for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
65
0
    mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp);
66
0
  }
67
0
68
0
  mRefreshTimerVsyncDispatcher->NotifyVsync(aVsyncTimestamp);
69
0
}
70
71
TimeDuration
72
VsyncSource::Display::GetVsyncRate()
73
0
{
74
0
  // If hardware queries fail / are unsupported, we have to just guess.
75
0
  return TimeDuration::FromMilliseconds(1000.0 / 60.0);
76
0
}
77
78
void
79
VsyncSource::Display::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
80
0
{
81
0
  MOZ_ASSERT(NS_IsMainThread());
82
0
  MOZ_ASSERT(aCompositorVsyncDispatcher);
83
0
  { // scope lock
84
0
    MutexAutoLock lock(mDispatcherLock);
85
0
    if (!mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) {
86
0
      mCompositorVsyncDispatchers.AppendElement(aCompositorVsyncDispatcher);
87
0
    }
88
0
  }
89
0
  UpdateVsyncStatus();
90
0
}
91
92
void
93
VsyncSource::Display::RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
94
0
{
95
0
  MOZ_ASSERT(NS_IsMainThread());
96
0
  MOZ_ASSERT(aCompositorVsyncDispatcher);
97
0
  { // Scope lock
98
0
    MutexAutoLock lock(mDispatcherLock);
99
0
    if (mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) {
100
0
      mCompositorVsyncDispatchers.RemoveElement(aCompositorVsyncDispatcher);
101
0
    }
102
0
  }
103
0
  UpdateVsyncStatus();
104
0
}
105
106
void
107
VsyncSource::Display::NotifyRefreshTimerVsyncStatus(bool aEnable)
108
0
{
109
0
  MOZ_ASSERT(NS_IsMainThread());
110
0
  mRefreshTimerNeedsVsync = aEnable;
111
0
  UpdateVsyncStatus();
112
0
}
113
114
void
115
VsyncSource::Display::UpdateVsyncStatus()
116
0
{
117
0
  MOZ_ASSERT(NS_IsMainThread());
118
0
  // WARNING: This function SHOULD NOT BE CALLED WHILE HOLDING LOCKS
119
0
  // NotifyVsync grabs a lock to dispatch vsync events
120
0
  // When disabling vsync, we wait for the underlying thread to stop on some platforms
121
0
  // We can deadlock if we wait for the underlying vsync thread to stop
122
0
  // while the vsync thread is in NotifyVsync.
123
0
  bool enableVsync = false;
124
0
  { // scope lock
125
0
    MutexAutoLock lock(mDispatcherLock);
126
0
    enableVsync = !mCompositorVsyncDispatchers.IsEmpty() || mRefreshTimerNeedsVsync;
127
0
  }
128
0
129
0
  if (enableVsync) {
130
0
    EnableVsync();
131
0
  } else {
132
0
    DisableVsync();
133
0
  }
134
0
135
0
  if (IsVsyncEnabled() != enableVsync) {
136
0
    NS_WARNING("Vsync status did not change.");
137
0
  }
138
0
}
139
140
RefPtr<RefreshTimerVsyncDispatcher>
141
VsyncSource::Display::GetRefreshTimerVsyncDispatcher()
142
0
{
143
0
  return mRefreshTimerVsyncDispatcher;
144
0
}
145
146
void
147
VsyncSource::Shutdown()
148
0
{
149
0
  GetGlobalDisplay().Shutdown();
150
0
}
151
152
} //namespace gfx
153
} //namespace mozilla