Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: content/renderer/scheduler/renderer_scheduler_impl.cc

Issue 1058873010: Move blink scheduler implementation into a component (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updates Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/scheduler/renderer_scheduler_impl.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/trace_event/trace_event.h"
10 #include "base/trace_event/trace_event_argument.h"
11 #include "cc/output/begin_frame_args.h"
12 #include "content/child/scheduler/nestable_single_thread_task_runner.h"
13 #include "content/child/scheduler/prioritizing_task_queue_selector.h"
14 #include "ui/gfx/frame_time.h"
15
16 namespace content {
17
18 RendererSchedulerImpl::RendererSchedulerImpl(
19 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner)
20 : helper_(main_task_runner,
21 this,
22 "renderer.scheduler",
23 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
24 "RendererSchedulerIdlePeriod",
25 TASK_QUEUE_COUNT,
26 base::TimeDelta()),
27 control_task_runner_(helper_.ControlTaskRunner()),
28 compositor_task_runner_(
29 helper_.TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)),
30 loading_task_runner_(helper_.TaskRunnerForQueue(LOADING_TASK_QUEUE)),
31 timer_task_runner_(helper_.TaskRunnerForQueue(TIMER_TASK_QUEUE)),
32 delayed_update_policy_runner_(
33 base::Bind(&RendererSchedulerImpl::UpdatePolicy,
34 base::Unretained(this)),
35 helper_.ControlTaskRunner()),
36 current_policy_(Policy::NORMAL),
37 renderer_hidden_(false),
38 last_input_type_(blink::WebInputEvent::Undefined),
39 input_stream_state_(InputStreamState::INACTIVE),
40 policy_may_need_update_(&incoming_signals_lock_),
41 timer_queue_suspend_count_(0),
42 weak_factory_(this) {
43 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
44 weak_factory_.GetWeakPtr());
45 end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
46 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
47
48 for (size_t i = SchedulerHelper::TASK_QUEUE_COUNT;
49 i < TASK_QUEUE_COUNT;
50 i++) {
51 helper_.SetQueueName(i, TaskQueueIdToString(static_cast<QueueId>(i)));
52 }
53 TRACE_EVENT_OBJECT_CREATED_WITH_ID(
54 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
55 this);
56 }
57
58 RendererSchedulerImpl::~RendererSchedulerImpl() {
59 TRACE_EVENT_OBJECT_DELETED_WITH_ID(
60 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
61 this);
62 }
63
64 void RendererSchedulerImpl::Shutdown() {
65 helper_.Shutdown();
66 }
67
68 scoped_refptr<base::SingleThreadTaskRunner>
69 RendererSchedulerImpl::DefaultTaskRunner() {
70 return helper_.DefaultTaskRunner();
71 }
72
73 scoped_refptr<base::SingleThreadTaskRunner>
74 RendererSchedulerImpl::CompositorTaskRunner() {
75 helper_.CheckOnValidThread();
76 return compositor_task_runner_;
77 }
78
79 scoped_refptr<SingleThreadIdleTaskRunner>
80 RendererSchedulerImpl::IdleTaskRunner() {
81 return helper_.IdleTaskRunner();
82 }
83
84 scoped_refptr<base::SingleThreadTaskRunner>
85 RendererSchedulerImpl::LoadingTaskRunner() {
86 helper_.CheckOnValidThread();
87 return loading_task_runner_;
88 }
89
90 scoped_refptr<base::SingleThreadTaskRunner>
91 RendererSchedulerImpl::TimerTaskRunner() {
92 helper_.CheckOnValidThread();
93 return timer_task_runner_;
94 }
95
96 bool RendererSchedulerImpl::CanExceedIdleDeadlineIfRequired() const {
97 return helper_.CanExceedIdleDeadlineIfRequired();
98 }
99
100 void RendererSchedulerImpl::AddTaskObserver(
101 base::MessageLoop::TaskObserver* task_observer) {
102 helper_.AddTaskObserver(task_observer);
103 }
104
105 void RendererSchedulerImpl::RemoveTaskObserver(
106 base::MessageLoop::TaskObserver* task_observer) {
107 helper_.RemoveTaskObserver(task_observer);
108 }
109
110 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
111 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
112 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue());
113 helper_.CheckOnValidThread();
114 if (helper_.IsShutdown())
115 return;
116
117 EndIdlePeriod();
118 estimated_next_frame_begin_ = args.frame_time + args.interval;
119 // TODO(skyostil): Wire up real notification of input events processing
120 // instead of this approximation.
121 DidProcessInputEvent(args.frame_time);
122 }
123
124 void RendererSchedulerImpl::DidCommitFrameToCompositor() {
125 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
126 "RendererSchedulerImpl::DidCommitFrameToCompositor");
127 helper_.CheckOnValidThread();
128 if (helper_.IsShutdown())
129 return;
130
131 base::TimeTicks now(helper_.Now());
132 if (now < estimated_next_frame_begin_) {
133 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of
134 // the next pending delayed tasks (as currently done in for long idle times)
135 helper_.StartIdlePeriod(
136 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
137 now,
138 estimated_next_frame_begin_,
139 true);
140 }
141 }
142
143 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() {
144 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
145 "RendererSchedulerImpl::BeginFrameNotExpectedSoon");
146 helper_.CheckOnValidThread();
147 if (helper_.IsShutdown())
148 return;
149
150 // TODO(skyostil): Wire up real notification of input events processing
151 // instead of this approximation.
152 DidProcessInputEvent(base::TimeTicks());
153
154 helper_.EnableLongIdlePeriod();
155 }
156
157 void RendererSchedulerImpl::OnRendererHidden() {
158 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
159 "RendererSchedulerImpl::OnRendererHidden");
160 helper_.CheckOnValidThread();
161 if (helper_.IsShutdown() || renderer_hidden_)
162 return;
163
164 helper_.EnableLongIdlePeriod();
165
166 // Ensure that we stop running idle tasks after a few seconds of being hidden.
167 end_renderer_hidden_idle_period_closure_.Cancel();
168 base::TimeDelta end_idle_when_hidden_delay =
169 base::TimeDelta::FromMilliseconds(kEndIdleWhenHiddenDelayMillis);
170 control_task_runner_->PostDelayedTask(
171 FROM_HERE,
172 end_renderer_hidden_idle_period_closure_.callback(),
173 end_idle_when_hidden_delay);
174 renderer_hidden_ = true;
175
176 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
177 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
178 this, AsValueLocked(helper_.Now()));
179 }
180
181 void RendererSchedulerImpl::OnRendererVisible() {
182 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
183 "RendererSchedulerImpl::OnRendererVisible");
184 helper_.CheckOnValidThread();
185 if (helper_.IsShutdown() || !renderer_hidden_)
186 return;
187
188 end_renderer_hidden_idle_period_closure_.Cancel();
189 renderer_hidden_ = false;
190 EndIdlePeriod();
191
192 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
193 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
194 this, AsValueLocked(helper_.Now()));
195 }
196
197 void RendererSchedulerImpl::EndIdlePeriod() {
198 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
199 "RendererSchedulerImpl::EndIdlePeriod");
200 helper_.CheckOnValidThread();
201 helper_.EndIdlePeriod();
202 }
203
204 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread(
205 const blink::WebInputEvent& web_input_event) {
206 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
207 "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread");
208 // We regard MouseMove events with the left mouse button down as a signal
209 // that the user is doing something requiring a smooth frame rate.
210 if (web_input_event.type == blink::WebInputEvent::MouseMove &&
211 (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
212 UpdateForInputEvent(web_input_event.type);
213 return;
214 }
215 // Ignore all other mouse events because they probably don't signal user
216 // interaction needing a smooth framerate. NOTE isMouseEventType returns false
217 // for mouse wheel events, hence we regard them as user input.
218 // Ignore keyboard events because it doesn't really make sense to enter
219 // compositor priority for them.
220 if (blink::WebInputEvent::isMouseEventType(web_input_event.type) ||
221 blink::WebInputEvent::isKeyboardEventType(web_input_event.type)) {
222 return;
223 }
224 UpdateForInputEvent(web_input_event.type);
225 }
226
227 void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() {
228 UpdateForInputEvent(blink::WebInputEvent::Undefined);
229 }
230
231 void RendererSchedulerImpl::UpdateForInputEvent(
232 blink::WebInputEvent::Type type) {
233 base::AutoLock lock(incoming_signals_lock_);
234
235 InputStreamState new_input_stream_state =
236 ComputeNewInputStreamState(input_stream_state_, type, last_input_type_);
237
238 if (input_stream_state_ != new_input_stream_state) {
239 // Update scheduler policy if we should start a new policy mode.
240 input_stream_state_ = new_input_stream_state;
241 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE);
242 }
243 last_input_receipt_time_on_compositor_ = helper_.Now();
244 // Clear the last known input processing time so that we know an input event
245 // is still queued up. This timestamp will be updated the next time the
246 // compositor commits or becomes quiescent. Note that this function is always
247 // called before the input event is processed either on the compositor or
248 // main threads.
249 last_input_process_time_on_main_ = base::TimeTicks();
250 last_input_type_ = type;
251 }
252
253 void RendererSchedulerImpl::DidProcessInputEvent(
254 base::TimeTicks begin_frame_time) {
255 helper_.CheckOnValidThread();
256 base::AutoLock lock(incoming_signals_lock_);
257 if (input_stream_state_ == InputStreamState::INACTIVE)
258 return;
259 // Avoid marking input that arrived after the BeginFrame as processed.
260 if (!begin_frame_time.is_null() &&
261 begin_frame_time < last_input_receipt_time_on_compositor_)
262 return;
263 last_input_process_time_on_main_ = helper_.Now();
264 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
265 }
266
267 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() {
268 helper_.CheckOnValidThread();
269 if (helper_.IsShutdown())
270 return false;
271
272 MaybeUpdatePolicy();
273 // The touchstart and compositor policies indicate a strong likelihood of
274 // high-priority work in the near future.
275 return SchedulerPolicy() == Policy::COMPOSITOR_PRIORITY ||
276 SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY;
277 }
278
279 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
280 helper_.CheckOnValidThread();
281 if (helper_.IsShutdown())
282 return false;
283
284 MaybeUpdatePolicy();
285 // We only yield if we are in the compositor priority and there is compositor
286 // work outstanding, or if we are in the touchstart response priority.
287 // Note: even though the control queue is higher priority we don't yield for
288 // it since these tasks are not user-provided work and they are only intended
289 // to run before the next task, not interrupt the tasks.
290 switch (SchedulerPolicy()) {
291 case Policy::NORMAL:
292 return false;
293
294 case Policy::COMPOSITOR_PRIORITY:
295 return !helper_.IsQueueEmpty(COMPOSITOR_TASK_QUEUE);
296
297 case Policy::TOUCHSTART_PRIORITY:
298 return true;
299
300 default:
301 NOTREACHED();
302 return false;
303 }
304 }
305
306 base::TimeTicks
307 RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() const {
308 base::TimeTicks deadline;
309 helper_.CurrentIdleTaskDeadlineCallback(&deadline);
310 return deadline;
311 }
312
313 RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const {
314 helper_.CheckOnValidThread();
315 return current_policy_;
316 }
317
318 void RendererSchedulerImpl::MaybeUpdatePolicy() {
319 helper_.CheckOnValidThread();
320 if (policy_may_need_update_.IsSet()) {
321 UpdatePolicy();
322 }
323 }
324
325 void RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
326 const tracked_objects::Location& from_here) {
327 // TODO(scheduler-dev): Check that this method isn't called from the main
328 // thread.
329 incoming_signals_lock_.AssertAcquired();
330 if (!policy_may_need_update_.IsSet()) {
331 policy_may_need_update_.SetWhileLocked(true);
332 control_task_runner_->PostTask(from_here, update_policy_closure_);
333 }
334 }
335
336 void RendererSchedulerImpl::UpdatePolicy() {
337 base::AutoLock lock(incoming_signals_lock_);
338 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
339 }
340
341 void RendererSchedulerImpl::ForceUpdatePolicy() {
342 base::AutoLock lock(incoming_signals_lock_);
343 UpdatePolicyLocked(UpdateType::FORCE_UPDATE);
344 }
345
346 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
347 helper_.CheckOnValidThread();
348 incoming_signals_lock_.AssertAcquired();
349 if (helper_.IsShutdown())
350 return;
351
352 base::TimeTicks now = helper_.Now();
353 policy_may_need_update_.SetWhileLocked(false);
354
355 base::TimeDelta new_policy_duration;
356 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration);
357 if (new_policy_duration > base::TimeDelta()) {
358 current_policy_expiration_time_ = now + new_policy_duration;
359 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
360 now);
361 } else {
362 current_policy_expiration_time_ = base::TimeTicks();
363 }
364
365 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED &&
366 new_policy == current_policy_)
367 return;
368
369 PrioritizingTaskQueueSelector* task_queue_selector =
370 helper_.SchedulerTaskQueueSelector();
371 bool policy_disables_timers = false;
372
373 switch (new_policy) {
374 case Policy::COMPOSITOR_PRIORITY:
375 task_queue_selector->SetQueuePriority(
376 COMPOSITOR_TASK_QUEUE, PrioritizingTaskQueueSelector::HIGH_PRIORITY);
377 // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT
378 // that still has some guarantee of running.
379 task_queue_selector->SetQueuePriority(
380 LOADING_TASK_QUEUE,
381 PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY);
382 break;
383 case Policy::TOUCHSTART_PRIORITY:
384 task_queue_selector->SetQueuePriority(
385 COMPOSITOR_TASK_QUEUE, PrioritizingTaskQueueSelector::HIGH_PRIORITY);
386 task_queue_selector->DisableQueue(LOADING_TASK_QUEUE);
387 // TODO(alexclarke): Set policy_disables_timers once the blink TimerBase
388 // refactor is safely landed.
389 break;
390 case Policy::NORMAL:
391 task_queue_selector->SetQueuePriority(
392 COMPOSITOR_TASK_QUEUE,
393 PrioritizingTaskQueueSelector::NORMAL_PRIORITY);
394 task_queue_selector->SetQueuePriority(
395 LOADING_TASK_QUEUE, PrioritizingTaskQueueSelector::NORMAL_PRIORITY);
396 break;
397 }
398 if (timer_queue_suspend_count_ != 0 || policy_disables_timers) {
399 task_queue_selector->DisableQueue(TIMER_TASK_QUEUE);
400 } else {
401 helper_.SchedulerTaskQueueSelector()->SetQueuePriority(
402 TIMER_TASK_QUEUE, PrioritizingTaskQueueSelector::NORMAL_PRIORITY);
403 }
404 DCHECK(task_queue_selector->IsQueueEnabled(COMPOSITOR_TASK_QUEUE));
405 if (new_policy != Policy::TOUCHSTART_PRIORITY)
406 DCHECK(task_queue_selector->IsQueueEnabled(LOADING_TASK_QUEUE));
407
408 current_policy_ = new_policy;
409
410 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
411 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
412 this, AsValueLocked(now));
413 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
414 "RendererScheduler.policy", current_policy_);
415 }
416
417 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy(
418 base::TimeTicks now,
419 base::TimeDelta* new_policy_duration) {
420 helper_.CheckOnValidThread();
421 incoming_signals_lock_.AssertAcquired();
422
423 Policy new_policy = Policy::NORMAL;
424 *new_policy_duration = base::TimeDelta();
425
426 if (input_stream_state_ == InputStreamState::INACTIVE)
427 return new_policy;
428
429 Policy input_priority_policy =
430 input_stream_state_ ==
431 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE
432 ? Policy::TOUCHSTART_PRIORITY
433 : Policy::COMPOSITOR_PRIORITY;
434 base::TimeDelta time_left_in_policy = TimeLeftInInputEscalatedPolicy(now);
435 if (time_left_in_policy > base::TimeDelta()) {
436 new_policy = input_priority_policy;
437 *new_policy_duration = time_left_in_policy;
438 } else {
439 // Reset |input_stream_state_| to ensure
440 // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task
441 // when it's next called.
442 input_stream_state_ = InputStreamState::INACTIVE;
443 }
444 return new_policy;
445 }
446
447 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy(
448 base::TimeTicks now) const {
449 helper_.CheckOnValidThread();
450 // TODO(rmcilroy): Change this to DCHECK_EQ when crbug.com/463869 is fixed.
451 DCHECK(input_stream_state_ != InputStreamState::INACTIVE);
452 incoming_signals_lock_.AssertAcquired();
453
454 base::TimeDelta escalated_priority_duration =
455 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis);
456 base::TimeDelta time_left_in_policy;
457 if (last_input_process_time_on_main_.is_null() &&
458 !helper_.IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) {
459 // If the input event is still pending, go into input prioritized policy
460 // and check again later.
461 time_left_in_policy = escalated_priority_duration;
462 } else {
463 // Otherwise make sure the input prioritization policy ends on time.
464 base::TimeTicks new_priority_end(
465 std::max(last_input_receipt_time_on_compositor_,
466 last_input_process_time_on_main_) +
467 escalated_priority_duration);
468 time_left_in_policy = new_priority_end - now;
469 }
470 return time_left_in_policy;
471 }
472
473 bool RendererSchedulerImpl::CanEnterLongIdlePeriod(
474 base::TimeTicks now,
475 base::TimeDelta* next_long_idle_period_delay_out) {
476 helper_.CheckOnValidThread();
477
478 MaybeUpdatePolicy();
479 if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) {
480 // Don't start a long idle task in touch start priority, try again when
481 // the policy is scheduled to end.
482 *next_long_idle_period_delay_out = current_policy_expiration_time_ - now;
483 return false;
484 }
485 return true;
486 }
487
488 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() {
489 return &helper_;
490 }
491
492 void RendererSchedulerImpl::SetWorkBatchSizeForTesting(size_t work_batch_size) {
493 helper_.SetWorkBatchSizeForTesting(work_batch_size);
494 }
495
496 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag(
497 base::Lock* write_lock_)
498 : flag_(false), write_lock_(write_lock_) {
499 }
500
501 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() {
502 }
503
504 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetWhileLocked(
505 bool value) {
506 write_lock_->AssertAcquired();
507 base::subtle::Release_Store(&flag_, value);
508 }
509
510 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const {
511 return base::subtle::Acquire_Load(&flag_) != 0;
512 }
513
514 void RendererSchedulerImpl::SuspendTimerQueue() {
515 helper_.CheckOnValidThread();
516 timer_queue_suspend_count_++;
517 ForceUpdatePolicy();
518 DCHECK(!helper_.SchedulerTaskQueueSelector()->IsQueueEnabled(
519 TIMER_TASK_QUEUE));
520 }
521
522 void RendererSchedulerImpl::ResumeTimerQueue() {
523 helper_.CheckOnValidThread();
524 timer_queue_suspend_count_--;
525 DCHECK_GE(timer_queue_suspend_count_, 0);
526 ForceUpdatePolicy();
527 }
528
529 // static
530 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) {
531 switch (queue_id) {
532 case COMPOSITOR_TASK_QUEUE:
533 return "compositor_tq";
534 case LOADING_TASK_QUEUE:
535 return "loading_tq";
536 case TIMER_TASK_QUEUE:
537 return "timer_tq";
538 default:
539 return SchedulerHelper::TaskQueueIdToString(
540 static_cast<SchedulerHelper::QueueId>(queue_id));
541 }
542 }
543
544 // static
545 const char* RendererSchedulerImpl::PolicyToString(Policy policy) {
546 switch (policy) {
547 case Policy::NORMAL:
548 return "normal";
549 case Policy::COMPOSITOR_PRIORITY:
550 return "compositor";
551 case Policy::TOUCHSTART_PRIORITY:
552 return "touchstart";
553 default:
554 NOTREACHED();
555 return nullptr;
556 }
557 }
558
559 const char* RendererSchedulerImpl::InputStreamStateToString(
560 InputStreamState state) {
561 switch (state) {
562 case InputStreamState::INACTIVE:
563 return "inactive";
564 case InputStreamState::ACTIVE:
565 return "active";
566 case InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE:
567 return "active_and_awaiting_touchstart_response";
568 default:
569 NOTREACHED();
570 return nullptr;
571 }
572 }
573
574 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
575 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
576 helper_.CheckOnValidThread();
577 incoming_signals_lock_.AssertAcquired();
578
579 if (optional_now.is_null())
580 optional_now = helper_.Now();
581 scoped_refptr<base::trace_event::TracedValue> state =
582 new base::trace_event::TracedValue();
583
584 state->SetString("current_policy", PolicyToString(current_policy_));
585 state->SetString("idle_period_state",
586 SchedulerHelper::IdlePeriodStateToString(
587 helper_.SchedulerIdlePeriodState()));
588 state->SetBoolean("renderer_hidden_", renderer_hidden_);
589 state->SetString("input_stream_state",
590 InputStreamStateToString(input_stream_state_));
591 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF());
592 state->SetDouble("last_input_receipt_time_on_compositor_",
593 (last_input_receipt_time_on_compositor_ - base::TimeTicks())
594 .InMillisecondsF());
595 state->SetDouble(
596 "last_input_process_time_on_main_",
597 (last_input_process_time_on_main_ - base::TimeTicks()).InMillisecondsF());
598 state->SetDouble(
599 "estimated_next_frame_begin",
600 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF());
601
602 return state;
603 }
604
605 RendererSchedulerImpl::InputStreamState
606 RendererSchedulerImpl::ComputeNewInputStreamState(
607 InputStreamState current_state,
608 blink::WebInputEvent::Type new_input_type,
609 blink::WebInputEvent::Type last_input_type) {
610 switch (new_input_type) {
611 case blink::WebInputEvent::TouchStart:
612 return InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE;
613
614 case blink::WebInputEvent::TouchMove:
615 // Observation of consecutive touchmoves is a strong signal that the page
616 // is consuming the touch sequence, in which case touchstart response
617 // prioritization is no longer necessary. Otherwise, the initial touchmove
618 // should preserve the touchstart response pending state.
619 if (current_state ==
620 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE) {
621 return last_input_type == blink::WebInputEvent::TouchMove
622 ? InputStreamState::ACTIVE
623 : InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE;
624 }
625 break;
626
627 case blink::WebInputEvent::GestureTapDown:
628 case blink::WebInputEvent::GestureShowPress:
629 case blink::WebInputEvent::GestureFlingCancel:
630 case blink::WebInputEvent::GestureScrollEnd:
631 // With no observable effect, these meta events do not indicate a
632 // meaningful touchstart response and should not impact task priority.
633 return current_state;
634
635 default:
636 break;
637 }
638 return InputStreamState::ACTIVE;
639 }
640
641 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/scheduler/renderer_scheduler_impl.h ('k') | content/renderer/scheduler/renderer_scheduler_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698