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/debug/trace_event.h" | |
| 9 #include "base/debug/trace_event_argument.h" | |
| 8 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
| 9 #include "cc/output/begin_frame_args.h" | 11 #include "cc/output/begin_frame_args.h" |
| 10 #include "content/renderer/scheduler/renderer_task_queue_selector.h" | 12 #include "content/renderer/scheduler/renderer_task_queue_selector.h" |
| 11 #include "ui/gfx/frame_time.h" | 13 #include "ui/gfx/frame_time.h" |
| 12 | 14 |
| 13 namespace content { | 15 namespace content { |
| 14 | 16 |
| 15 RendererSchedulerImpl::RendererSchedulerImpl() | 17 RendererSchedulerImpl::RendererSchedulerImpl() |
| 16 : RendererSchedulerImpl(base::MessageLoopProxy::current()) { | 18 : RendererSchedulerImpl(base::MessageLoopProxy::current()) { |
| 17 } | 19 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 33 policy_may_need_update_(0), | 35 policy_may_need_update_(0), |
| 34 weak_factory_(this) { | 36 weak_factory_(this) { |
| 35 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); | 37 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); |
| 36 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( | 38 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
| 37 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), | 39 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), |
| 38 weak_factory_.GetWeakPtr())); | 40 weak_factory_.GetWeakPtr())); |
| 39 renderer_task_queue_selector_->SetQueuePriority( | 41 renderer_task_queue_selector_->SetQueuePriority( |
| 40 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); | 42 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); |
| 41 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 43 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| 42 task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false); | 44 task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false); |
| 45 | |
| 46 for (size_t i = 0; i < TASK_QUEUE_COUNT; i++) { | |
| 47 task_queue_manager_->SetQueueName( | |
| 48 i, TaskQueueIdToString(static_cast<QueueId>(i))); | |
| 49 } | |
| 50 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | |
| 51 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 52 "RendererScheduler", | |
| 53 this); | |
| 43 } | 54 } |
| 44 | 55 |
| 45 RendererSchedulerImpl::~RendererSchedulerImpl() { | 56 RendererSchedulerImpl::~RendererSchedulerImpl() { |
| 46 } | 57 } |
| 47 | 58 |
| 48 void RendererSchedulerImpl::Shutdown() { | 59 void RendererSchedulerImpl::Shutdown() { |
| 49 task_queue_manager_.reset(); | 60 task_queue_manager_.reset(); |
| 50 } | 61 } |
| 51 | 62 |
| 52 scoped_refptr<base::SingleThreadTaskRunner> | 63 scoped_refptr<base::SingleThreadTaskRunner> |
| 53 RendererSchedulerImpl::DefaultTaskRunner() { | 64 RendererSchedulerImpl::DefaultTaskRunner() { |
| 54 return default_task_runner_; | 65 return default_task_runner_; |
| 55 } | 66 } |
| 56 | 67 |
| 57 scoped_refptr<base::SingleThreadTaskRunner> | 68 scoped_refptr<base::SingleThreadTaskRunner> |
| 58 RendererSchedulerImpl::CompositorTaskRunner() { | 69 RendererSchedulerImpl::CompositorTaskRunner() { |
| 59 return compositor_task_runner_; | 70 return compositor_task_runner_; |
| 60 } | 71 } |
| 61 | 72 |
| 62 scoped_refptr<SingleThreadIdleTaskRunner> | 73 scoped_refptr<SingleThreadIdleTaskRunner> |
| 63 RendererSchedulerImpl::IdleTaskRunner() { | 74 RendererSchedulerImpl::IdleTaskRunner() { |
| 64 return idle_task_runner_; | 75 return idle_task_runner_; |
| 65 } | 76 } |
| 66 | 77 |
| 67 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { | 78 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { |
| 79 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 80 "RendererSchedulerImpl::WillBeginFrame"); | |
|
rmcilroy
2014/11/07 18:21:57
Would it be worth passing the args values (frame_t
Sami
2014/11/10 14:35:01
Good idea. Looks like |args| already knows how to
| |
| 68 main_thread_checker_.CalledOnValidThread(); | 81 main_thread_checker_.CalledOnValidThread(); |
| 69 if (!task_queue_manager_) | 82 if (!task_queue_manager_) |
| 70 return; | 83 return; |
| 71 | 84 |
| 72 EndIdlePeriod(); | 85 EndIdlePeriod(); |
| 73 estimated_next_frame_begin_ = args.frame_time + args.interval; | 86 estimated_next_frame_begin_ = args.frame_time + args.interval; |
| 74 } | 87 } |
| 75 | 88 |
| 76 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 89 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
| 90 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 91 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | |
| 77 main_thread_checker_.CalledOnValidThread(); | 92 main_thread_checker_.CalledOnValidThread(); |
| 78 if (!task_queue_manager_) | 93 if (!task_queue_manager_) |
| 79 return; | 94 return; |
| 80 | 95 |
| 81 if (Now() < estimated_next_frame_begin_) { | 96 if (Now() < estimated_next_frame_begin_) { |
| 82 StartIdlePeriod(); | 97 StartIdlePeriod(); |
| 83 } | 98 } |
| 84 } | 99 } |
| 85 | 100 |
| 86 void RendererSchedulerImpl::DidReceiveInputEvent() { | 101 void RendererSchedulerImpl::DidReceiveInputEvent() { |
| 102 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 103 "RendererSchedulerImpl::DidReceiveInputEvent"); | |
| 87 if (!task_queue_manager_) | 104 if (!task_queue_manager_) |
| 88 return; | 105 return; |
| 89 base::AutoLock lock(incoming_signals_lock_); | 106 base::AutoLock lock(incoming_signals_lock_); |
| 90 if (last_input_time_.is_null()) { | 107 if (last_input_time_.is_null()) { |
| 91 // Update scheduler policy if should start a new compositor policy mode. | 108 // Update scheduler policy if should start a new compositor policy mode. |
| 92 base::subtle::Release_Store(&policy_may_need_update_, 1); | 109 base::subtle::Release_Store(&policy_may_need_update_, 1); |
| 93 PostUpdatePolicyOnControlRunner(base::TimeDelta()); | 110 PostUpdatePolicyOnControlRunner(base::TimeDelta()); |
| 94 } | 111 } |
| 95 last_input_time_ = Now(); | 112 last_input_time_ = Now(); |
| 96 } | 113 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 } | 145 } |
| 129 } | 146 } |
| 130 | 147 |
| 131 void RendererSchedulerImpl::UpdatePolicy() { | 148 void RendererSchedulerImpl::UpdatePolicy() { |
| 132 main_thread_checker_.CalledOnValidThread(); | 149 main_thread_checker_.CalledOnValidThread(); |
| 133 if (!task_queue_manager_) | 150 if (!task_queue_manager_) |
| 134 return; | 151 return; |
| 135 | 152 |
| 136 base::AutoLock lock(incoming_signals_lock_); | 153 base::AutoLock lock(incoming_signals_lock_); |
| 137 base::subtle::Release_Store(&policy_may_need_update_, 0); | 154 base::subtle::Release_Store(&policy_may_need_update_, 0); |
| 155 base::TimeTicks now; | |
| 138 | 156 |
| 139 Policy new_policy = NORMAL_PRIORITY_POLICY; | 157 Policy new_policy = NORMAL_PRIORITY_POLICY; |
| 140 if (!last_input_time_.is_null()) { | 158 if (!last_input_time_.is_null()) { |
| 159 now = Now(); | |
| 141 base::TimeDelta compositor_priority_duration = | 160 base::TimeDelta compositor_priority_duration = |
| 142 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); | 161 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); |
| 143 base::TimeDelta remaining_compositor_priority_duration = | 162 base::TimeDelta remaining_compositor_priority_duration = |
| 144 last_input_time_ + compositor_priority_duration - Now(); | 163 last_input_time_ + compositor_priority_duration - now; |
| 145 if (remaining_compositor_priority_duration > base::TimeDelta()) { | 164 if (remaining_compositor_priority_duration > base::TimeDelta()) { |
| 146 PostUpdatePolicyOnControlRunner(remaining_compositor_priority_duration); | 165 PostUpdatePolicyOnControlRunner(remaining_compositor_priority_duration); |
| 147 new_policy = COMPOSITOR_PRIORITY_POLICY; | 166 new_policy = COMPOSITOR_PRIORITY_POLICY; |
| 148 } else { | 167 } else { |
| 149 // Null out last_input_time_ to ensure DidReceiveInputEvent will post an | 168 // Null out last_input_time_ to ensure DidReceiveInputEvent will post an |
| 150 // UpdatePolicy task when it's next called. | 169 // UpdatePolicy task when it's next called. |
| 151 last_input_time_ = base::TimeTicks(); | 170 last_input_time_ = base::TimeTicks(); |
| 152 } | 171 } |
| 153 } | 172 } |
| 154 | 173 |
| 155 if (new_policy == current_policy_) { | 174 if (new_policy == current_policy_) { |
| 156 return; | 175 return; |
| 157 } | 176 } |
| 158 | 177 |
| 159 switch (new_policy) { | 178 switch (new_policy) { |
| 160 case COMPOSITOR_PRIORITY_POLICY: | 179 case COMPOSITOR_PRIORITY_POLICY: |
| 161 renderer_task_queue_selector_->SetQueuePriority( | 180 renderer_task_queue_selector_->SetQueuePriority( |
| 162 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); | 181 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
| 163 break; | 182 break; |
| 164 case NORMAL_PRIORITY_POLICY: | 183 case NORMAL_PRIORITY_POLICY: |
| 165 renderer_task_queue_selector_->SetQueuePriority( | 184 renderer_task_queue_selector_->SetQueuePriority( |
| 166 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); | 185 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); |
| 167 break; | 186 break; |
| 168 } | 187 } |
| 169 current_policy_ = new_policy; | 188 current_policy_ = new_policy; |
| 189 | |
| 190 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | |
| 191 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 192 "RendererScheduler", | |
| 193 this, | |
| 194 AsValueLocked(now)); | |
| 195 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 196 "RendererScheduler.policy", | |
| 197 current_policy_); | |
| 170 } | 198 } |
| 171 | 199 |
| 172 void RendererSchedulerImpl::StartIdlePeriod() { | 200 void RendererSchedulerImpl::StartIdlePeriod() { |
| 201 TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 202 "RendererSchedulerIdlePeriod", | |
| 203 this); | |
| 173 renderer_task_queue_selector_->EnableQueue( | 204 renderer_task_queue_selector_->EnableQueue( |
| 174 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 205 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
| 175 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 206 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
| 176 } | 207 } |
| 177 | 208 |
| 178 void RendererSchedulerImpl::EndIdlePeriod() { | 209 void RendererSchedulerImpl::EndIdlePeriod() { |
| 210 TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 211 "RendererSchedulerIdlePeriod", | |
| 212 this); | |
| 179 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 213 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| 180 } | 214 } |
| 181 | 215 |
| 182 base::TimeTicks RendererSchedulerImpl::Now() const { | 216 base::TimeTicks RendererSchedulerImpl::Now() const { |
| 183 return gfx::FrameTime::Now(); | 217 return gfx::FrameTime::Now(); |
| 184 } | 218 } |
| 185 | 219 |
| 220 // static | |
| 221 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { | |
| 222 switch (queue_id) { | |
| 223 case DEFAULT_TASK_QUEUE: | |
| 224 return "default_tq"; | |
| 225 case COMPOSITOR_TASK_QUEUE: | |
| 226 return "compositor_tq"; | |
| 227 case IDLE_TASK_QUEUE: | |
| 228 return "idle_tq"; | |
| 229 case CONTROL_TASK_QUEUE: | |
| 230 return "control_tq"; | |
| 231 default: | |
| 232 NOTREACHED(); | |
| 233 return nullptr; | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 // static | |
| 238 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { | |
| 239 switch (policy) { | |
| 240 case NORMAL_PRIORITY_POLICY: | |
| 241 return "normal"; | |
| 242 case COMPOSITOR_PRIORITY_POLICY: | |
| 243 return "compositor"; | |
| 244 default: | |
| 245 NOTREACHED(); | |
| 246 return nullptr; | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 scoped_refptr<base::debug::ConvertableToTraceFormat> | |
| 251 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | |
| 252 main_thread_checker_.CalledOnValidThread(); | |
| 253 incoming_signals_lock_.AssertAcquired(); | |
| 254 | |
| 255 if (optional_now.is_null()) | |
| 256 optional_now = Now(); | |
| 257 scoped_refptr<base::debug::TracedValue> state = | |
| 258 new base::debug::TracedValue(); | |
| 259 | |
| 260 state->SetString("current_policy", PolicyToString(current_policy_)); | |
| 261 state->SetBoolean("has_task_queue_manager", task_queue_manager_.get()); | |
| 262 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | |
| 263 state->SetDouble("last_input_time", | |
| 264 (last_input_time_ - base::TimeTicks()).InMillisecondsF()); | |
| 265 state->SetDouble( | |
| 266 "estimated_next_frame_begin", | |
| 267 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); | |
| 268 | |
| 269 return state; | |
| 270 } | |
| 271 | |
| 186 } // namespace content | 272 } // namespace content |
| OLD | NEW |