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/scheduler.h" | 5 #include "cc/scheduler/scheduler.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/scoped_vector.h" | 11 #include "base/memory/scoped_vector.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/power_monitor/power_monitor.h" | |
14 #include "base/power_monitor/power_monitor_source.h" | |
15 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
16 #include "base/time/time.h" | 14 #include "base/time/time.h" |
17 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
18 #include "cc/test/begin_frame_args_test.h" | 16 #include "cc/test/begin_frame_args_test.h" |
19 #include "cc/test/ordered_simple_task_runner.h" | 17 #include "cc/test/ordered_simple_task_runner.h" |
20 #include "cc/test/scheduler_test_common.h" | 18 #include "cc/test/scheduler_test_common.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
23 | 21 |
24 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ | 22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 int num_draws_; | 189 int num_draws_; |
192 bool log_anticipated_draw_time_change_; | 190 bool log_anticipated_draw_time_change_; |
193 bool begin_frame_is_sent_to_children_; | 191 bool begin_frame_is_sent_to_children_; |
194 base::TimeTicks posted_begin_impl_frame_deadline_; | 192 base::TimeTicks posted_begin_impl_frame_deadline_; |
195 std::vector<const char*> actions_; | 193 std::vector<const char*> actions_; |
196 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>> | 194 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>> |
197 states_; | 195 states_; |
198 TestScheduler* scheduler_; | 196 TestScheduler* scheduler_; |
199 }; | 197 }; |
200 | 198 |
201 class FakePowerMonitorSource : public base::PowerMonitorSource { | |
202 public: | |
203 FakePowerMonitorSource() {} | |
204 ~FakePowerMonitorSource() override {} | |
205 void GeneratePowerStateEvent(bool on_battery_power) { | |
206 on_battery_power_impl_ = on_battery_power; | |
207 ProcessPowerEvent(POWER_STATE_EVENT); | |
208 base::MessageLoop::current()->RunUntilIdle(); | |
209 } | |
210 bool IsOnBatteryPowerImpl() override { return on_battery_power_impl_; } | |
211 | |
212 private: | |
213 bool on_battery_power_impl_; | |
214 }; | |
215 | |
216 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { | 199 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { |
217 public: | 200 public: |
218 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client) | 201 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client) |
219 : client_(client) {} | 202 : client_(client) {} |
220 ~FakeExternalBeginFrameSource() override {} | 203 ~FakeExternalBeginFrameSource() override {} |
221 | 204 |
222 void OnNeedsBeginFramesChange(bool needs_begin_frames) override { | 205 void OnNeedsBeginFramesChange(bool needs_begin_frames) override { |
223 if (needs_begin_frames) { | 206 if (needs_begin_frames) { |
224 client_->PushAction("SetNeedsBeginFrames(true)"); | 207 client_->PushAction("SetNeedsBeginFrames(true)"); |
225 } else { | 208 } else { |
226 client_->PushAction("SetNeedsBeginFrames(false)"); | 209 client_->PushAction("SetNeedsBeginFrames(false)"); |
227 } | 210 } |
228 } | 211 } |
229 | 212 |
230 void TestOnBeginFrame(const BeginFrameArgs& args) { | 213 void TestOnBeginFrame(const BeginFrameArgs& args) { |
231 return CallOnBeginFrame(args); | 214 return CallOnBeginFrame(args); |
232 } | 215 } |
233 | 216 |
234 private: | 217 private: |
235 FakeSchedulerClient* client_; | 218 FakeSchedulerClient* client_; |
236 }; | 219 }; |
237 | 220 |
238 class SchedulerTest : public testing::Test { | 221 class SchedulerTest : public testing::Test { |
239 public: | 222 public: |
240 SchedulerTest() | 223 SchedulerTest() |
241 : now_src_(TestNowSource::Create()), | 224 : now_src_(TestNowSource::Create()), |
242 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), | 225 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), |
243 fake_external_begin_frame_source_(nullptr), | 226 fake_external_begin_frame_source_(nullptr) { |
244 fake_power_monitor_source_(new FakePowerMonitorSource), | |
245 power_monitor_(make_scoped_ptr<base::PowerMonitorSource>( | |
246 fake_power_monitor_source_)) { | |
247 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval() | 227 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval() |
248 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100)); | 228 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100)); |
249 // Fail if we need to run 100 tasks in a row. | 229 // Fail if we need to run 100 tasks in a row. |
250 task_runner_->SetRunTaskLimit(100); | 230 task_runner_->SetRunTaskLimit(100); |
251 } | 231 } |
252 | 232 |
253 ~SchedulerTest() override {} | 233 ~SchedulerTest() override {} |
254 | 234 |
255 protected: | 235 protected: |
256 TestScheduler* CreateScheduler() { | 236 TestScheduler* CreateScheduler() { |
257 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source; | 237 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source; |
258 if (scheduler_settings_.use_external_begin_frame_source) { | 238 if (scheduler_settings_.use_external_begin_frame_source) { |
259 fake_external_begin_frame_source.reset( | 239 fake_external_begin_frame_source.reset( |
260 new FakeExternalBeginFrameSource(client_.get())); | 240 new FakeExternalBeginFrameSource(client_.get())); |
261 fake_external_begin_frame_source_ = | 241 fake_external_begin_frame_source_ = |
262 fake_external_begin_frame_source.get(); | 242 fake_external_begin_frame_source.get(); |
263 } | 243 } |
264 scheduler_ = TestScheduler::Create( | 244 scheduler_ = TestScheduler::Create(now_src_, client_.get(), |
265 now_src_, client_.get(), scheduler_settings_, 0, task_runner_, | 245 scheduler_settings_, 0, task_runner_, |
266 &power_monitor_, fake_external_begin_frame_source.Pass()); | 246 fake_external_begin_frame_source.Pass()); |
267 DCHECK(scheduler_); | 247 DCHECK(scheduler_); |
268 client_->set_scheduler(scheduler_.get()); | 248 client_->set_scheduler(scheduler_.get()); |
269 return scheduler_.get(); | 249 return scheduler_.get(); |
270 } | 250 } |
271 | 251 |
272 void CreateSchedulerAndInitSurface() { | 252 void CreateSchedulerAndInitSurface() { |
273 CreateScheduler(); | 253 CreateScheduler(); |
274 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); | 254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); |
275 } | 255 } |
276 | 256 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 359 |
380 void SendNextBeginFrame() { | 360 void SendNextBeginFrame() { |
381 DCHECK(scheduler_->settings().use_external_begin_frame_source); | 361 DCHECK(scheduler_->settings().use_external_begin_frame_source); |
382 // Creep the time forward so that any BeginFrameArgs is not equal to the | 362 // Creep the time forward so that any BeginFrameArgs is not equal to the |
383 // last one otherwise we violate the BeginFrameSource contract. | 363 // last one otherwise we violate the BeginFrameSource contract. |
384 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval()); | 364 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval()); |
385 fake_external_begin_frame_source_->TestOnBeginFrame( | 365 fake_external_begin_frame_source_->TestOnBeginFrame( |
386 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src())); | 366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src())); |
387 } | 367 } |
388 | 368 |
389 base::PowerMonitor* PowerMonitor() { return &power_monitor_; } | |
390 FakePowerMonitorSource* PowerMonitorSource() { | |
391 return fake_power_monitor_source_; | |
392 } | |
393 | |
394 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { | 369 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { |
395 return fake_external_begin_frame_source_; | 370 return fake_external_begin_frame_source_; |
396 } | 371 } |
397 | 372 |
398 void MainFrameInHighLatencyMode( | 373 void MainFrameInHighLatencyMode( |
399 int64 begin_main_frame_to_commit_estimate_in_ms, | 374 int64 begin_main_frame_to_commit_estimate_in_ms, |
400 int64 commit_to_activate_estimate_in_ms, | 375 int64 commit_to_activate_estimate_in_ms, |
401 bool impl_latency_takes_priority, | 376 bool impl_latency_takes_priority, |
402 bool should_send_begin_main_frame); | 377 bool should_send_begin_main_frame); |
403 void BeginFramesNotFromClient(bool use_external_begin_frame_source, | 378 void BeginFramesNotFromClient(bool use_external_begin_frame_source, |
404 bool throttle_frame_production); | 379 bool throttle_frame_production); |
405 void BeginFramesNotFromClient_SwapThrottled( | 380 void BeginFramesNotFromClient_SwapThrottled( |
406 bool use_external_begin_frame_source, | 381 bool use_external_begin_frame_source, |
407 bool throttle_frame_production); | 382 bool throttle_frame_production); |
408 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( | 383 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency( |
409 bool impl_side_painting); | 384 bool impl_side_painting); |
410 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting); | 385 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting); |
411 | 386 |
412 scoped_refptr<TestNowSource> now_src_; | 387 scoped_refptr<TestNowSource> now_src_; |
413 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; | 388 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
414 FakeExternalBeginFrameSource* fake_external_begin_frame_source_; | 389 FakeExternalBeginFrameSource* fake_external_begin_frame_source_; |
415 FakePowerMonitorSource* fake_power_monitor_source_; | |
416 base::PowerMonitor power_monitor_; | |
417 SchedulerSettings scheduler_settings_; | 390 SchedulerSettings scheduler_settings_; |
418 scoped_ptr<FakeSchedulerClient> client_; | 391 scoped_ptr<FakeSchedulerClient> client_; |
419 scoped_ptr<TestScheduler> scheduler_; | 392 scoped_ptr<TestScheduler> scheduler_; |
420 }; | 393 }; |
421 | 394 |
422 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { | 395 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { |
423 scheduler_settings_.use_external_begin_frame_source = true; | 396 scheduler_settings_.use_external_begin_frame_source = true; |
424 SetUpScheduler(false); | 397 SetUpScheduler(false); |
425 scheduler_->SetCanStart(); | 398 scheduler_->SetCanStart(); |
426 scheduler_->SetVisible(true); | 399 scheduler_->SetVisible(true); |
(...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 scheduler_->NotifyReadyToCommit(); | 2085 scheduler_->NotifyReadyToCommit(); |
2113 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); | 2086 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); |
2114 | 2087 |
2115 client_->Reset(); | 2088 client_->Reset(); |
2116 scheduler_->SetVisible(false); | 2089 scheduler_->SetVisible(false); |
2117 // Sync tree should be forced to activate. | 2090 // Sync tree should be forced to activate. |
2118 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | 2091 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); |
2119 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); | 2092 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); |
2120 } | 2093 } |
2121 | 2094 |
2122 TEST_F(SchedulerTest, SchedulerPowerMonitoring) { | |
2123 scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true; | |
2124 SetUpScheduler(true); | |
2125 | |
2126 base::TimeTicks before_deadline, after_deadline; | |
2127 | |
2128 scheduler_->SetNeedsCommit(); | |
2129 scheduler_->SetNeedsRedraw(); | |
2130 client_->Reset(); | |
2131 | |
2132 // On non-battery power | |
2133 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower()); | |
2134 | |
2135 EXPECT_SCOPED(AdvanceFrame()); | |
2136 client_->Reset(); | |
2137 | |
2138 before_deadline = now_src()->Now(); | |
2139 EXPECT_TRUE( | |
2140 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true))); | |
2141 after_deadline = now_src()->Now(); | |
2142 | |
2143 // We post a non-zero deadline task when not on battery | |
2144 EXPECT_LT(before_deadline, after_deadline); | |
2145 | |
2146 // Switch to battery power | |
2147 PowerMonitorSource()->GeneratePowerStateEvent(true); | |
2148 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower()); | |
2149 | |
2150 EXPECT_SCOPED(AdvanceFrame()); | |
2151 scheduler_->SetNeedsCommit(); | |
2152 scheduler_->SetNeedsRedraw(); | |
2153 client_->Reset(); | |
2154 | |
2155 before_deadline = now_src()->Now(); | |
2156 EXPECT_TRUE( | |
2157 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true))); | |
2158 after_deadline = now_src()->Now(); | |
2159 | |
2160 // We post a zero deadline task when on battery | |
2161 EXPECT_EQ(before_deadline, after_deadline); | |
2162 | |
2163 // Switch to non-battery power | |
2164 PowerMonitorSource()->GeneratePowerStateEvent(false); | |
2165 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower()); | |
2166 | |
2167 EXPECT_SCOPED(AdvanceFrame()); | |
2168 scheduler_->SetNeedsCommit(); | |
2169 scheduler_->SetNeedsRedraw(); | |
2170 client_->Reset(); | |
2171 | |
2172 // Same as before | |
2173 before_deadline = now_src()->Now(); | |
2174 EXPECT_TRUE( | |
2175 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true))); | |
2176 after_deadline = now_src()->Now(); | |
2177 } | |
2178 | |
2179 TEST_F(SchedulerTest, | |
2180 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff) { | |
2181 scheduler_settings_.use_external_begin_frame_source = true; | |
2182 SetUpScheduler(true); | |
2183 | |
2184 // Set needs commit so that the scheduler tries to wait for the main thread | |
2185 scheduler_->SetNeedsCommit(); | |
2186 // Set needs redraw so that the scheduler doesn't wait too long | |
2187 scheduler_->SetNeedsRedraw(); | |
2188 client_->Reset(); | |
2189 | |
2190 // Switch to battery power | |
2191 PowerMonitorSource()->GeneratePowerStateEvent(true); | |
2192 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower()); | |
2193 | |
2194 EXPECT_SCOPED(AdvanceFrame()); | |
2195 scheduler_->SetNeedsCommit(); | |
2196 scheduler_->SetNeedsRedraw(); | |
2197 client_->Reset(); | |
2198 | |
2199 // Disable auto-advancing of now_src | |
2200 task_runner().SetAutoAdvanceNowToPendingTasks(false); | |
2201 | |
2202 // Deadline task is pending | |
2203 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2204 task_runner().RunPendingTasks(); | |
2205 // Deadline task is still pending | |
2206 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2207 | |
2208 // Advance now by 15 ms - same as windows low res timer | |
2209 now_src()->AdvanceNowMicroseconds(15000); | |
2210 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2211 task_runner().RunPendingTasks(); | |
2212 // Deadline task finally completes | |
2213 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2214 } | |
2215 | |
2216 TEST_F(SchedulerTest, | |
2217 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn) { | |
2218 scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true; | |
2219 scheduler_settings_.use_external_begin_frame_source = true; | |
2220 SetUpScheduler(true); | |
2221 | |
2222 // Set needs commit so that the scheduler tries to wait for the main thread | |
2223 scheduler_->SetNeedsCommit(); | |
2224 // Set needs redraw so that the scheduler doesn't wait too long | |
2225 scheduler_->SetNeedsRedraw(); | |
2226 client_->Reset(); | |
2227 | |
2228 // Switch to battery power | |
2229 PowerMonitorSource()->GeneratePowerStateEvent(true); | |
2230 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower()); | |
2231 | |
2232 EXPECT_SCOPED(AdvanceFrame()); | |
2233 scheduler_->SetNeedsCommit(); | |
2234 scheduler_->SetNeedsRedraw(); | |
2235 client_->Reset(); | |
2236 | |
2237 // Disable auto-advancing of now_src | |
2238 task_runner().SetAutoAdvanceNowToPendingTasks(false); | |
2239 | |
2240 // Deadline task is pending | |
2241 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
2242 task_runner().RunPendingTasks(); | |
2243 // Deadline task runs immediately | |
2244 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
2245 } | |
2246 | |
2247 // Tests to ensure frame sources can be successfully changed while drawing. | 2095 // Tests to ensure frame sources can be successfully changed while drawing. |
2248 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) { | 2096 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) { |
2249 scheduler_settings_.use_external_begin_frame_source = true; | 2097 scheduler_settings_.use_external_begin_frame_source = true; |
2250 SetUpScheduler(true); | 2098 SetUpScheduler(true); |
2251 | 2099 |
2252 // SetNeedsRedraw should begin the frame on the next BeginImplFrame. | 2100 // SetNeedsRedraw should begin the frame on the next BeginImplFrame. |
2253 scheduler_->SetNeedsRedraw(); | 2101 scheduler_->SetNeedsRedraw(); |
2254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); | 2102 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); |
2255 client_->Reset(); | 2103 client_->Reset(); |
2256 | 2104 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2391 client_->Reset(); | 2239 client_->Reset(); |
2392 | 2240 |
2393 task_runner().RunPendingTasks(); // Run posted deadline. | 2241 task_runner().RunPendingTasks(); // Run posted deadline. |
2394 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); | 2242 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); |
2395 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); | 2243 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); |
2396 client_->Reset(); | 2244 client_->Reset(); |
2397 } | 2245 } |
2398 | 2246 |
2399 } // namespace | 2247 } // namespace |
2400 } // namespace cc | 2248 } // namespace cc |
OLD | NEW |