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

Side by Side Diff: cc/scheduler/scheduler.cc

Issue 554973002: Disable scheduler deadline task on battery power in Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address code review nit Created 6 years, 3 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698