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 #include "cc/scheduler/scheduler.h" | 4 #include "cc/scheduler/scheduler.h" |
5 | 5 |
6 #include <string> | 6 #include <string> |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
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" |
13 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
14 #include "base/time/time.h" | 16 #include "base/time/time.h" |
15 #include "cc/test/begin_frame_args_test.h" | 17 #include "cc/test/begin_frame_args_test.h" |
16 #include "cc/test/ordered_simple_task_runner.h" | 18 #include "cc/test/ordered_simple_task_runner.h" |
17 #include "cc/test/scheduler_test_common.h" | 19 #include "cc/test/scheduler_test_common.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
20 | 22 |
21 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ | 23 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \ |
22 do { \ | 24 do { \ |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) override { | 58 virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) override { |
57 if (needs_begin_frames) { | 59 if (needs_begin_frames) { |
58 client_->actions_.push_back("SetNeedsBeginFrames(true)"); | 60 client_->actions_.push_back("SetNeedsBeginFrames(true)"); |
59 } else { | 61 } else { |
60 client_->actions_.push_back("SetNeedsBeginFrames(false)"); | 62 client_->actions_.push_back("SetNeedsBeginFrames(false)"); |
61 } | 63 } |
62 client_->states_.push_back(client_->scheduler_->AsValue()); | 64 client_->states_.push_back(client_->scheduler_->AsValue()); |
63 } | 65 } |
64 }; | 66 }; |
65 | 67 |
| 68 class FakePowerMonitorSource : public base::PowerMonitorSource { |
| 69 public: |
| 70 FakePowerMonitorSource() {} |
| 71 virtual ~FakePowerMonitorSource() {} |
| 72 void GeneratePowerStateEvent(bool on_battery_power) { |
| 73 on_battery_power_impl_ = on_battery_power; |
| 74 ProcessPowerEvent(POWER_STATE_EVENT); |
| 75 base::MessageLoop::current()->RunUntilIdle(); |
| 76 } |
| 77 virtual bool IsOnBatteryPowerImpl() override { |
| 78 return on_battery_power_impl_; |
| 79 } |
| 80 |
| 81 private: |
| 82 bool on_battery_power_impl_; |
| 83 }; |
| 84 |
66 FakeSchedulerClient() | 85 FakeSchedulerClient() |
67 : automatic_swap_ack_(true), | 86 : automatic_swap_ack_(true), |
68 swap_contains_incomplete_tile_(false), | 87 swap_contains_incomplete_tile_(false), |
69 redraw_will_happen_if_update_visible_tiles_happens_(false), | 88 redraw_will_happen_if_update_visible_tiles_happens_(false), |
70 now_src_(TestNowSource::Create()), | 89 now_src_(TestNowSource::Create()), |
71 fake_frame_source_(this) { | 90 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), |
| 91 fake_frame_source_(this), |
| 92 fake_power_monitor_source_(new FakePowerMonitorSource), |
| 93 power_monitor_(make_scoped_ptr<base::PowerMonitorSource>( |
| 94 fake_power_monitor_source_)), |
| 95 scheduler_(nullptr) { |
| 96 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval() |
| 97 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100)); |
| 98 // Fail if we need to run 100 tasks in a row. |
| 99 task_runner_->SetRunTaskLimit(100); |
72 Reset(); | 100 Reset(); |
73 } | 101 } |
74 | 102 |
75 void Reset() { | 103 void Reset() { |
76 actions_.clear(); | 104 actions_.clear(); |
77 states_.clear(); | 105 states_.clear(); |
78 draw_will_happen_ = true; | 106 draw_will_happen_ = true; |
79 swap_will_happen_if_draw_happens_ = true; | 107 swap_will_happen_if_draw_happens_ = true; |
80 num_draws_ = 0; | 108 num_draws_ = 0; |
81 log_anticipated_draw_time_change_ = false; | 109 log_anticipated_draw_time_change_ = false; |
82 } | 110 } |
83 | 111 |
84 TestScheduler* CreateScheduler(const SchedulerSettings& settings) { | 112 TestScheduler* CreateScheduler(const SchedulerSettings& settings) { |
85 scheduler_ = TestScheduler::Create(now_src_, this, settings, 0); | 113 scheduler_ = TestScheduler::Create( |
| 114 now_src_, this, settings, 0, task_runner_, &power_monitor_); |
86 DCHECK(scheduler_); | 115 DCHECK(scheduler_); |
87 // Fail if we need to run 100 tasks in a row. | |
88 task_runner().SetRunTaskLimit(100); | |
89 return scheduler_.get(); | 116 return scheduler_.get(); |
90 } | 117 } |
91 | 118 |
92 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it | 119 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it |
93 // for tests that do. | 120 // for tests that do. |
94 void set_log_anticipated_draw_time_change(bool log) { | 121 void set_log_anticipated_draw_time_change(bool log) { |
95 log_anticipated_draw_time_change_ = log; | 122 log_anticipated_draw_time_change_ = log; |
96 } | 123 } |
97 bool needs_begin_frames() { return fake_frame_source_.NeedsBeginFrames(); } | 124 bool needs_begin_frames() { return fake_frame_source_.NeedsBeginFrames(); } |
98 int num_draws() const { return num_draws_; } | 125 int num_draws() const { return num_draws_; } |
99 int num_actions_() const { return static_cast<int>(actions_.size()); } | 126 int num_actions_() const { return static_cast<int>(actions_.size()); } |
100 const char* Action(int i) const { return actions_[i]; } | 127 const char* Action(int i) const { return actions_[i]; } |
101 std::string StateForAction(int i) const { return states_[i]->ToString(); } | 128 std::string StateForAction(int i) const { return states_[i]->ToString(); } |
102 base::TimeTicks posted_begin_impl_frame_deadline() const { | 129 base::TimeTicks posted_begin_impl_frame_deadline() const { |
103 return posted_begin_impl_frame_deadline_; | 130 return posted_begin_impl_frame_deadline_; |
104 } | 131 } |
105 | 132 |
106 bool ExternalBeginFrame() { | 133 bool ExternalBeginFrame() { |
107 return scheduler_->settings().begin_frame_scheduling_enabled && | 134 return scheduler_->settings().begin_frame_scheduling_enabled && |
108 scheduler_->settings().throttle_frame_production; | 135 scheduler_->settings().throttle_frame_production; |
109 } | 136 } |
110 virtual FakeBeginFrameSource* ExternalBeginFrameSource() override { | 137 virtual FakeBeginFrameSource* ExternalBeginFrameSource() override { |
111 return &fake_frame_source_; | 138 return &fake_frame_source_; |
112 } | 139 } |
113 | 140 |
| 141 base::PowerMonitor* PowerMonitor() { return &power_monitor_; } |
| 142 |
| 143 FakePowerMonitorSource* PowerMonitorSource() { |
| 144 return fake_power_monitor_source_; |
| 145 } |
| 146 |
114 void AdvanceFrame() { | 147 void AdvanceFrame() { |
115 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), | 148 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), |
116 "FakeSchedulerClient::AdvanceFrame"); | 149 "FakeSchedulerClient::AdvanceFrame"); |
117 // EXPECT_TRUE(needs_begin_frames()); | 150 // EXPECT_TRUE(needs_begin_frames()); |
118 if (ExternalBeginFrame()) { | 151 if (ExternalBeginFrame()) { |
119 // Creep the time forward so that any BeginFrameArgs is not equal to the | 152 // Creep the time forward so that any BeginFrameArgs is not equal to the |
120 // last one otherwise we violate the BeginFrameSource contract. | 153 // last one otherwise we violate the BeginFrameSource contract. |
121 now_src_->AdvanceNowMicroseconds(1); | 154 now_src_->AdvanceNowMicroseconds(1); |
122 fake_frame_source_.TestOnBeginFrame( | 155 fake_frame_source_.TestOnBeginFrame( |
123 CreateBeginFrameArgsForTesting(now_src_)); | 156 CreateBeginFrameArgsForTesting(now_src_)); |
124 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | 157 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
125 } | 158 } |
126 | 159 |
127 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false))); | 160 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false))); |
128 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | 161 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
129 } | 162 } |
130 | 163 |
131 OrderedSimpleTaskRunner& task_runner() { return scheduler_->task_runner(); } | 164 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; } |
132 TestNowSource* now_src() { return now_src_.get(); } | 165 TestNowSource* now_src() { return now_src_.get(); } |
133 | 166 |
134 int ActionIndex(const char* action) const { | 167 int ActionIndex(const char* action) const { |
135 for (size_t i = 0; i < actions_.size(); i++) | 168 for (size_t i = 0; i < actions_.size(); i++) |
136 if (!strcmp(actions_[i], action)) | 169 if (!strcmp(actions_[i], action)) |
137 return i; | 170 return i; |
138 return -1; | 171 return -1; |
139 } | 172 } |
140 | 173 |
141 void SetSwapContainsIncompleteTile(bool contain) { | 174 void SetSwapContainsIncompleteTile(bool contain) { |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 bool draw_will_happen_; | 283 bool draw_will_happen_; |
251 bool swap_will_happen_if_draw_happens_; | 284 bool swap_will_happen_if_draw_happens_; |
252 bool automatic_swap_ack_; | 285 bool automatic_swap_ack_; |
253 int num_draws_; | 286 int num_draws_; |
254 bool log_anticipated_draw_time_change_; | 287 bool log_anticipated_draw_time_change_; |
255 bool swap_contains_incomplete_tile_; | 288 bool swap_contains_incomplete_tile_; |
256 bool redraw_will_happen_if_update_visible_tiles_happens_; | 289 bool redraw_will_happen_if_update_visible_tiles_happens_; |
257 base::TimeTicks posted_begin_impl_frame_deadline_; | 290 base::TimeTicks posted_begin_impl_frame_deadline_; |
258 std::vector<const char*> actions_; | 291 std::vector<const char*> actions_; |
259 std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_; | 292 std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_; |
| 293 scoped_refptr<TestNowSource> now_src_; |
| 294 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
| 295 FakeBeginFrameSourceForFakeSchedulerClient fake_frame_source_; |
| 296 FakePowerMonitorSource* fake_power_monitor_source_; |
| 297 base::PowerMonitor power_monitor_; |
260 scoped_ptr<TestScheduler> scheduler_; | 298 scoped_ptr<TestScheduler> scheduler_; |
261 scoped_refptr<TestNowSource> now_src_; | |
262 FakeBeginFrameSourceForFakeSchedulerClient fake_frame_source_; | |
263 }; | 299 }; |
264 | 300 |
265 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, | 301 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, |
266 FakeSchedulerClient* client) { | 302 FakeSchedulerClient* client) { |
267 TRACE_EVENT0("cc", | 303 TRACE_EVENT0("cc", |
268 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit"); | 304 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit"); |
269 | 305 |
270 scheduler->DidCreateAndInitializeOutputSurface(); | 306 scheduler->DidCreateAndInitializeOutputSurface(); |
271 scheduler->SetNeedsCommit(); | 307 scheduler->SetNeedsCommit(); |
272 scheduler->NotifyBeginMainFrameStarted(); | 308 scheduler->NotifyBeginMainFrameStarted(); |
(...skipping 1687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1960 scheduler->NotifyReadyToCommit(); | 1996 scheduler->NotifyReadyToCommit(); |
1961 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); | 1997 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); |
1962 | 1998 |
1963 client.Reset(); | 1999 client.Reset(); |
1964 scheduler->SetVisible(false); | 2000 scheduler->SetVisible(false); |
1965 // Sync tree should be forced to activate. | 2001 // Sync tree should be forced to activate. |
1966 EXPECT_ACTION("SetNeedsBeginFrames(false)", client, 0, 2); | 2002 EXPECT_ACTION("SetNeedsBeginFrames(false)", client, 0, 2); |
1967 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 2); | 2003 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 2); |
1968 } | 2004 } |
1969 | 2005 |
| 2006 TEST(SchedulerTest, SchedulerPowerMonitoring) { |
| 2007 FakeSchedulerClient client; |
| 2008 SchedulerSettings settings; |
| 2009 settings.disable_hi_res_timer_tasks_on_battery = true; |
| 2010 TestScheduler* scheduler = client.CreateScheduler(settings); |
| 2011 |
| 2012 base::TimeTicks before_deadline, after_deadline; |
| 2013 |
| 2014 scheduler->SetCanStart(); |
| 2015 scheduler->SetVisible(true); |
| 2016 scheduler->SetCanDraw(true); |
| 2017 |
| 2018 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); |
| 2019 |
| 2020 scheduler->SetNeedsCommit(); |
| 2021 scheduler->SetNeedsRedraw(); |
| 2022 client.Reset(); |
| 2023 |
| 2024 // On non-battery power |
| 2025 EXPECT_FALSE(client.PowerMonitor()->IsOnBatteryPower()); |
| 2026 |
| 2027 client.AdvanceFrame(); |
| 2028 client.Reset(); |
| 2029 |
| 2030 before_deadline = client.now_src()->Now(); |
| 2031 EXPECT_TRUE(client.task_runner().RunTasksWhile( |
| 2032 client.ImplFrameDeadlinePending(true))); |
| 2033 after_deadline = client.now_src()->Now(); |
| 2034 |
| 2035 // We post a non-zero deadline task when not on battery |
| 2036 EXPECT_LT(before_deadline, after_deadline); |
| 2037 |
| 2038 // Switch to battery power |
| 2039 client.PowerMonitorSource()->GeneratePowerStateEvent(true); |
| 2040 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower()); |
| 2041 |
| 2042 client.AdvanceFrame(); |
| 2043 scheduler->SetNeedsCommit(); |
| 2044 scheduler->SetNeedsRedraw(); |
| 2045 client.Reset(); |
| 2046 |
| 2047 before_deadline = client.now_src()->Now(); |
| 2048 EXPECT_TRUE(client.task_runner().RunTasksWhile( |
| 2049 client.ImplFrameDeadlinePending(true))); |
| 2050 after_deadline = client.now_src()->Now(); |
| 2051 |
| 2052 // We post a zero deadline task when on battery |
| 2053 EXPECT_EQ(before_deadline, after_deadline); |
| 2054 |
| 2055 // Switch to non-battery power |
| 2056 client.PowerMonitorSource()->GeneratePowerStateEvent(false); |
| 2057 EXPECT_FALSE(client.PowerMonitor()->IsOnBatteryPower()); |
| 2058 |
| 2059 client.AdvanceFrame(); |
| 2060 scheduler->SetNeedsCommit(); |
| 2061 scheduler->SetNeedsRedraw(); |
| 2062 client.Reset(); |
| 2063 |
| 2064 // Same as before |
| 2065 before_deadline = client.now_src()->Now(); |
| 2066 EXPECT_TRUE(client.task_runner().RunTasksWhile( |
| 2067 client.ImplFrameDeadlinePending(true))); |
| 2068 after_deadline = client.now_src()->Now(); |
| 2069 } |
| 2070 |
| 2071 TEST(SchedulerTest, |
| 2072 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff) { |
| 2073 FakeSchedulerClient client; |
| 2074 SchedulerSettings settings; |
| 2075 TestScheduler* scheduler = client.CreateScheduler(settings); |
| 2076 |
| 2077 scheduler->SetCanStart(); |
| 2078 scheduler->SetVisible(true); |
| 2079 scheduler->SetCanDraw(true); |
| 2080 |
| 2081 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); |
| 2082 |
| 2083 // Set needs commit so that the scheduler tries to wait for the main thread |
| 2084 scheduler->SetNeedsCommit(); |
| 2085 // Set needs redraw so that the scheduler doesn't wait too long |
| 2086 scheduler->SetNeedsRedraw(); |
| 2087 client.Reset(); |
| 2088 |
| 2089 // Switch to battery power |
| 2090 client.PowerMonitorSource()->GeneratePowerStateEvent(true); |
| 2091 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower()); |
| 2092 |
| 2093 client.AdvanceFrame(); |
| 2094 scheduler->SetNeedsCommit(); |
| 2095 scheduler->SetNeedsRedraw(); |
| 2096 client.Reset(); |
| 2097 |
| 2098 // Disable auto-advancing of now_src |
| 2099 client.task_runner().SetAutoAdvanceNowToPendingTasks(false); |
| 2100 |
| 2101 // Deadline task is pending |
| 2102 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); |
| 2103 client.task_runner().RunPendingTasks(); |
| 2104 // Deadline task is still pending |
| 2105 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); |
| 2106 |
| 2107 // Advance now by 15 ms - same as windows low res timer |
| 2108 client.now_src()->AdvanceNowMicroseconds(15000); |
| 2109 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); |
| 2110 client.task_runner().RunPendingTasks(); |
| 2111 // Deadline task finally completes |
| 2112 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); |
| 2113 } |
| 2114 |
| 2115 TEST(SchedulerTest, |
| 2116 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn) { |
| 2117 FakeSchedulerClient client; |
| 2118 SchedulerSettings settings; |
| 2119 settings.disable_hi_res_timer_tasks_on_battery = true; |
| 2120 TestScheduler* scheduler = client.CreateScheduler(settings); |
| 2121 |
| 2122 scheduler->SetCanStart(); |
| 2123 scheduler->SetVisible(true); |
| 2124 scheduler->SetCanDraw(true); |
| 2125 |
| 2126 InitializeOutputSurfaceAndFirstCommit(scheduler, &client); |
| 2127 |
| 2128 // Set needs commit so that the scheduler tries to wait for the main thread |
| 2129 scheduler->SetNeedsCommit(); |
| 2130 // Set needs redraw so that the scheduler doesn't wait too long |
| 2131 scheduler->SetNeedsRedraw(); |
| 2132 client.Reset(); |
| 2133 |
| 2134 // Switch to battery power |
| 2135 client.PowerMonitorSource()->GeneratePowerStateEvent(true); |
| 2136 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower()); |
| 2137 |
| 2138 client.AdvanceFrame(); |
| 2139 scheduler->SetNeedsCommit(); |
| 2140 scheduler->SetNeedsRedraw(); |
| 2141 client.Reset(); |
| 2142 |
| 2143 // Disable auto-advancing of now_src |
| 2144 client.task_runner().SetAutoAdvanceNowToPendingTasks(false); |
| 2145 |
| 2146 // Deadline task is pending |
| 2147 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); |
| 2148 client.task_runner().RunPendingTasks(); |
| 2149 // Deadline task runs immediately |
| 2150 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); |
| 2151 } |
| 2152 |
1970 } // namespace | 2153 } // namespace |
1971 } // namespace cc | 2154 } // namespace cc |
OLD | NEW |