| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/scheduler/frame_rate_controller.h" | 5 #include "cc/scheduler/frame_rate_controller.h" |
| 6 | 6 |
| 7 #include "base/test/test_simple_task_runner.h" | 7 #include "base/test/test_simple_task_runner.h" |
| 8 #include "cc/test/scheduler_test_common.h" | 8 #include "cc/test/scheduler_test_common.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 namespace cc { | 11 namespace cc { |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 class FakeFrameRateControllerClient : public FrameRateControllerClient { | 14 class FakeBeginFrameSourceClient : public BeginFrameSourceClient { |
| 15 public: | 15 public: |
| 16 FakeFrameRateControllerClient() { Reset(); } | 16 FakeBeginFrameSourceClient() { Reset(); } |
| 17 | 17 |
| 18 void Reset() { frame_count_ = 0; } | 18 void Reset() { frame_count_ = 0; } |
| 19 bool BeganFrame() const { return frame_count_ > 0; } | 19 bool BeganFrame() const { return frame_count_ > 0; } |
| 20 int frame_count() const { return frame_count_; } | 20 int frame_count() const { return frame_count_; } |
| 21 | 21 |
| 22 virtual void FrameRateControllerTick( | 22 virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE { |
| 23 bool throttled, const BeginFrameArgs& args) OVERRIDE { | 23 frame_count_ += 1; |
| 24 frame_count_ += throttled ? 0 : 1; | |
| 25 } | 24 } |
| 26 | 25 |
| 27 protected: | 26 protected: |
| 28 int frame_count_; | 27 int frame_count_; |
| 29 }; | 28 }; |
| 30 | 29 |
| 31 TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) { | 30 TEST(BeginFrameSourceTest, TestFrameThrottling_ImmediateAck) { |
| 32 scoped_refptr<base::TestSimpleTaskRunner> task_runner = | 31 scoped_refptr<base::TestSimpleTaskRunner> task_runner = |
| 33 new base::TestSimpleTaskRunner; | 32 new base::TestSimpleTaskRunner; |
| 34 FakeFrameRateControllerClient client; | 33 FakeBeginFrameSourceClient client; |
| 35 base::TimeDelta interval = base::TimeDelta::FromMicroseconds( | 34 base::TimeDelta interval = base::TimeDelta::FromMicroseconds( |
| 36 base::Time::kMicrosecondsPerSecond / 60); | 35 base::Time::kMicrosecondsPerSecond / 60); |
| 37 scoped_refptr<FakeDelayBasedTimeSource> time_source = | 36 scoped_refptr<FakeDelayBasedTimeSource> time_source = |
| 38 FakeDelayBasedTimeSource::Create(interval, task_runner.get()); | 37 FakeDelayBasedTimeSource::Create(interval, task_runner.get()); |
| 39 FrameRateController controller(time_source); | 38 BeginFrameSource controller(time_source); |
| 40 | 39 |
| 41 controller.SetClient(&client); | 40 controller.SetClient(&client); |
| 42 controller.SetActive(true); | 41 controller.SetActive(true); |
| 43 | 42 |
| 44 base::TimeTicks elapsed; // Muck around with time a bit | 43 base::TimeTicks elapsed; // Muck around with time a bit |
| 45 | 44 |
| 46 // Trigger one frame, make sure the BeginFrame callback is called | 45 // Trigger one frame, make sure the BeginFrame callback is called |
| 47 elapsed += task_runner->NextPendingTaskDelay(); | 46 elapsed += task_runner->NextPendingTaskDelay(); |
| 48 time_source->SetNow(elapsed); | 47 time_source->SetNow(elapsed); |
| 49 task_runner->RunPendingTasks(); | 48 task_runner->RunPendingTasks(); |
| 50 EXPECT_TRUE(client.BeganFrame()); | 49 EXPECT_TRUE(client.BeganFrame()); |
| 51 client.Reset(); | 50 client.Reset(); |
| 52 | 51 |
| 53 // Tell the controller we drew | |
| 54 controller.DidSwapBuffers(); | |
| 55 | |
| 56 // Tell the controller the frame ended 5ms later | |
| 57 time_source->SetNow(time_source->Now() + | |
| 58 base::TimeDelta::FromMilliseconds(5)); | |
| 59 controller.DidSwapBuffersComplete(); | |
| 60 | |
| 61 // Trigger another frame, make sure BeginFrame runs again | 52 // Trigger another frame, make sure BeginFrame runs again |
| 62 elapsed += task_runner->NextPendingTaskDelay(); | 53 elapsed += task_runner->NextPendingTaskDelay(); |
| 63 // Sanity check that previous code didn't move time backward. | 54 // Sanity check that previous code didn't move time backward. |
| 64 EXPECT_GE(elapsed, time_source->Now()); | 55 EXPECT_GE(elapsed, time_source->Now()); |
| 65 time_source->SetNow(elapsed); | 56 time_source->SetNow(elapsed); |
| 66 task_runner->RunPendingTasks(); | 57 task_runner->RunPendingTasks(); |
| 67 EXPECT_TRUE(client.BeganFrame()); | 58 EXPECT_TRUE(client.BeganFrame()); |
| 68 } | 59 } |
| 69 | 60 |
| 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); | |
| 79 | |
| 80 controller.SetClient(&client); | |
| 81 controller.SetActive(true); | |
| 82 controller.SetMaxSwapsPending(2); | |
| 83 | |
| 84 base::TimeTicks elapsed; // Muck around with time a bit | |
| 85 | |
| 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()); | |
| 91 client.Reset(); | |
| 92 | |
| 93 // Tell the controller we drew | |
| 94 controller.DidSwapBuffers(); | |
| 95 | |
| 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()); | |
| 103 client.Reset(); | |
| 104 | |
| 105 // Tell the controller we drew, again. | |
| 106 controller.DidSwapBuffers(); | |
| 107 | |
| 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()); | |
| 115 | |
| 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(); | |
| 120 | |
| 121 // Tick should not have been called | |
| 122 EXPECT_FALSE(client.BeganFrame()); | |
| 123 | |
| 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()); | |
| 132 } | |
| 133 | |
| 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()); | |
| 139 | |
| 140 controller.SetClient(&client); | |
| 141 controller.SetMaxSwapsPending(2); | |
| 142 | |
| 143 // SetActive triggers 1st frame, make sure the BeginFrame callback | |
| 144 // is called | |
| 145 controller.SetActive(true); | |
| 146 task_runner->RunPendingTasks(); | |
| 147 EXPECT_TRUE(client.BeganFrame()); | |
| 148 client.Reset(); | |
| 149 | |
| 150 // Even if we don't call DidSwapBuffers, FrameRateController should | |
| 151 // still attempt to tick multiple times until it does result in | |
| 152 // a DidSwapBuffers. | |
| 153 task_runner->RunPendingTasks(); | |
| 154 EXPECT_TRUE(client.BeganFrame()); | |
| 155 client.Reset(); | |
| 156 | |
| 157 task_runner->RunPendingTasks(); | |
| 158 EXPECT_TRUE(client.BeganFrame()); | |
| 159 client.Reset(); | |
| 160 | |
| 161 // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is | |
| 162 // called | |
| 163 controller.DidSwapBuffers(); | |
| 164 task_runner->RunPendingTasks(); | |
| 165 EXPECT_TRUE(client.BeganFrame()); | |
| 166 client.Reset(); | |
| 167 | |
| 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()); | |
| 173 client.Reset(); | |
| 174 | |
| 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()); | |
| 178 | |
| 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()); | |
| 184 } | |
| 185 | |
| 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); | |
| 192 | |
| 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()); | |
| 198 client.Reset(); | |
| 199 EXPECT_TRUE(task_runner->HasPendingTask()); | |
| 200 | |
| 201 // Simulate a frame swap. This shouldn't queue a second tick task. | |
| 202 controller.DidSwapBuffers(); | |
| 203 controller.DidSwapBuffersComplete(); | |
| 204 | |
| 205 // The client should only be ticked once. | |
| 206 task_runner->RunPendingTasks(); | |
| 207 EXPECT_EQ(1, client.frame_count()); | |
| 208 } | |
| 209 | |
| 210 } // namespace | 61 } // namespace |
| 211 } // namespace cc | 62 } // namespace cc |
| OLD | NEW |