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 | 4 |
5 #include "cc/scheduler/scheduler.h" | 5 #include "cc/scheduler/scheduler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include "base/auto_reset.h" | 8 #include "base/auto_reset.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/debug/trace_event_argument.h" | 10 #include "base/debug/trace_event_argument.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/power_monitor/power_monitor.h" | |
12 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
13 #include "cc/debug/devtools_instrumentation.h" | 14 #include "cc/debug/devtools_instrumentation.h" |
14 #include "cc/debug/traced_value.h" | 15 #include "cc/debug/traced_value.h" |
15 #include "cc/scheduler/delay_based_time_source.h" | 16 #include "cc/scheduler/delay_based_time_source.h" |
16 #include "ui/gfx/frame_time.h" | 17 #include "ui/gfx/frame_time.h" |
17 | 18 |
18 namespace cc { | 19 namespace cc { |
19 | 20 |
20 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( | 21 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( |
21 Scheduler* scheduler, | 22 Scheduler* scheduler, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 107 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
107 begin_unthrottled_frame_closure_ = | 108 begin_unthrottled_frame_closure_ = |
108 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | 109 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); |
109 begin_impl_frame_deadline_closure_ = base::Bind( | 110 begin_impl_frame_deadline_closure_ = base::Bind( |
110 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 111 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
111 poll_for_draw_triggers_closure_ = base::Bind( | 112 poll_for_draw_triggers_closure_ = base::Bind( |
112 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 113 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
113 advance_commit_state_closure_ = base::Bind( | 114 advance_commit_state_closure_ = base::Bind( |
114 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 115 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
115 | 116 |
117 if (settings_.high_latency_mode_on_battery) { | |
118 SetupPowerMonitoring(); | |
119 } | |
120 | |
116 if (!settings_.begin_frame_scheduling_enabled) { | 121 if (!settings_.begin_frame_scheduling_enabled) { |
117 SetupSyntheticBeginFrames(); | 122 SetupSyntheticBeginFrames(); |
118 } | 123 } |
119 } | 124 } |
120 | 125 |
121 Scheduler::~Scheduler() { | 126 Scheduler::~Scheduler() { |
127 if (settings_.high_latency_mode_on_battery) { | |
128 TeardownPowerMonitoring(); | |
129 } | |
130 | |
122 if (synthetic_begin_frame_source_) { | 131 if (synthetic_begin_frame_source_) { |
123 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 132 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
124 &begin_retro_frame_args_); | 133 &begin_retro_frame_args_); |
125 } | 134 } |
126 } | 135 } |
127 | 136 |
128 void Scheduler::SetupSyntheticBeginFrames() { | 137 void Scheduler::SetupSyntheticBeginFrames() { |
129 DCHECK(!synthetic_begin_frame_source_); | 138 DCHECK(!synthetic_begin_frame_source_); |
130 synthetic_begin_frame_source_.reset( | 139 synthetic_begin_frame_source_.reset( |
131 new SyntheticBeginFrameSource(this, task_runner_.get())); | 140 new SyntheticBeginFrameSource(this, task_runner_.get())); |
132 } | 141 } |
133 | 142 |
143 void Scheduler::SetupPowerMonitoring() { | |
144 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | |
145 DCHECK(power_monitor != NULL); | |
146 power_monitor->AddObserver(this); | |
147 } | |
148 | |
149 void Scheduler::TeardownPowerMonitoring() { | |
150 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | |
151 DCHECK(power_monitor != NULL); | |
152 power_monitor->RemoveObserver(this); | |
153 } | |
154 | |
155 void Scheduler::OnPowerStateChange(bool on_battery_power) { | |
156 on_battery_power_ = on_battery_power; | |
157 } | |
158 | |
134 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 159 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
135 base::TimeDelta interval) { | 160 base::TimeDelta interval) { |
136 // TODO(brianderson): We should not be receiving 0 intervals. | 161 // TODO(brianderson): We should not be receiving 0 intervals. |
137 if (interval == base::TimeDelta()) | 162 if (interval == base::TimeDelta()) |
138 interval = BeginFrameArgs::DefaultInterval(); | 163 interval = BeginFrameArgs::DefaultInterval(); |
139 vsync_interval_ = interval; | 164 vsync_interval_ = interval; |
140 if (!settings_.begin_frame_scheduling_enabled) | 165 if (!settings_.begin_frame_scheduling_enabled) |
141 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 166 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); |
142 } | 167 } |
143 | 168 |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 DCHECK(!settings_.using_synchronous_renderer_compositor); | 515 DCHECK(!settings_.using_synchronous_renderer_compositor); |
491 | 516 |
492 if (state_machine_.begin_impl_frame_state() != | 517 if (state_machine_.begin_impl_frame_state() != |
493 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) | 518 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) |
494 return; | 519 return; |
495 | 520 |
496 begin_retro_frame_posted_ = true; | 521 begin_retro_frame_posted_ = true; |
497 task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); | 522 task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); |
498 } | 523 } |
499 | 524 |
525 bool Scheduler::ShouldPostBeginImplFrameDeadline() { | |
526 // The synchronous renderer compositor has to make its GL calls | |
527 // within this call. | |
brianderson
2014/09/09 17:59:05
this call -> within the BeginFrame call stack.
| |
528 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
529 // so the sychronous renderer compositor can take advantage of splitting | |
530 // up the BeginImplFrame and deadline as well. | |
531 if (settings_.using_synchronous_renderer_compositor) | |
532 return false; | |
533 | |
534 if (settings_.high_latency_mode_on_battery && on_battery_power_) | |
535 return false; | |
536 | |
537 // We are ready to draw a new active tree immediately. | |
538 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) | |
539 return false; | |
540 | |
541 return true; | |
542 } | |
543 | |
500 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 544 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
501 // for a BeginMainFrame+activation to complete before it times out and draws | 545 // for a BeginMainFrame+activation to complete before it times out and draws |
502 // any asynchronous animation and scroll/pinch updates. | 546 // any asynchronous animation and scroll/pinch updates. |
503 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 547 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
504 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue()); | 548 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue()); |
505 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 549 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
506 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 550 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
507 DCHECK(state_machine_.HasInitializedOutputSurface()); | 551 DCHECK(state_machine_.HasInitializedOutputSurface()); |
552 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | |
508 | 553 |
509 advance_commit_state_task_.Cancel(); | 554 advance_commit_state_task_.Cancel(); |
510 | 555 |
511 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 556 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
512 begin_impl_frame_args_ = args; | 557 begin_impl_frame_args_ = args; |
513 begin_impl_frame_args_.deadline -= draw_duration_estimate; | 558 begin_impl_frame_args_.deadline -= draw_duration_estimate; |
514 | 559 |
515 if (!state_machine_.impl_latency_takes_priority() && | 560 if (!state_machine_.impl_latency_takes_priority() && |
516 state_machine_.MainThreadIsInHighLatencyMode() && | 561 state_machine_.MainThreadIsInHighLatencyMode() && |
517 CanCommitAndActivateBeforeDeadline()) { | 562 CanCommitAndActivateBeforeDeadline()) { |
518 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 563 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
519 } | 564 } |
520 | 565 |
521 client_->WillBeginImplFrame(begin_impl_frame_args_); | 566 client_->WillBeginImplFrame(begin_impl_frame_args_); |
522 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); | 567 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); |
523 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 568 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
524 | 569 |
525 ProcessScheduledActions(); | 570 ProcessScheduledActions(); |
526 | 571 |
527 state_machine_.OnBeginImplFrameDeadlinePending(); | 572 state_machine_.OnBeginImplFrameDeadlinePending(); |
528 ScheduleBeginImplFrameDeadline( | 573 |
529 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | 574 if (ShouldPostBeginImplFrameDeadline()) { |
575 ScheduleBeginImplFrameDeadline( | |
576 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | |
577 } else { | |
578 OnBeginImplFrameDeadline(); | |
579 } | |
530 } | 580 } |
531 | 581 |
532 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( | 582 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( |
533 const BeginFrameArgs& args, | 583 const BeginFrameArgs& args, |
534 base::TimeDelta draw_duration_estimate) const { | 584 base::TimeDelta draw_duration_estimate) const { |
535 if (settings_.using_synchronous_renderer_compositor) { | 585 if (state_machine_.needs_redraw()) { |
brianderson
2014/09/09 17:59:05
AdjustedBeginImplFrameDeadline is used in more tha
| |
536 // The synchronous compositor needs to draw right away. | |
537 return base::TimeTicks(); | |
538 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | |
539 // We are ready to draw a new active tree immediately. | |
540 return base::TimeTicks(); | |
541 } else if (state_machine_.needs_redraw()) { | |
542 // We have an animation or fast input path on the impl thread that wants | 586 // We have an animation or fast input path on the impl thread that wants |
543 // to draw, so don't wait too long for a new active tree. | 587 // to draw, so don't wait too long for a new active tree. |
544 return args.deadline - draw_duration_estimate; | 588 return args.deadline - draw_duration_estimate; |
545 } else { | 589 } else { |
546 // The impl thread doesn't have anything it wants to draw and we are just | 590 // The impl thread doesn't have anything it wants to draw and we are just |
547 // waiting for a new active tree, so post the deadline for the next | 591 // waiting for a new active tree, so post the deadline for the next |
548 // expected BeginImplFrame start. This allows us to draw immediately when | 592 // expected BeginImplFrame start. This allows us to draw immediately when |
549 // there is a new active tree, instead of waiting for the next | 593 // there is a new active tree, instead of waiting for the next |
550 // BeginImplFrame. | 594 // BeginImplFrame. |
551 // TODO(brianderson): Handle long deadlines (that are past the next frame's | 595 // TODO(brianderson): Handle long deadlines (that are past the next frame's |
552 // frame time) properly instead of using this hack. | 596 // frame time) properly instead of using this hack. |
553 return args.frame_time + args.interval; | 597 return args.frame_time + args.interval; |
554 } | 598 } |
555 } | 599 } |
556 | 600 |
557 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | 601 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { |
558 if (settings_.using_synchronous_renderer_compositor) { | |
559 // The synchronous renderer compositor has to make its GL calls | |
560 // within this call. | |
561 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
562 // so the sychronous renderer compositor can take advantage of splitting | |
563 // up the BeginImplFrame and deadline as well. | |
564 OnBeginImplFrameDeadline(); | |
565 return; | |
566 } | |
567 begin_impl_frame_deadline_task_.Cancel(); | 602 begin_impl_frame_deadline_task_.Cancel(); |
568 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 603 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
569 | 604 |
570 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); | 605 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); |
571 if (delta <= base::TimeDelta()) | 606 if (delta <= base::TimeDelta()) |
572 delta = base::TimeDelta(); | 607 delta = base::TimeDelta(); |
573 task_runner_->PostDelayedTask( | 608 task_runner_->PostDelayedTask( |
574 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 609 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
575 } | 610 } |
576 | 611 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
753 } | 788 } |
754 | 789 |
755 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 790 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
756 return (state_machine_.commit_state() == | 791 return (state_machine_.commit_state() == |
757 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 792 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
758 state_machine_.commit_state() == | 793 state_machine_.commit_state() == |
759 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 794 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
760 } | 795 } |
761 | 796 |
762 } // namespace cc | 797 } // namespace cc |
OLD | NEW |