OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/renderer/scheduler/renderer_scheduler_impl.h" | 5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 this); | 57 this); |
58 } | 58 } |
59 | 59 |
60 RendererSchedulerImpl::~RendererSchedulerImpl() { | 60 RendererSchedulerImpl::~RendererSchedulerImpl() { |
61 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 61 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
62 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 62 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
63 this); | 63 this); |
64 } | 64 } |
65 | 65 |
66 void RendererSchedulerImpl::Shutdown() { | 66 void RendererSchedulerImpl::Shutdown() { |
67 main_thread_checker_.CalledOnValidThread(); | 67 DCHECK(main_thread_checker_.CalledOnValidThread()); |
68 task_queue_manager_.reset(); | 68 task_queue_manager_.reset(); |
69 } | 69 } |
70 | 70 |
71 scoped_refptr<base::SingleThreadTaskRunner> | 71 scoped_refptr<base::SingleThreadTaskRunner> |
72 RendererSchedulerImpl::DefaultTaskRunner() { | 72 RendererSchedulerImpl::DefaultTaskRunner() { |
73 main_thread_checker_.CalledOnValidThread(); | 73 DCHECK(main_thread_checker_.CalledOnValidThread()); |
74 return default_task_runner_; | 74 return default_task_runner_; |
75 } | 75 } |
76 | 76 |
77 scoped_refptr<base::SingleThreadTaskRunner> | 77 scoped_refptr<base::SingleThreadTaskRunner> |
78 RendererSchedulerImpl::CompositorTaskRunner() { | 78 RendererSchedulerImpl::CompositorTaskRunner() { |
79 main_thread_checker_.CalledOnValidThread(); | 79 DCHECK(main_thread_checker_.CalledOnValidThread()); |
80 return compositor_task_runner_; | 80 return compositor_task_runner_; |
81 } | 81 } |
82 | 82 |
83 scoped_refptr<SingleThreadIdleTaskRunner> | 83 scoped_refptr<SingleThreadIdleTaskRunner> |
84 RendererSchedulerImpl::IdleTaskRunner() { | 84 RendererSchedulerImpl::IdleTaskRunner() { |
85 main_thread_checker_.CalledOnValidThread(); | 85 DCHECK(main_thread_checker_.CalledOnValidThread()); |
86 return idle_task_runner_; | 86 return idle_task_runner_; |
87 } | 87 } |
88 | 88 |
89 scoped_refptr<base::SingleThreadTaskRunner> | 89 scoped_refptr<base::SingleThreadTaskRunner> |
90 RendererSchedulerImpl::LoadingTaskRunner() { | 90 RendererSchedulerImpl::LoadingTaskRunner() { |
91 main_thread_checker_.CalledOnValidThread(); | 91 DCHECK(main_thread_checker_.CalledOnValidThread()); |
92 return loading_task_runner_; | 92 return loading_task_runner_; |
93 } | 93 } |
94 | 94 |
95 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { | 95 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { |
96 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 96 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
97 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); | 97 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); |
98 main_thread_checker_.CalledOnValidThread(); | 98 DCHECK(main_thread_checker_.CalledOnValidThread()); |
99 if (!task_queue_manager_) | 99 if (!task_queue_manager_) |
100 return; | 100 return; |
101 | 101 |
102 EndIdlePeriod(); | 102 EndIdlePeriod(); |
103 estimated_next_frame_begin_ = args.frame_time + args.interval; | 103 estimated_next_frame_begin_ = args.frame_time + args.interval; |
104 } | 104 } |
105 | 105 |
106 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 106 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
107 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 107 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
108 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | 108 "RendererSchedulerImpl::DidCommitFrameToCompositor"); |
109 main_thread_checker_.CalledOnValidThread(); | 109 DCHECK(main_thread_checker_.CalledOnValidThread()); |
110 if (!task_queue_manager_) | 110 if (!task_queue_manager_) |
111 return; | 111 return; |
112 | 112 |
113 base::TimeTicks now(Now()); | 113 base::TimeTicks now(Now()); |
114 if (now < estimated_next_frame_begin_) { | 114 if (now < estimated_next_frame_begin_) { |
115 StartIdlePeriod(); | 115 StartIdlePeriod(); |
116 control_task_runner_->PostDelayedTask(FROM_HERE, | 116 control_task_runner_->PostDelayedTask(FROM_HERE, |
117 end_idle_period_closure_.callback(), | 117 end_idle_period_closure_.callback(), |
118 estimated_next_frame_begin_ - now); | 118 estimated_next_frame_begin_ - now); |
119 } | 119 } |
(...skipping 21 matching lines...) Expand all Loading... |
141 base::AutoLock lock(incoming_signals_lock_); | 141 base::AutoLock lock(incoming_signals_lock_); |
142 if (last_input_time_.is_null()) { | 142 if (last_input_time_.is_null()) { |
143 // Update scheduler policy if should start a new compositor policy mode. | 143 // Update scheduler policy if should start a new compositor policy mode. |
144 policy_may_need_update_.SetLocked(true); | 144 policy_may_need_update_.SetLocked(true); |
145 PostUpdatePolicyOnControlRunner(base::TimeDelta()); | 145 PostUpdatePolicyOnControlRunner(base::TimeDelta()); |
146 } | 146 } |
147 last_input_time_ = Now(); | 147 last_input_time_ = Now(); |
148 } | 148 } |
149 | 149 |
150 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { | 150 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { |
151 main_thread_checker_.CalledOnValidThread(); | 151 DCHECK(main_thread_checker_.CalledOnValidThread()); |
152 if (!task_queue_manager_) | 152 if (!task_queue_manager_) |
153 return false; | 153 return false; |
154 | 154 |
155 MaybeUpdatePolicy(); | 155 MaybeUpdatePolicy(); |
156 return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY; | 156 return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY; |
157 } | 157 } |
158 | 158 |
159 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { | 159 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
160 main_thread_checker_.CalledOnValidThread(); | 160 DCHECK(main_thread_checker_.CalledOnValidThread()); |
161 if (!task_queue_manager_) | 161 if (!task_queue_manager_) |
162 return false; | 162 return false; |
163 | 163 |
164 MaybeUpdatePolicy(); | 164 MaybeUpdatePolicy(); |
165 // We only yield if we are in the compositor priority and there is compositor | 165 // We only yield if we are in the compositor priority and there is compositor |
166 // work outstanding. Note: even though the control queue is higher priority | 166 // work outstanding. Note: even though the control queue is higher priority |
167 // we don't yield for it since these tasks are not user-provided work and they | 167 // we don't yield for it since these tasks are not user-provided work and they |
168 // are only intended to run before the next task, not interrupt the tasks. | 168 // are only intended to run before the next task, not interrupt the tasks. |
169 // Note: This function could conceivably be implemented in terms of | 169 // Note: This function could conceivably be implemented in terms of |
170 // |IsHighPriorityWorkAnticipated|, but for clarity is not. | 170 // |IsHighPriorityWorkAnticipated|, but for clarity is not. |
171 return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY && | 171 return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY && |
172 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE); | 172 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE); |
173 } | 173 } |
174 | 174 |
175 void RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback( | 175 void RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback( |
176 base::TimeTicks* deadline_out) const { | 176 base::TimeTicks* deadline_out) const { |
177 main_thread_checker_.CalledOnValidThread(); | 177 DCHECK(main_thread_checker_.CalledOnValidThread()); |
178 *deadline_out = estimated_next_frame_begin_; | 178 *deadline_out = estimated_next_frame_begin_; |
179 } | 179 } |
180 | 180 |
181 RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const { | 181 RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const { |
182 main_thread_checker_.CalledOnValidThread(); | 182 DCHECK(main_thread_checker_.CalledOnValidThread()); |
183 return current_policy_; | 183 return current_policy_; |
184 } | 184 } |
185 | 185 |
186 void RendererSchedulerImpl::MaybeUpdatePolicy() { | 186 void RendererSchedulerImpl::MaybeUpdatePolicy() { |
187 main_thread_checker_.CalledOnValidThread(); | 187 DCHECK(main_thread_checker_.CalledOnValidThread()); |
188 if (policy_may_need_update_.IsSet()) { | 188 if (policy_may_need_update_.IsSet()) { |
189 UpdatePolicy(); | 189 UpdatePolicy(); |
190 } | 190 } |
191 } | 191 } |
192 | 192 |
193 void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner( | 193 void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner( |
194 base::TimeDelta delay) { | 194 base::TimeDelta delay) { |
195 control_task_runner_->PostDelayedTask( | 195 control_task_runner_->PostDelayedTask( |
196 FROM_HERE, update_policy_closure_, delay); | 196 FROM_HERE, update_policy_closure_, delay); |
197 } | 197 } |
198 | 198 |
199 void RendererSchedulerImpl::UpdatePolicy() { | 199 void RendererSchedulerImpl::UpdatePolicy() { |
200 main_thread_checker_.CalledOnValidThread(); | 200 DCHECK(main_thread_checker_.CalledOnValidThread()); |
201 if (!task_queue_manager_) | 201 if (!task_queue_manager_) |
202 return; | 202 return; |
203 | 203 |
204 base::AutoLock lock(incoming_signals_lock_); | 204 base::AutoLock lock(incoming_signals_lock_); |
205 base::TimeTicks now; | 205 base::TimeTicks now; |
206 policy_may_need_update_.SetLocked(false); | 206 policy_may_need_update_.SetLocked(false); |
207 | 207 |
208 Policy new_policy = NORMAL_PRIORITY_POLICY; | 208 Policy new_policy = NORMAL_PRIORITY_POLICY; |
209 if (!last_input_time_.is_null()) { | 209 if (!last_input_time_.is_null()) { |
210 base::TimeDelta compositor_priority_duration = | 210 base::TimeDelta compositor_priority_duration = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 247 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
248 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 248 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
249 this, AsValueLocked(now)); | 249 this, AsValueLocked(now)); |
250 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 250 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
251 "RendererScheduler.policy", current_policy_); | 251 "RendererScheduler.policy", current_policy_); |
252 } | 252 } |
253 | 253 |
254 void RendererSchedulerImpl::StartIdlePeriod() { | 254 void RendererSchedulerImpl::StartIdlePeriod() { |
255 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", | 255 TRACE_EVENT_ASYNC_BEGIN0("renderer.scheduler", |
256 "RendererSchedulerIdlePeriod", this); | 256 "RendererSchedulerIdlePeriod", this); |
257 main_thread_checker_.CalledOnValidThread(); | 257 DCHECK(main_thread_checker_.CalledOnValidThread()); |
258 renderer_task_queue_selector_->EnableQueue( | 258 renderer_task_queue_selector_->EnableQueue( |
259 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 259 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
260 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 260 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
261 } | 261 } |
262 | 262 |
263 void RendererSchedulerImpl::EndIdlePeriod() { | 263 void RendererSchedulerImpl::EndIdlePeriod() { |
264 TRACE_EVENT_ASYNC_END0("renderer.scheduler", | 264 TRACE_EVENT_ASYNC_END0("renderer.scheduler", |
265 "RendererSchedulerIdlePeriod", this); | 265 "RendererSchedulerIdlePeriod", this); |
266 main_thread_checker_.CalledOnValidThread(); | 266 DCHECK(main_thread_checker_.CalledOnValidThread()); |
267 end_idle_period_closure_.Cancel(); | 267 end_idle_period_closure_.Cancel(); |
268 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 268 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
269 } | 269 } |
270 | 270 |
271 void RendererSchedulerImpl::SetTimeSourceForTesting( | 271 void RendererSchedulerImpl::SetTimeSourceForTesting( |
272 scoped_refptr<cc::TestNowSource> time_source) { | 272 scoped_refptr<cc::TestNowSource> time_source) { |
273 main_thread_checker_.CalledOnValidThread(); | 273 DCHECK(main_thread_checker_.CalledOnValidThread()); |
274 time_source_ = time_source; | 274 time_source_ = time_source; |
275 task_queue_manager_->SetTimeSourceForTesting(time_source); | 275 task_queue_manager_->SetTimeSourceForTesting(time_source); |
276 } | 276 } |
277 | 277 |
278 base::TimeTicks RendererSchedulerImpl::Now() const { | 278 base::TimeTicks RendererSchedulerImpl::Now() const { |
279 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); | 279 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); |
280 } | 280 } |
281 | 281 |
282 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( | 282 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( |
283 base::Lock* write_lock_) | 283 base::Lock* write_lock_) |
284 : flag_(false), write_lock_(write_lock_) { | 284 : flag_(false), write_lock_(write_lock_) { |
285 } | 285 } |
286 | 286 |
287 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { | 287 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { |
288 } | 288 } |
289 | 289 |
290 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { | 290 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { |
291 write_lock_->AssertAcquired(); | 291 write_lock_->AssertAcquired(); |
292 base::subtle::Release_Store(&flag_, value); | 292 base::subtle::Release_Store(&flag_, value); |
293 } | 293 } |
294 | 294 |
295 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { | 295 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { |
296 thread_checker_.CalledOnValidThread(); | |
297 return base::subtle::Acquire_Load(&flag_) != 0; | 296 return base::subtle::Acquire_Load(&flag_) != 0; |
298 } | 297 } |
299 | 298 |
300 // static | 299 // static |
301 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { | 300 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { |
302 switch (queue_id) { | 301 switch (queue_id) { |
303 case DEFAULT_TASK_QUEUE: | 302 case DEFAULT_TASK_QUEUE: |
304 return "default_tq"; | 303 return "default_tq"; |
305 case COMPOSITOR_TASK_QUEUE: | 304 case COMPOSITOR_TASK_QUEUE: |
306 return "compositor_tq"; | 305 return "compositor_tq"; |
(...skipping 17 matching lines...) Expand all Loading... |
324 case COMPOSITOR_PRIORITY_POLICY: | 323 case COMPOSITOR_PRIORITY_POLICY: |
325 return "compositor"; | 324 return "compositor"; |
326 default: | 325 default: |
327 NOTREACHED(); | 326 NOTREACHED(); |
328 return nullptr; | 327 return nullptr; |
329 } | 328 } |
330 } | 329 } |
331 | 330 |
332 scoped_refptr<base::debug::ConvertableToTraceFormat> | 331 scoped_refptr<base::debug::ConvertableToTraceFormat> |
333 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | 332 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
334 main_thread_checker_.CalledOnValidThread(); | 333 DCHECK(main_thread_checker_.CalledOnValidThread()); |
335 incoming_signals_lock_.AssertAcquired(); | 334 incoming_signals_lock_.AssertAcquired(); |
336 | 335 |
337 if (optional_now.is_null()) | 336 if (optional_now.is_null()) |
338 optional_now = Now(); | 337 optional_now = Now(); |
339 scoped_refptr<base::debug::TracedValue> state = | 338 scoped_refptr<base::debug::TracedValue> state = |
340 new base::debug::TracedValue(); | 339 new base::debug::TracedValue(); |
341 | 340 |
342 state->SetString("current_policy", PolicyToString(current_policy_)); | 341 state->SetString("current_policy", PolicyToString(current_policy_)); |
343 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | 342 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
344 state->SetDouble("last_input_time", | 343 state->SetDouble("last_input_time", |
345 (last_input_time_ - base::TimeTicks()).InMillisecondsF()); | 344 (last_input_time_ - base::TimeTicks()).InMillisecondsF()); |
346 state->SetDouble( | 345 state->SetDouble( |
347 "estimated_next_frame_begin", | 346 "estimated_next_frame_begin", |
348 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); | 347 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); |
349 | 348 |
350 return state; | 349 return state; |
351 } | 350 } |
352 | 351 |
353 } // namespace content | 352 } // namespace content |
OLD | NEW |