1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/frame_rate_controller.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "cc/test/scheduler_test_common.h"
9 #include "testing/gtest/include/gtest/gtest.h"
14 class FakeFrameRateControllerClient
: public FrameRateControllerClient
{
16 FakeFrameRateControllerClient() { Reset(); }
18 void Reset() { frame_count_
= 0; }
19 bool BeganFrame() const { return frame_count_
> 0; }
20 int frame_count() const { return frame_count_
; }
22 virtual void FrameRateControllerTick(
23 bool throttled
, const BeginFrameArgs
& args
) OVERRIDE
{
24 frame_count_
+= throttled
? 0 : 1;
31 TEST(FrameRateControllerTest
, TestFrameThrottling_ImmediateAck
) {
32 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
33 new base::TestSimpleTaskRunner
;
34 FakeFrameRateControllerClient client
;
35 base::TimeDelta interval
= base::TimeDelta::FromMicroseconds(
36 base::Time::kMicrosecondsPerSecond
/ 60);
37 scoped_refptr
<FakeDelayBasedTimeSource
> time_source
=
38 FakeDelayBasedTimeSource::Create(interval
, task_runner
.get());
39 FrameRateController
controller(time_source
);
41 controller
.SetClient(&client
);
42 controller
.SetActive(true);
44 base::TimeTicks elapsed
; // Muck around with time a bit
46 // Trigger one frame, make sure the BeginFrame callback is called
47 elapsed
+= task_runner
->NextPendingTaskDelay();
48 time_source
->SetNow(elapsed
);
49 task_runner
->RunPendingTasks();
50 EXPECT_TRUE(client
.BeganFrame());
53 // Tell the controller we drew
54 controller
.DidSwapBuffers();
56 // Tell the controller the frame ended 5ms later
57 time_source
->SetNow(time_source
->Now() +
58 base::TimeDelta::FromMilliseconds(5));
59 controller
.DidSwapBuffersComplete();
61 // Trigger another frame, make sure BeginFrame runs again
62 elapsed
+= task_runner
->NextPendingTaskDelay();
63 // Sanity check that previous code didn't move time backward.
64 EXPECT_GE(elapsed
, time_source
->Now());
65 time_source
->SetNow(elapsed
);
66 task_runner
->RunPendingTasks();
67 EXPECT_TRUE(client
.BeganFrame());
70 TEST(FrameRateControllerTest
, TestFrameThrottling_TwoFramesInFlight
) {
71 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
72 new base::TestSimpleTaskRunner
;
73 FakeFrameRateControllerClient client
;
74 base::TimeDelta interval
= base::TimeDelta::FromMicroseconds(
75 base::Time::kMicrosecondsPerSecond
/ 60);
76 scoped_refptr
<FakeDelayBasedTimeSource
> time_source
=
77 FakeDelayBasedTimeSource::Create(interval
, task_runner
.get());
78 FrameRateController
controller(time_source
);
80 controller
.SetClient(&client
);
81 controller
.SetActive(true);
82 controller
.SetMaxSwapsPending(2);
84 base::TimeTicks elapsed
; // Muck around with time a bit
86 // Trigger one frame, make sure the BeginFrame callback is called
87 elapsed
+= task_runner
->NextPendingTaskDelay();
88 time_source
->SetNow(elapsed
);
89 task_runner
->RunPendingTasks();
90 EXPECT_TRUE(client
.BeganFrame());
93 // Tell the controller we drew
94 controller
.DidSwapBuffers();
96 // Trigger another frame, make sure BeginFrame callback runs again
97 elapsed
+= task_runner
->NextPendingTaskDelay();
98 // Sanity check that previous code didn't move time backward.
99 EXPECT_GE(elapsed
, time_source
->Now());
100 time_source
->SetNow(elapsed
);
101 task_runner
->RunPendingTasks();
102 EXPECT_TRUE(client
.BeganFrame());
105 // Tell the controller we drew, again.
106 controller
.DidSwapBuffers();
108 // Trigger another frame. Since two frames are pending, we should not draw.
109 elapsed
+= task_runner
->NextPendingTaskDelay();
110 // Sanity check that previous code didn't move time backward.
111 EXPECT_GE(elapsed
, time_source
->Now());
112 time_source
->SetNow(elapsed
);
113 task_runner
->RunPendingTasks();
114 EXPECT_FALSE(client
.BeganFrame());
116 // Tell the controller the first frame ended 5ms later
117 time_source
->SetNow(time_source
->Now() +
118 base::TimeDelta::FromMilliseconds(5));
119 controller
.DidSwapBuffersComplete();
121 // Tick should not have been called
122 EXPECT_FALSE(client
.BeganFrame());
124 // Trigger yet another frame. Since one frames is pending, another
125 // BeginFrame callback should run.
126 elapsed
+= task_runner
->NextPendingTaskDelay();
127 // Sanity check that previous code didn't move time backward.
128 EXPECT_GE(elapsed
, time_source
->Now());
129 time_source
->SetNow(elapsed
);
130 task_runner
->RunPendingTasks();
131 EXPECT_TRUE(client
.BeganFrame());
134 TEST(FrameRateControllerTest
, TestFrameThrottling_Unthrottled
) {
135 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
136 new base::TestSimpleTaskRunner
;
137 FakeFrameRateControllerClient client
;
138 FrameRateController
controller(task_runner
.get());
140 controller
.SetClient(&client
);
141 controller
.SetMaxSwapsPending(2);
143 // SetActive triggers 1st frame, make sure the BeginFrame callback
145 controller
.SetActive(true);
146 task_runner
->RunPendingTasks();
147 EXPECT_TRUE(client
.BeganFrame());
150 // Even if we don't call DidSwapBuffers, FrameRateController should
151 // still attempt to tick multiple times until it does result in
153 task_runner
->RunPendingTasks();
154 EXPECT_TRUE(client
.BeganFrame());
157 task_runner
->RunPendingTasks();
158 EXPECT_TRUE(client
.BeganFrame());
161 // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is
163 controller
.DidSwapBuffers();
164 task_runner
->RunPendingTasks();
165 EXPECT_TRUE(client
.BeganFrame());
168 // DidSwapBuffers triggers 3rd frame (> max_frames_pending),
169 // make sure the BeginFrame callback is NOT called
170 controller
.DidSwapBuffers();
171 task_runner
->RunPendingTasks();
172 EXPECT_FALSE(client
.BeganFrame());
175 // Make sure there is no pending task since we can't do anything until we
176 // receive a DidSwapBuffersComplete anyway.
177 EXPECT_FALSE(task_runner
->HasPendingTask());
179 // DidSwapBuffersComplete triggers a frame, make sure the BeginFrame
180 // callback is called
181 controller
.DidSwapBuffersComplete();
182 task_runner
->RunPendingTasks();
183 EXPECT_TRUE(client
.BeganFrame());
186 TEST(FrameRateControllerTest
, TestFrameThrottling_NoDoubleTicking
) {
187 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
188 new base::TestSimpleTaskRunner
;
189 FakeFrameRateControllerClient client
;
190 FrameRateController
controller(task_runner
.get());
191 controller
.SetClient(&client
);
193 // SetActive triggers 1st frame and queues another tick task since the time
194 // source isn't throttling.
195 controller
.SetActive(true);
196 task_runner
->RunPendingTasks();
197 EXPECT_TRUE(client
.BeganFrame());
199 EXPECT_TRUE(task_runner
->HasPendingTask());
201 // Simulate a frame swap. This shouldn't queue a second tick task.
202 controller
.DidSwapBuffers();
203 controller
.DidSwapBuffersComplete();
205 // The client should only be ticked once.
206 task_runner
->RunPendingTasks();
207 EXPECT_EQ(1, client
.frame_count());