Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/tests/gtest/TestVsync.cpp
Line
Count
Source (jump to first uncovered line)
1
/* vim:set ts=2 sw=2 sts=2 et: */
2
/* Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
#include "gmock/gmock.h"
7
#include "gtest/gtest.h"
8
#include "gfxPlatform.h"
9
#include "gfxPrefs.h"
10
#include "MainThreadUtils.h"
11
#include "nsIThread.h"
12
#include "mozilla/RefPtr.h"
13
#include "SoftwareVsyncSource.h"
14
#include "VsyncSource.h"
15
#include "mozilla/Monitor.h"
16
#include "mozilla/TimeStamp.h"
17
#include "mozilla/VsyncDispatcher.h"
18
19
using namespace mozilla;
20
using namespace mozilla::gfx;
21
using namespace mozilla::layers;
22
using ::testing::_;
23
24
// Timeout for vsync events to occur in milliseconds
25
// Windows 8.1 has intermittents at 50 ms. Raise limit to 5 vsync intervals.
26
const int kVsyncTimeoutMS = 80;
27
28
class TestVsyncObserver : public VsyncObserver {
29
public:
30
  TestVsyncObserver()
31
    : mDidGetVsyncNotification(false)
32
    , mVsyncMonitor("VsyncMonitor")
33
0
  {
34
0
  }
35
36
0
  virtual bool NotifyVsync(TimeStamp aVsyncTimeStamp) override {
37
0
    MonitorAutoLock lock(mVsyncMonitor);
38
0
    mDidGetVsyncNotification = true;
39
0
    mVsyncMonitor.Notify();
40
0
    return true;
41
0
  }
42
43
  void WaitForVsyncNotification()
44
0
  {
45
0
    MOZ_ASSERT(NS_IsMainThread());
46
0
    if (DidGetVsyncNotification()) {
47
0
      return;
48
0
    }
49
0
50
0
    { // scope lock
51
0
      MonitorAutoLock lock(mVsyncMonitor);
52
0
      lock.Wait(TimeDuration::FromMilliseconds(kVsyncTimeoutMS));
53
0
    }
54
0
  }
55
56
  bool DidGetVsyncNotification()
57
0
  {
58
0
    MonitorAutoLock lock(mVsyncMonitor);
59
0
    return mDidGetVsyncNotification;
60
0
  }
61
62
  void ResetVsyncNotification()
63
0
  {
64
0
    MonitorAutoLock lock(mVsyncMonitor);
65
0
    mDidGetVsyncNotification = false;
66
0
  }
67
68
private:
69
  bool mDidGetVsyncNotification;
70
71
private:
72
  Monitor mVsyncMonitor;
73
};
74
75
class VsyncTester : public ::testing::Test {
76
protected:
77
  explicit VsyncTester()
78
0
  {
79
0
    gfxPlatform::GetPlatform();
80
0
    gfxPrefs::GetSingleton();
81
0
    mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
82
0
    MOZ_RELEASE_ASSERT(mVsyncSource, "GFX: Vsync source not found.");
83
0
  }
84
85
  virtual ~VsyncTester()
86
0
  {
87
0
    mVsyncSource = nullptr;
88
0
  }
89
90
  RefPtr<VsyncSource> mVsyncSource;
91
};
92
93
static void
94
FlushMainThreadLoop()
95
0
{
96
0
  // Some tasks are pushed onto the main thread when adding vsync observers
97
0
  // This function will ensure all tasks are executed on the main thread
98
0
  // before returning.
99
0
  nsCOMPtr<nsIThread> mainThread;
100
0
  nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
101
0
  ASSERT_TRUE(NS_SUCCEEDED(rv));
102
0
103
0
  rv = NS_OK;
104
0
  bool processed = true;
105
0
  while (processed && NS_SUCCEEDED(rv)) {
106
0
    rv = mainThread->ProcessNextEvent(false, &processed);
107
0
  }
108
0
}
109
110
// Tests that we can enable/disable vsync notifications
111
TEST_F(VsyncTester, EnableVsync)
112
0
{
113
0
  VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
114
0
  globalDisplay.DisableVsync();
115
0
  ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
116
0
117
0
  globalDisplay.EnableVsync();
118
0
  ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
119
0
120
0
  globalDisplay.DisableVsync();
121
0
  ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
122
0
}
123
124
// Test that if we have vsync enabled, the display should get vsync notifications
125
TEST_F(VsyncTester, CompositorGetVsyncNotifications)
126
0
{
127
0
  VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
128
0
  globalDisplay.DisableVsync();
129
0
  ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
130
0
131
0
  RefPtr<CompositorVsyncDispatcher> vsyncDispatcher = new CompositorVsyncDispatcher();
132
0
  RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
133
0
134
0
  vsyncDispatcher->SetCompositorVsyncObserver(testVsyncObserver);
135
0
  FlushMainThreadLoop();
136
0
  ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
137
0
138
0
  testVsyncObserver->WaitForVsyncNotification();
139
0
  ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
140
0
141
0
  vsyncDispatcher = nullptr;
142
0
  testVsyncObserver = nullptr;
143
0
}
144
145
// Test that if we have vsync enabled, the parent refresh driver should get notifications
146
TEST_F(VsyncTester, ParentRefreshDriverGetVsyncNotifications)
147
0
{
148
0
  VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
149
0
  globalDisplay.DisableVsync();
150
0
  ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
151
0
152
0
  RefPtr<RefreshTimerVsyncDispatcher> vsyncDispatcher = globalDisplay.GetRefreshTimerVsyncDispatcher();
153
0
  ASSERT_TRUE(vsyncDispatcher != nullptr);
154
0
155
0
  RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
156
0
  vsyncDispatcher->SetParentRefreshTimer(testVsyncObserver);
157
0
  ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
158
0
159
0
  testVsyncObserver->WaitForVsyncNotification();
160
0
  ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
161
0
  vsyncDispatcher->SetParentRefreshTimer(nullptr);
162
0
163
0
  testVsyncObserver->ResetVsyncNotification();
164
0
  testVsyncObserver->WaitForVsyncNotification();
165
0
  ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification());
166
0
167
0
  vsyncDispatcher = nullptr;
168
0
  testVsyncObserver = nullptr;
169
0
}
170
171
// Test that child refresh vsync observers get vsync notifications
172
TEST_F(VsyncTester, ChildRefreshDriverGetVsyncNotifications)
173
0
{
174
0
  VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
175
0
  globalDisplay.DisableVsync();
176
0
  ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
177
0
178
0
  RefPtr<RefreshTimerVsyncDispatcher> vsyncDispatcher = globalDisplay.GetRefreshTimerVsyncDispatcher();
179
0
  ASSERT_TRUE(vsyncDispatcher != nullptr);
180
0
181
0
  RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
182
0
  vsyncDispatcher->AddChildRefreshTimer(testVsyncObserver);
183
0
  ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
184
0
185
0
  testVsyncObserver->WaitForVsyncNotification();
186
0
  ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
187
0
188
0
  vsyncDispatcher->RemoveChildRefreshTimer(testVsyncObserver);
189
0
  testVsyncObserver->ResetVsyncNotification();
190
0
  testVsyncObserver->WaitForVsyncNotification();
191
0
  ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification());
192
0
193
0
  vsyncDispatcher = nullptr;
194
0
  testVsyncObserver = nullptr;
195
0
}
196
197
// Test that we can read the vsync rate
198
TEST_F(VsyncTester, VsyncSourceHasVsyncRate)
199
0
{
200
0
  VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
201
0
  TimeDuration vsyncRate = globalDisplay.GetVsyncRate();
202
0
  ASSERT_NE(vsyncRate, TimeDuration::Forever());
203
0
  ASSERT_GT(vsyncRate.ToMilliseconds(), 0);
204
0
}