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

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

Issue 387493002: Fixing and enhancing OrderedSimpleTaskRunner to allow 100% deterministic tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Lots of changes. Created 6 years, 5 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 | Annotate | Revision Log
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/logging.h" 10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
12 #include "cc/debug/devtools_instrumentation.h" 12 #include "cc/debug/devtools_instrumentation.h"
13 #include "cc/debug/traced_value.h" 13 #include "cc/debug/traced_value.h"
14 #include "cc/scheduler/delay_based_time_source.h" 14 #include "cc/scheduler/delay_based_time_source.h"
15 #include "ui/gfx/frame_time.h"
16 15
17 namespace cc { 16 namespace cc {
18 17
19 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( 18 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource(
20 Scheduler* scheduler, 19 Scheduler* scheduler,
21 base::SingleThreadTaskRunner* task_runner) 20 scoped_refptr<DelayBasedTimeSource>& time_source)
22 : scheduler_(scheduler) { 21 : scheduler_(scheduler), time_source_(time_source) {
23 if (gfx::FrameTime::TimestampsAreHighRes()) {
24 time_source_ = DelayBasedTimeSourceHighRes::Create(
25 scheduler_->VSyncInterval(), task_runner);
26 } else {
27 time_source_ = DelayBasedTimeSource::Create(scheduler_->VSyncInterval(),
28 task_runner);
29 }
30 time_source_->SetClient(this); 22 time_source_->SetClient(this);
31 } 23 }
32 24
33 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { 25 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
34 } 26 }
35 27
36 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters( 28 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters(
37 base::TimeTicks timebase, 29 base::TimeTicks timebase,
38 base::TimeDelta interval) { 30 base::TimeDelta interval) {
39 time_source_->SetTimebaseAndInterval(timebase, interval); 31 time_source_->SetTimebaseAndInterval(timebase, interval);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 109 }
118 110
119 Scheduler::~Scheduler() { 111 Scheduler::~Scheduler() {
120 if (synthetic_begin_frame_source_) { 112 if (synthetic_begin_frame_source_) {
121 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, 113 synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
122 &begin_retro_frame_args_); 114 &begin_retro_frame_args_);
123 } 115 }
124 } 116 }
125 117
126 void Scheduler::SetupSyntheticBeginFrames() { 118 void Scheduler::SetupSyntheticBeginFrames() {
119 scoped_refptr<DelayBasedTimeSource> time_source;
120 if (gfx::FrameTime::TimestampsAreHighRes()) {
121 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(),
122 impl_task_runner_.get());
123 } else {
124 time_source =
125 DelayBasedTimeSource::Create(VSyncInterval(), impl_task_runner_.get());
126 }
127 DCHECK(!synthetic_begin_frame_source_); 127 DCHECK(!synthetic_begin_frame_source_);
128 synthetic_begin_frame_source_.reset( 128 synthetic_begin_frame_source_.reset(
129 new SyntheticBeginFrameSource(this, impl_task_runner_.get())); 129 new SyntheticBeginFrameSource(this, time_source));
130 }
131
132 base::TimeTicks Scheduler::Now() const {
133 return gfx::FrameTime::Now();
130 } 134 }
131 135
132 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, 136 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
133 base::TimeDelta interval) { 137 base::TimeDelta interval) {
134 // TODO(brianderson): We should not be receiving 0 intervals. 138 // TODO(brianderson): We should not be receiving 0 intervals.
135 if (interval == base::TimeDelta()) 139 if (interval == base::TimeDelta())
136 interval = BeginFrameArgs::DefaultInterval(); 140 interval = BeginFrameArgs::DefaultInterval();
137 vsync_interval_ = interval; 141 vsync_interval_ = interval;
138 if (!settings_.begin_frame_scheduling_enabled) 142 if (!settings_.begin_frame_scheduling_enabled)
139 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); 143 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 void Scheduler::NotifyBeginMainFrameStarted() { 257 void Scheduler::NotifyBeginMainFrameStarted() {
254 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); 258 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
255 state_machine_.NotifyBeginMainFrameStarted(); 259 state_machine_.NotifyBeginMainFrameStarted();
256 } 260 }
257 261
258 base::TimeTicks Scheduler::AnticipatedDrawTime() const { 262 base::TimeTicks Scheduler::AnticipatedDrawTime() const {
259 if (!last_set_needs_begin_frame_ || 263 if (!last_set_needs_begin_frame_ ||
260 begin_impl_frame_args_.interval <= base::TimeDelta()) 264 begin_impl_frame_args_.interval <= base::TimeDelta())
261 return base::TimeTicks(); 265 return base::TimeTicks();
262 266
263 base::TimeTicks now = gfx::FrameTime::Now(); 267 base::TimeTicks now = Now();
264 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, 268 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time,
265 begin_impl_frame_args_.deadline); 269 begin_impl_frame_args_.deadline);
266 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); 270 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval);
267 return timebase + (begin_impl_frame_args_.interval * intervals); 271 return timebase + (begin_impl_frame_args_.interval * intervals);
268 } 272 }
269 273
270 base::TimeTicks Scheduler::LastBeginImplFrameTime() { 274 base::TimeTicks Scheduler::LastBeginImplFrameTime() {
271 return begin_impl_frame_args_.frame_time; 275 return begin_impl_frame_args_.frame_time;
272 } 276 }
273 277
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 begin_unthrottled_frame_posted_ = true; 332 begin_unthrottled_frame_posted_ = true;
329 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); 333 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
330 } 334 }
331 335
332 // BeginUnthrottledFrame is used when we aren't throttling frame production. 336 // BeginUnthrottledFrame is used when we aren't throttling frame production.
333 // This will usually be because VSync is disabled. 337 // This will usually be because VSync is disabled.
334 void Scheduler::BeginUnthrottledFrame() { 338 void Scheduler::BeginUnthrottledFrame() {
335 DCHECK(!settings_.throttle_frame_production); 339 DCHECK(!settings_.throttle_frame_production);
336 DCHECK(begin_retro_frame_args_.empty()); 340 DCHECK(begin_retro_frame_args_.empty());
337 341
338 base::TimeTicks now = gfx::FrameTime::Now(); 342 base::TimeTicks now = Now();
339 base::TimeTicks deadline = now + vsync_interval_; 343 base::TimeTicks deadline = now + vsync_interval_;
340 344
341 BeginFrameArgs begin_frame_args = 345 BeginFrameArgs begin_frame_args =
342 BeginFrameArgs::Create(now, deadline, vsync_interval_); 346 BeginFrameArgs::Create(now, deadline, vsync_interval_);
343 BeginImplFrame(begin_frame_args); 347 BeginImplFrame(begin_frame_args);
344 348
345 begin_unthrottled_frame_posted_ = false; 349 begin_unthrottled_frame_posted_ = false;
346 } 350 }
347 351
348 // We may need to poll when we can't rely on BeginFrame to advance certain 352 // We may need to poll when we can't rely on BeginFrame to advance certain
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 if (begin_retro_frame_args_.empty()) 443 if (begin_retro_frame_args_.empty())
440 return; 444 return;
441 445
442 // Discard expired BeginRetroFrames 446 // Discard expired BeginRetroFrames
443 // Today, we should always end up with at most one un-expired BeginRetroFrame 447 // Today, we should always end up with at most one un-expired BeginRetroFrame
444 // because deadlines will not be greater than the next frame time. We don't 448 // because deadlines will not be greater than the next frame time. We don't
445 // DCHECK though because some systems don't always have monotonic timestamps. 449 // DCHECK though because some systems don't always have monotonic timestamps.
446 // TODO(brianderson): In the future, long deadlines could result in us not 450 // TODO(brianderson): In the future, long deadlines could result in us not
447 // draining the queue if we don't catch up. If we consistently can't catch 451 // draining the queue if we don't catch up. If we consistently can't catch
448 // up, our fallback should be to lower our frame rate. 452 // up, our fallback should be to lower our frame rate.
449 base::TimeTicks now = gfx::FrameTime::Now(); 453 base::TimeTicks now = Now();
450 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); 454 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
451 while (!begin_retro_frame_args_.empty() && 455 while (!begin_retro_frame_args_.empty() &&
452 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), 456 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(),
453 draw_duration_estimate)) { 457 draw_duration_estimate)) {
454 TRACE_EVENT1("cc", 458 TRACE_EVENT1("cc",
455 "Scheduler::BeginRetroFrame discarding", 459 "Scheduler::BeginRetroFrame discarding",
456 "frame_time", 460 "frame_time",
457 begin_retro_frame_args_.front().frame_time); 461 begin_retro_frame_args_.front().frame_time);
458 begin_retro_frame_args_.pop_front(); 462 begin_retro_frame_args_.pop_front();
459 } 463 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 // within this call. 559 // within this call.
556 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks 560 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
557 // so the sychronous renderer compositor can take advantage of splitting 561 // so the sychronous renderer compositor can take advantage of splitting
558 // up the BeginImplFrame and deadline as well. 562 // up the BeginImplFrame and deadline as well.
559 OnBeginImplFrameDeadline(); 563 OnBeginImplFrameDeadline();
560 return; 564 return;
561 } 565 }
562 begin_impl_frame_deadline_task_.Cancel(); 566 begin_impl_frame_deadline_task_.Cancel();
563 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 567 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
564 568
565 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); 569 base::TimeDelta delta = deadline - Now();
566 if (delta <= base::TimeDelta()) 570 if (delta <= base::TimeDelta())
567 delta = base::TimeDelta(); 571 delta = base::TimeDelta();
568 impl_task_runner_->PostDelayedTask( 572 impl_task_runner_->PostDelayedTask(
569 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); 573 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
570 } 574 }
571 575
572 void Scheduler::OnBeginImplFrameDeadline() { 576 void Scheduler::OnBeginImplFrameDeadline() {
573 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); 577 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline");
574 begin_impl_frame_deadline_task_.Cancel(); 578 begin_impl_frame_deadline_task_.Cancel();
575 579
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 } 685 }
682 686
683 scoped_ptr<base::Value> Scheduler::AsValue() const { 687 scoped_ptr<base::Value> Scheduler::AsValue() const {
684 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 688 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
685 state->Set("state_machine", state_machine_.AsValue().release()); 689 state->Set("state_machine", state_machine_.AsValue().release());
686 if (synthetic_begin_frame_source_) 690 if (synthetic_begin_frame_source_)
687 state->Set("synthetic_begin_frame_source_", 691 state->Set("synthetic_begin_frame_source_",
688 synthetic_begin_frame_source_->AsValue().release()); 692 synthetic_begin_frame_source_->AsValue().release());
689 693
690 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); 694 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue);
691 scheduler_state->SetDouble( 695 scheduler_state->SetDouble("time_until_anticipated_draw_time_ms",
692 "time_until_anticipated_draw_time_ms", 696 (AnticipatedDrawTime() - Now()).InMillisecondsF());
693 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF());
694 scheduler_state->SetDouble("vsync_interval_ms", 697 scheduler_state->SetDouble("vsync_interval_ms",
695 vsync_interval_.InMillisecondsF()); 698 vsync_interval_.InMillisecondsF());
696 scheduler_state->SetDouble("estimated_parent_draw_time_ms", 699 scheduler_state->SetDouble("estimated_parent_draw_time_ms",
697 estimated_parent_draw_time_.InMillisecondsF()); 700 estimated_parent_draw_time_.InMillisecondsF());
698 scheduler_state->SetBoolean("last_set_needs_begin_frame_", 701 scheduler_state->SetBoolean("last_set_needs_begin_frame_",
699 last_set_needs_begin_frame_); 702 last_set_needs_begin_frame_);
700 scheduler_state->SetBoolean("begin_unthrottled_frame_posted_", 703 scheduler_state->SetBoolean("begin_unthrottled_frame_posted_",
701 begin_unthrottled_frame_posted_); 704 begin_unthrottled_frame_posted_);
702 scheduler_state->SetBoolean("begin_retro_frame_posted_", 705 scheduler_state->SetBoolean("begin_retro_frame_posted_",
703 begin_retro_frame_posted_); 706 begin_retro_frame_posted_);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 } 750 }
748 751
749 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 752 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
750 return (state_machine_.commit_state() == 753 return (state_machine_.commit_state() ==
751 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 754 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
752 state_machine_.commit_state() == 755 state_machine_.commit_state() ==
753 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 756 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
754 } 757 }
755 758
756 } // namespace cc 759 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698