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