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 cc::FrameRateControllerClient {
16 FakeFrameRateControllerClient() { Reset(); }
18 void Reset() { began_frame_ = false; }
19 bool BeganFrame() const { return began_frame_; }
21 virtual void FrameRateControllerTick(
22 bool throttled, const BeginFrameArgs& args) OVERRIDE {
23 began_frame_ = !throttled;
30 TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) {
31 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
32 new base::TestSimpleTaskRunner;
33 FakeFrameRateControllerClient client;
34 base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
35 base::Time::kMicrosecondsPerSecond / 60);
36 scoped_refptr<FakeDelayBasedTimeSource> time_source =
37 FakeDelayBasedTimeSource::Create(interval, task_runner.get());
38 FrameRateController controller(time_source);
40 controller.SetClient(&client);
41 controller.SetActive(true);
43 base::TimeTicks elapsed; // Muck around with time a bit
45 // Trigger one frame, make sure the BeginFrame callback is called
46 elapsed += task_runner->NextPendingTaskDelay();
47 time_source->SetNow(elapsed);
48 task_runner->RunPendingTasks();
49 EXPECT_TRUE(client.BeganFrame());
52 // Tell the controller we drew
53 controller.DidSwapBuffers();
55 // Tell the controller the frame ended 5ms later
56 time_source->SetNow(time_source->Now() +
57 base::TimeDelta::FromMilliseconds(5));
58 controller.DidSwapBuffersComplete();
60 // Trigger another frame, make sure BeginFrame runs again
61 elapsed += task_runner->NextPendingTaskDelay();
62 // Sanity check that previous code didn't move time backward.
63 EXPECT_GE(elapsed, time_source->Now());
64 time_source->SetNow(elapsed);
65 task_runner->RunPendingTasks();
66 EXPECT_TRUE(client.BeganFrame());
69 TEST(FrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight) {
70 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
71 new base::TestSimpleTaskRunner;
72 FakeFrameRateControllerClient client;
73 base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
74 base::Time::kMicrosecondsPerSecond / 60);
75 scoped_refptr<FakeDelayBasedTimeSource> time_source =
76 FakeDelayBasedTimeSource::Create(interval, task_runner.get());
77 FrameRateController controller(time_source);
79 controller.SetClient(&client);
80 controller.SetActive(true);
81 controller.SetMaxSwapsPending(2);
83 base::TimeTicks elapsed; // Muck around with time a bit
85 // Trigger one frame, make sure the BeginFrame callback is called
86 elapsed += task_runner->NextPendingTaskDelay();
87 time_source->SetNow(elapsed);
88 task_runner->RunPendingTasks();
89 EXPECT_TRUE(client.BeganFrame());
92 // Tell the controller we drew
93 controller.DidSwapBuffers();
95 // Trigger another frame, make sure BeginFrame callback runs again
96 elapsed += task_runner->NextPendingTaskDelay();
97 // Sanity check that previous code didn't move time backward.
98 EXPECT_GE(elapsed, time_source->Now());
99 time_source->SetNow(elapsed);
100 task_runner->RunPendingTasks();
101 EXPECT_TRUE(client.BeganFrame());
104 // Tell the controller we drew, again.
105 controller.DidSwapBuffers();
107 // Trigger another frame. Since two frames are pending, we should not draw.
108 elapsed += task_runner->NextPendingTaskDelay();
109 // Sanity check that previous code didn't move time backward.
110 EXPECT_GE(elapsed, time_source->Now());
111 time_source->SetNow(elapsed);
112 task_runner->RunPendingTasks();
113 EXPECT_FALSE(client.BeganFrame());
115 // Tell the controller the first frame ended 5ms later
116 time_source->SetNow(time_source->Now() +
117 base::TimeDelta::FromMilliseconds(5));
118 controller.DidSwapBuffersComplete();
120 // Tick should not have been called
121 EXPECT_FALSE(client.BeganFrame());
123 // Trigger yet another frame. Since one frames is pending, another
124 // BeginFrame callback should run.
125 elapsed += task_runner->NextPendingTaskDelay();
126 // Sanity check that previous code didn't move time backward.
127 EXPECT_GE(elapsed, time_source->Now());
128 time_source->SetNow(elapsed);
129 task_runner->RunPendingTasks();
130 EXPECT_TRUE(client.BeganFrame());
133 TEST(FrameRateControllerTest, TestFrameThrottling_Unthrottled) {
134 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
135 new base::TestSimpleTaskRunner;
136 FakeFrameRateControllerClient client;
137 FrameRateController controller(task_runner.get());
139 controller.SetClient(&client);
140 controller.SetMaxSwapsPending(2);
142 // SetActive triggers 1st frame, make sure the BeginFrame callback
144 controller.SetActive(true);
145 task_runner->RunPendingTasks();
146 EXPECT_TRUE(client.BeganFrame());
149 // Even if we don't call DidSwapBuffers, FrameRateController should
150 // still attempt to tick multiple times until it does result in
152 task_runner->RunPendingTasks();
153 EXPECT_TRUE(client.BeganFrame());
156 task_runner->RunPendingTasks();
157 EXPECT_TRUE(client.BeganFrame());
160 // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is
162 controller.DidSwapBuffers();
163 task_runner->RunPendingTasks();
164 EXPECT_TRUE(client.BeganFrame());
167 // DidSwapBuffers triggers 3rd frame (> max_frames_pending),
168 // make sure the BeginFrame callback is NOT called
169 controller.DidSwapBuffers();
170 task_runner->RunPendingTasks();
171 EXPECT_FALSE(client.BeganFrame());
174 // Make sure there is no pending task since we can't do anything until we
175 // receive a DidSwapBuffersComplete anyway.
176 EXPECT_FALSE(task_runner->HasPendingTask());
178 // DidSwapBuffersComplete triggers a frame, make sure the BeginFrame
179 // callback is called
180 controller.DidSwapBuffersComplete();
181 task_runner->RunPendingTasks();
182 EXPECT_TRUE(client.BeganFrame());