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 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 |