Chromium Code Reviews| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 100 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
| 100 begin_unthrottled_frame_closure_ = | 101 begin_unthrottled_frame_closure_ = |
| 101 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | 102 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); |
| 102 begin_impl_frame_deadline_closure_ = base::Bind( | 103 begin_impl_frame_deadline_closure_ = base::Bind( |
| 103 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 104 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| 104 poll_for_draw_triggers_closure_ = base::Bind( | 105 poll_for_draw_triggers_closure_ = base::Bind( |
| 105 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 106 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
| 106 advance_commit_state_closure_ = base::Bind( | 107 advance_commit_state_closure_ = base::Bind( |
| 107 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 108 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
| 108 | 109 |
| 110 if (settings_.high_latency_mode_on_battery) { | |
| 111 SetupPowerMonitoring(); | |
| 112 } | |
| 113 | |
| 109 if (!settings_.begin_frame_scheduling_enabled) { | 114 if (!settings_.begin_frame_scheduling_enabled) { |
| 110 SetupSyntheticBeginFrames(); | 115 SetupSyntheticBeginFrames(); |
| 111 } | 116 } |
| 112 } | 117 } |
| 113 | 118 |
| 114 Scheduler::~Scheduler() { | 119 Scheduler::~Scheduler() { |
| 120 if (settings_.high_latency_mode_on_battery) { | |
| 121 TeardownPowerMonitoring(); | |
| 122 } | |
| 123 | |
| 115 if (synthetic_begin_frame_source_) { | 124 if (synthetic_begin_frame_source_) { |
| 116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 125 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
| 117 &begin_retro_frame_args_); | 126 &begin_retro_frame_args_); |
| 118 } | 127 } |
| 119 } | 128 } |
| 120 | 129 |
| 121 void Scheduler::SetupSyntheticBeginFrames() { | 130 void Scheduler::SetupSyntheticBeginFrames() { |
| 122 scoped_refptr<DelayBasedTimeSource> time_source; | 131 scoped_refptr<DelayBasedTimeSource> time_source; |
| 123 if (gfx::FrameTime::TimestampsAreHighRes()) { | 132 if (gfx::FrameTime::TimestampsAreHighRes()) { |
| 124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), | 133 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), |
| 125 task_runner_.get()); | 134 task_runner_.get()); |
| 126 } else { | 135 } else { |
| 127 time_source = | 136 time_source = |
| 128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); | 137 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); |
| 129 } | 138 } |
| 130 DCHECK(!synthetic_begin_frame_source_); | 139 DCHECK(!synthetic_begin_frame_source_); |
| 131 synthetic_begin_frame_source_.reset( | 140 synthetic_begin_frame_source_.reset( |
| 132 new SyntheticBeginFrameSource(this, time_source)); | 141 new SyntheticBeginFrameSource(this, time_source)); |
| 133 } | 142 } |
| 134 | 143 |
| 135 base::TimeTicks Scheduler::Now() const { | 144 base::TimeTicks Scheduler::Now() const { |
| 136 return gfx::FrameTime::Now(); | 145 return gfx::FrameTime::Now(); |
| 137 } | 146 } |
| 138 | 147 |
| 148 void Scheduler::SetupPowerMonitoring() { | |
| 149 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | |
| 150 DCHECK(power_monitor != NULL); | |
| 151 power_monitor->AddObserver(this); | |
| 152 on_battery_power_ = power_monitor->IsOnBatteryPower(); | |
| 153 } | |
| 154 | |
| 155 void Scheduler::TeardownPowerMonitoring() { | |
| 156 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | |
| 157 DCHECK(power_monitor != NULL); | |
| 158 power_monitor->RemoveObserver(this); | |
| 159 } | |
| 160 | |
| 161 void Scheduler::OnPowerStateChange(bool on_battery_power) { | |
| 162 on_battery_power_ = on_battery_power; | |
| 163 } | |
| 164 | |
| 139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 165 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
| 140 base::TimeDelta interval) { | 166 base::TimeDelta interval) { |
| 141 // TODO(brianderson): We should not be receiving 0 intervals. | 167 // TODO(brianderson): We should not be receiving 0 intervals. |
| 142 if (interval == base::TimeDelta()) | 168 if (interval == base::TimeDelta()) |
| 143 interval = BeginFrameArgs::DefaultInterval(); | 169 interval = BeginFrameArgs::DefaultInterval(); |
| 144 vsync_interval_ = interval; | 170 vsync_interval_ = interval; |
| 145 if (!settings_.begin_frame_scheduling_enabled) | 171 if (!settings_.begin_frame_scheduling_enabled) |
| 146 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 172 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); |
| 147 } | 173 } |
| 148 | 174 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 DCHECK(!settings_.using_synchronous_renderer_compositor); | 525 DCHECK(!settings_.using_synchronous_renderer_compositor); |
| 500 | 526 |
| 501 if (state_machine_.begin_impl_frame_state() != | 527 if (state_machine_.begin_impl_frame_state() != |
| 502 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) | 528 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) |
| 503 return; | 529 return; |
| 504 | 530 |
| 505 begin_retro_frame_posted_ = true; | 531 begin_retro_frame_posted_ = true; |
| 506 task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); | 532 task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); |
| 507 } | 533 } |
| 508 | 534 |
| 535 bool Scheduler::ShouldPostBeginImplFrameDeadline() const { | |
| 536 // The synchronous renderer compositor has to make its GL calls | |
| 537 // within the BeginFrame call stack. | |
| 538 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
| 539 // so the sychronous renderer compositor can take advantage of splitting | |
| 540 // up the BeginImplFrame and deadline as well. | |
| 541 if (settings_.using_synchronous_renderer_compositor) | |
| 542 return false; | |
| 543 | |
| 544 if (settings_.high_latency_mode_on_battery && on_battery_power_) | |
|
brianderson
2014/09/12 22:05:27
Please add a comment above this if.
| |
| 545 return false; | |
| 546 | |
| 547 return true; | |
| 548 } | |
| 549 | |
| 509 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 550 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
| 510 // for a BeginMainFrame+activation to complete before it times out and draws | 551 // for a BeginMainFrame+activation to complete before it times out and draws |
| 511 // any asynchronous animation and scroll/pinch updates. | 552 // any asynchronous animation and scroll/pinch updates. |
| 512 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 553 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
| 513 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue()); | 554 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue()); |
| 514 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 555 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 515 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 556 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 516 DCHECK(state_machine_.HasInitializedOutputSurface()); | 557 DCHECK(state_machine_.HasInitializedOutputSurface()); |
| 558 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | |
| 517 | 559 |
| 518 advance_commit_state_task_.Cancel(); | 560 advance_commit_state_task_.Cancel(); |
| 519 | 561 |
| 520 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 562 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
| 521 begin_impl_frame_args_ = args; | 563 begin_impl_frame_args_ = args; |
| 522 begin_impl_frame_args_.deadline -= draw_duration_estimate; | 564 begin_impl_frame_args_.deadline -= draw_duration_estimate; |
| 523 | 565 |
| 524 if (!state_machine_.impl_latency_takes_priority() && | 566 if (!state_machine_.impl_latency_takes_priority() && |
| 525 state_machine_.MainThreadIsInHighLatencyMode() && | 567 state_machine_.MainThreadIsInHighLatencyMode() && |
| 526 CanCommitAndActivateBeforeDeadline()) { | 568 CanCommitAndActivateBeforeDeadline()) { |
| 527 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 569 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| 528 } | 570 } |
| 529 | 571 |
| 530 client_->WillBeginImplFrame(begin_impl_frame_args_); | 572 client_->WillBeginImplFrame(begin_impl_frame_args_); |
| 531 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); | 573 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); |
| 532 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 574 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
| 533 | 575 |
| 534 ProcessScheduledActions(); | 576 ProcessScheduledActions(); |
| 535 | 577 |
| 536 state_machine_.OnBeginImplFrameDeadlinePending(); | 578 state_machine_.OnBeginImplFrameDeadlinePending(); |
| 537 ScheduleBeginImplFrameDeadline( | 579 |
| 538 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | 580 if (ShouldPostBeginImplFrameDeadline()) { |
| 581 ScheduleBeginImplFrameDeadline( | |
| 582 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | |
| 583 } else { | |
| 584 OnBeginImplFrameDeadline(); | |
|
brianderson
2014/09/12 22:05:27
After thinking about this some more, I am a bit co
sunnyps
2014/09/15 21:52:48
An immediate task will also take 15 ms before it e
sunnyps
2014/09/16 21:30:31
I've gone through some of the MessageLoop/MessageP
| |
| 585 } | |
| 539 } | 586 } |
| 540 | 587 |
| 541 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( | 588 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( |
| 542 const BeginFrameArgs& args, | 589 const BeginFrameArgs& args, |
| 543 base::TimeDelta draw_duration_estimate) const { | 590 base::TimeDelta draw_duration_estimate) const { |
| 544 if (settings_.using_synchronous_renderer_compositor) { | 591 if (!ShouldPostBeginImplFrameDeadline()) { |
| 545 // The synchronous compositor needs to draw right away. | |
| 546 return base::TimeTicks(); | 592 return base::TimeTicks(); |
| 547 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | 593 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { |
| 548 // We are ready to draw a new active tree immediately. | 594 // We are ready to draw a new active tree immediately. |
| 549 return base::TimeTicks(); | 595 return base::TimeTicks(); |
| 550 } else if (state_machine_.needs_redraw()) { | 596 } else if (state_machine_.needs_redraw()) { |
| 551 // We have an animation or fast input path on the impl thread that wants | 597 // We have an animation or fast input path on the impl thread that wants |
| 552 // to draw, so don't wait too long for a new active tree. | 598 // to draw, so don't wait too long for a new active tree. |
| 553 return args.deadline - draw_duration_estimate; | 599 return args.deadline - draw_duration_estimate; |
| 554 } else { | 600 } else { |
| 555 // The impl thread doesn't have anything it wants to draw and we are just | 601 // The impl thread doesn't have anything it wants to draw and we are just |
| 556 // waiting for a new active tree, so post the deadline for the next | 602 // waiting for a new active tree, so post the deadline for the next |
| 557 // expected BeginImplFrame start. This allows us to draw immediately when | 603 // expected BeginImplFrame start. This allows us to draw immediately when |
| 558 // there is a new active tree, instead of waiting for the next | 604 // there is a new active tree, instead of waiting for the next |
| 559 // BeginImplFrame. | 605 // BeginImplFrame. |
| 560 // TODO(brianderson): Handle long deadlines (that are past the next frame's | 606 // TODO(brianderson): Handle long deadlines (that are past the next frame's |
| 561 // frame time) properly instead of using this hack. | 607 // frame time) properly instead of using this hack. |
| 562 return args.frame_time + args.interval; | 608 return args.frame_time + args.interval; |
| 563 } | 609 } |
| 564 } | 610 } |
| 565 | 611 |
| 566 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | 612 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { |
| 567 TRACE_EVENT1( | 613 TRACE_EVENT1( |
| 568 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); | 614 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); |
| 569 if (settings_.using_synchronous_renderer_compositor) { | |
| 570 // The synchronous renderer compositor has to make its GL calls | |
| 571 // within this call. | |
| 572 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
| 573 // so the sychronous renderer compositor can take advantage of splitting | |
| 574 // up the BeginImplFrame and deadline as well. | |
| 575 OnBeginImplFrameDeadline(); | |
| 576 return; | |
| 577 } | |
| 578 begin_impl_frame_deadline_task_.Cancel(); | 615 begin_impl_frame_deadline_task_.Cancel(); |
| 579 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 616 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
| 580 | 617 |
| 581 base::TimeDelta delta = deadline - Now(); | 618 base::TimeDelta delta = deadline - Now(); |
| 582 if (delta <= base::TimeDelta()) | 619 if (delta <= base::TimeDelta()) |
| 583 delta = base::TimeDelta(); | 620 delta = base::TimeDelta(); |
| 584 task_runner_->PostDelayedTask( | 621 task_runner_->PostDelayedTask( |
| 585 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 622 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
| 586 } | 623 } |
| 587 | 624 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 763 } | 800 } |
| 764 | 801 |
| 765 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 802 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 766 return (state_machine_.commit_state() == | 803 return (state_machine_.commit_state() == |
| 767 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 804 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
| 768 state_machine_.commit_state() == | 805 state_machine_.commit_state() == |
| 769 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 806 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
| 770 } | 807 } |
| 771 | 808 |
| 772 } // namespace cc | 809 } // namespace cc |
| OLD | NEW |