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 "cc/test/scheduler_test_common.h"
8 #include "testing/gtest/include/gtest/gtest.h"
13 class FakeFrameRateControllerClient
: public cc::FrameRateControllerClient
{
15 FakeFrameRateControllerClient() { Reset(); }
17 void Reset() { began_frame_
= false; }
18 bool BeganFrame() const { return began_frame_
; }
20 virtual void BeginFrame(bool throttled
) OVERRIDE
{
21 began_frame_
= !throttled
;
28 TEST(FrameRateControllerTest
, TestFrameThrottling_ImmediateAck
) {
30 FakeFrameRateControllerClient client
;
31 base::TimeDelta interval
= base::TimeDelta::FromMicroseconds(
32 base::Time::kMicrosecondsPerSecond
/ 60);
33 scoped_refptr
<FakeDelayBasedTimeSource
> time_source
=
34 FakeDelayBasedTimeSource::Create(interval
, &thread
);
35 FrameRateController
controller(time_source
);
37 controller
.SetClient(&client
);
38 controller
.SetActive(true);
40 base::TimeTicks elapsed
; // Muck around with time a bit
42 // Trigger one frame, make sure the BeginFrame callback is called
43 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
44 time_source
->SetNow(elapsed
);
45 thread
.RunPendingTask();
46 EXPECT_TRUE(client
.BeganFrame());
49 // Tell the controller we drew
50 controller
.DidSwapBuffers();
52 // Tell the controller the frame ended 5ms later
53 time_source
->SetNow(time_source
->Now() +
54 base::TimeDelta::FromMilliseconds(5));
55 controller
.DidSwapBuffersComplete();
57 // Trigger another frame, make sure BeginFrame runs again
58 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
59 // Sanity check that previous code didn't move time backward.
60 EXPECT_GE(elapsed
, time_source
->Now());
61 time_source
->SetNow(elapsed
);
62 thread
.RunPendingTask();
63 EXPECT_TRUE(client
.BeganFrame());
66 TEST(FrameRateControllerTest
, TestFrameThrottling_TwoFramesInFlight
) {
68 FakeFrameRateControllerClient client
;
69 base::TimeDelta interval
= base::TimeDelta::FromMicroseconds(
70 base::Time::kMicrosecondsPerSecond
/ 60);
71 scoped_refptr
<FakeDelayBasedTimeSource
> time_source
=
72 FakeDelayBasedTimeSource::Create(interval
, &thread
);
73 FrameRateController
controller(time_source
);
75 controller
.SetClient(&client
);
76 controller
.SetActive(true);
77 controller
.SetMaxFramesPending(2);
79 base::TimeTicks elapsed
; // Muck around with time a bit
81 // Trigger one frame, make sure the BeginFrame callback is called
82 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
83 time_source
->SetNow(elapsed
);
84 thread
.RunPendingTask();
85 EXPECT_TRUE(client
.BeganFrame());
88 // Tell the controller we drew
89 controller
.DidSwapBuffers();
91 // Trigger another frame, make sure BeginFrame callback runs again
92 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
93 // Sanity check that previous code didn't move time backward.
94 EXPECT_GE(elapsed
, time_source
->Now());
95 time_source
->SetNow(elapsed
);
96 thread
.RunPendingTask();
97 EXPECT_TRUE(client
.BeganFrame());
100 // Tell the controller we drew, again.
101 controller
.DidSwapBuffers();
103 // Trigger another frame. Since two frames are pending, we should not draw.
104 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
105 // Sanity check that previous code didn't move time backward.
106 EXPECT_GE(elapsed
, time_source
->Now());
107 time_source
->SetNow(elapsed
);
108 thread
.RunPendingTask();
109 EXPECT_FALSE(client
.BeganFrame());
111 // Tell the controller the first frame ended 5ms later
112 time_source
->SetNow(time_source
->Now() +
113 base::TimeDelta::FromMilliseconds(5));
114 controller
.DidSwapBuffersComplete();
116 // Tick should not have been called
117 EXPECT_FALSE(client
.BeganFrame());
119 // Trigger yet another frame. Since one frames is pending, another
120 // BeginFrame callback should run.
121 elapsed
+= base::TimeDelta::FromMilliseconds(thread
.PendingDelayMs());
122 // Sanity check that previous code didn't move time backward.
123 EXPECT_GE(elapsed
, time_source
->Now());
124 time_source
->SetNow(elapsed
);
125 thread
.RunPendingTask();
126 EXPECT_TRUE(client
.BeganFrame());
129 TEST(FrameRateControllerTest
, TestFrameThrottling_Unthrottled
) {
131 FakeFrameRateControllerClient client
;
132 FrameRateController
controller(&thread
);
134 controller
.SetClient(&client
);
135 controller
.SetMaxFramesPending(2);
137 // SetActive triggers 1st frame, make sure the BeginFrame callback
139 controller
.SetActive(true);
140 thread
.RunPendingTask();
141 EXPECT_TRUE(client
.BeganFrame());
144 // Even if we don't call DidSwapBuffers, FrameRateController should
145 // still attempt to tick multiple times until it does result in
147 thread
.RunPendingTask();
148 EXPECT_TRUE(client
.BeganFrame());
151 thread
.RunPendingTask();
152 EXPECT_TRUE(client
.BeganFrame());
155 // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is
157 controller
.DidSwapBuffers();
158 thread
.RunPendingTask();
159 EXPECT_TRUE(client
.BeganFrame());
162 // DidSwapBuffers triggers 3rd frame (> max_frames_pending),
163 // make sure the BeginFrame callback is NOT called
164 controller
.DidSwapBuffers();
165 thread
.RunPendingTask();
166 EXPECT_FALSE(client
.BeganFrame());
169 // Make sure there is no pending task since we can't do anything until we
170 // receive a DidSwapBuffersComplete anyway.
171 EXPECT_FALSE(thread
.HasPendingTask());
173 // DidSwapBuffersComplete triggers a frame, make sure the BeginFrame
174 // callback is called
175 controller
.DidSwapBuffersComplete();
176 thread
.RunPendingTask();
177 EXPECT_TRUE(client
.BeganFrame());