| 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 |