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

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: Fixes for Brian's comments. 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 | Annotate | Revision Log
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "cc/debug/devtools_instrumentation.h" 13 #include "cc/debug/devtools_instrumentation.h"
14 #include "cc/debug/traced_value.h" 14 #include "cc/debug/traced_value.h"
15 #include "cc/scheduler/delay_based_time_source.h" 15 #include "cc/scheduler/delay_based_time_source.h"
16 #include "ui/gfx/frame_time.h" 16 #include "ui/gfx/frame_time.h"
17 17
18 namespace cc { 18 namespace cc {
19 19
20 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( 20 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource(
21 Scheduler* scheduler, 21 Scheduler* scheduler,
22 base::SingleThreadTaskRunner* task_runner) 22 scoped_refptr<DelayBasedTimeSource> time_source)
23 : scheduler_(scheduler) { 23 : scheduler_(scheduler), time_source_(time_source) {
24 if (gfx::FrameTime::TimestampsAreHighRes()) {
25 time_source_ = DelayBasedTimeSourceHighRes::Create(
26 scheduler_->VSyncInterval(), task_runner);
27 } else {
28 time_source_ = DelayBasedTimeSource::Create(scheduler_->VSyncInterval(),
29 task_runner);
30 }
31 time_source_->SetClient(this); 24 time_source_->SetClient(this);
32 } 25 }
33 26
34 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { 27 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
35 } 28 }
36 29
37 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters( 30 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters(
38 base::TimeTicks timebase, 31 base::TimeTicks timebase,
39 base::TimeDelta interval) { 32 base::TimeDelta interval) {
40 time_source_->SetTimebaseAndInterval(timebase, interval); 33 time_source_->SetTimebaseAndInterval(timebase, interval);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 } 112 }
120 113
121 Scheduler::~Scheduler() { 114 Scheduler::~Scheduler() {
122 if (synthetic_begin_frame_source_) { 115 if (synthetic_begin_frame_source_) {
123 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, 116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
124 &begin_retro_frame_args_); 117 &begin_retro_frame_args_);
125 } 118 }
126 } 119 }
127 120
128 void Scheduler::SetupSyntheticBeginFrames() { 121 void Scheduler::SetupSyntheticBeginFrames() {
122 scoped_refptr<DelayBasedTimeSource> time_source;
123 if (gfx::FrameTime::TimestampsAreHighRes()) {
124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(),
125 task_runner_.get());
126 } else {
127 time_source =
128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get());
129 }
129 DCHECK(!synthetic_begin_frame_source_); 130 DCHECK(!synthetic_begin_frame_source_);
130 synthetic_begin_frame_source_.reset( 131 synthetic_begin_frame_source_.reset(
131 new SyntheticBeginFrameSource(this, task_runner_.get())); 132 new SyntheticBeginFrameSource(this, time_source));
133 }
134
135 base::TimeTicks Scheduler::Now() const {
136 return gfx::FrameTime::Now();
132 } 137 }
133 138
134 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, 139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
135 base::TimeDelta interval) { 140 base::TimeDelta interval) {
136 // TODO(brianderson): We should not be receiving 0 intervals. 141 // TODO(brianderson): We should not be receiving 0 intervals.
137 if (interval == base::TimeDelta()) 142 if (interval == base::TimeDelta())
138 interval = BeginFrameArgs::DefaultInterval(); 143 interval = BeginFrameArgs::DefaultInterval();
139 vsync_interval_ = interval; 144 vsync_interval_ = interval;
140 if (!settings_.begin_frame_scheduling_enabled) 145 if (!settings_.begin_frame_scheduling_enabled)
141 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); 146 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 void Scheduler::NotifyBeginMainFrameStarted() { 260 void Scheduler::NotifyBeginMainFrameStarted() {
256 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); 261 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
257 state_machine_.NotifyBeginMainFrameStarted(); 262 state_machine_.NotifyBeginMainFrameStarted();
258 } 263 }
259 264
260 base::TimeTicks Scheduler::AnticipatedDrawTime() const { 265 base::TimeTicks Scheduler::AnticipatedDrawTime() const {
261 if (!last_set_needs_begin_frame_ || 266 if (!last_set_needs_begin_frame_ ||
262 begin_impl_frame_args_.interval <= base::TimeDelta()) 267 begin_impl_frame_args_.interval <= base::TimeDelta())
263 return base::TimeTicks(); 268 return base::TimeTicks();
264 269
265 base::TimeTicks now = gfx::FrameTime::Now(); 270 base::TimeTicks now = Now();
266 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, 271 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time,
267 begin_impl_frame_args_.deadline); 272 begin_impl_frame_args_.deadline);
268 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); 273 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval);
269 return timebase + (begin_impl_frame_args_.interval * intervals); 274 return timebase + (begin_impl_frame_args_.interval * intervals);
270 } 275 }
271 276
272 base::TimeTicks Scheduler::LastBeginImplFrameTime() { 277 base::TimeTicks Scheduler::LastBeginImplFrameTime() {
273 return begin_impl_frame_args_.frame_time; 278 return begin_impl_frame_args_.frame_time;
274 } 279 }
275 280
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 begin_unthrottled_frame_posted_ = true; 338 begin_unthrottled_frame_posted_ = true;
334 task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); 339 task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
335 } 340 }
336 341
337 // BeginUnthrottledFrame is used when we aren't throttling frame production. 342 // BeginUnthrottledFrame is used when we aren't throttling frame production.
338 // This will usually be because VSync is disabled. 343 // This will usually be because VSync is disabled.
339 void Scheduler::BeginUnthrottledFrame() { 344 void Scheduler::BeginUnthrottledFrame() {
340 DCHECK(!settings_.throttle_frame_production); 345 DCHECK(!settings_.throttle_frame_production);
341 DCHECK(begin_retro_frame_args_.empty()); 346 DCHECK(begin_retro_frame_args_.empty());
342 347
343 base::TimeTicks now = gfx::FrameTime::Now(); 348 base::TimeTicks now = Now();
344 base::TimeTicks deadline = now + vsync_interval_; 349 base::TimeTicks deadline = now + vsync_interval_;
345 350
346 BeginFrameArgs begin_frame_args = 351 BeginFrameArgs begin_frame_args =
347 BeginFrameArgs::Create(now, deadline, vsync_interval_); 352 BeginFrameArgs::Create(now, deadline, vsync_interval_);
348 BeginImplFrame(begin_frame_args); 353 BeginImplFrame(begin_frame_args);
349 354
350 begin_unthrottled_frame_posted_ = false; 355 begin_unthrottled_frame_posted_ = false;
351 } 356 }
352 357
353 // We may need to poll when we can't rely on BeginFrame to advance certain 358 // 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
444 if (begin_retro_frame_args_.empty()) 449 if (begin_retro_frame_args_.empty())
445 return; 450 return;
446 451
447 // Discard expired BeginRetroFrames 452 // Discard expired BeginRetroFrames
448 // Today, we should always end up with at most one un-expired BeginRetroFrame 453 // Today, we should always end up with at most one un-expired BeginRetroFrame
449 // because deadlines will not be greater than the next frame time. We don't 454 // because deadlines will not be greater than the next frame time. We don't
450 // DCHECK though because some systems don't always have monotonic timestamps. 455 // DCHECK though because some systems don't always have monotonic timestamps.
451 // TODO(brianderson): In the future, long deadlines could result in us not 456 // TODO(brianderson): In the future, long deadlines could result in us not
452 // draining the queue if we don't catch up. If we consistently can't catch 457 // draining the queue if we don't catch up. If we consistently can't catch
453 // up, our fallback should be to lower our frame rate. 458 // up, our fallback should be to lower our frame rate.
454 base::TimeTicks now = gfx::FrameTime::Now(); 459 base::TimeTicks now = Now();
455 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); 460 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
456 while (!begin_retro_frame_args_.empty() && 461 while (!begin_retro_frame_args_.empty() &&
457 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), 462 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(),
458 draw_duration_estimate)) { 463 draw_duration_estimate)) {
459 TRACE_EVENT1("cc", 464 TRACE_EVENT1("cc",
460 "Scheduler::BeginRetroFrame discarding", 465 "Scheduler::BeginRetroFrame discarding",
461 "frame_time", 466 "frame_time",
462 begin_retro_frame_args_.front().frame_time); 467 begin_retro_frame_args_.front().frame_time);
463 begin_retro_frame_args_.pop_front(); 468 begin_retro_frame_args_.pop_front();
464 } 469 }
465 470
466 if (begin_retro_frame_args_.empty()) { 471 if (begin_retro_frame_args_.empty()) {
467 DCHECK(settings_.throttle_frame_production); 472 DCHECK(settings_.throttle_frame_production);
468 TRACE_EVENT_INSTANT0("cc", 473 TRACE_EVENT_INSTANT0("cc",
469 "Scheduler::BeginRetroFrames all expired", 474 "Scheduler::BeginRetroFrames all expired",
470 TRACE_EVENT_SCOPE_THREAD); 475 TRACE_EVENT_SCOPE_THREAD);
471 } else { 476 } else {
472 BeginImplFrame(begin_retro_frame_args_.front()); 477 BeginImplFrame(begin_retro_frame_args_.front());
473 begin_retro_frame_args_.pop_front(); 478 begin_retro_frame_args_.pop_front();
474 } 479 }
475 } 480 }
476 481
477 // There could be a race between the posted BeginRetroFrame and a new 482 // There could be a race between the posted BeginRetroFrame and a new
478 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame 483 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
479 // will check if there is a pending BeginRetroFrame to ensure we handle 484 // will check if there is a pending BeginRetroFrame to ensure we handle
480 // BeginFrames in FIFO order. 485 // BeginFrames in FIFO order.
481 void Scheduler::PostBeginRetroFrameIfNeeded() { 486 void Scheduler::PostBeginRetroFrameIfNeeded() {
487 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
488 "Scheduler::PostBeginRetroFrameIfNeeded",
489 "state",
490 AsValue());
482 if (!last_set_needs_begin_frame_) 491 if (!last_set_needs_begin_frame_)
483 return; 492 return;
484 493
485 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) 494 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
486 return; 495 return;
487 496
488 // begin_retro_frame_args_ should always be empty for the 497 // begin_retro_frame_args_ should always be empty for the
489 // synchronous compositor. 498 // synchronous compositor.
490 DCHECK(!settings_.using_synchronous_renderer_compositor); 499 DCHECK(!settings_.using_synchronous_renderer_compositor);
491 500
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 // expected BeginImplFrame start. This allows us to draw immediately when 557 // expected BeginImplFrame start. This allows us to draw immediately when
549 // there is a new active tree, instead of waiting for the next 558 // there is a new active tree, instead of waiting for the next
550 // BeginImplFrame. 559 // BeginImplFrame.
551 // TODO(brianderson): Handle long deadlines (that are past the next frame's 560 // TODO(brianderson): Handle long deadlines (that are past the next frame's
552 // frame time) properly instead of using this hack. 561 // frame time) properly instead of using this hack.
553 return args.frame_time + args.interval; 562 return args.frame_time + args.interval;
554 } 563 }
555 } 564 }
556 565
557 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { 566 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) {
567 TRACE_EVENT1(
568 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline);
558 if (settings_.using_synchronous_renderer_compositor) { 569 if (settings_.using_synchronous_renderer_compositor) {
559 // The synchronous renderer compositor has to make its GL calls 570 // The synchronous renderer compositor has to make its GL calls
560 // within this call. 571 // within this call.
561 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks 572 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
562 // so the sychronous renderer compositor can take advantage of splitting 573 // so the sychronous renderer compositor can take advantage of splitting
563 // up the BeginImplFrame and deadline as well. 574 // up the BeginImplFrame and deadline as well.
564 OnBeginImplFrameDeadline(); 575 OnBeginImplFrameDeadline();
565 return; 576 return;
566 } 577 }
567 begin_impl_frame_deadline_task_.Cancel(); 578 begin_impl_frame_deadline_task_.Cancel();
568 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 579 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
569 580
570 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); 581 base::TimeDelta delta = deadline - Now();
571 if (delta <= base::TimeDelta()) 582 if (delta <= base::TimeDelta())
572 delta = base::TimeDelta(); 583 delta = base::TimeDelta();
573 task_runner_->PostDelayedTask( 584 task_runner_->PostDelayedTask(
574 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); 585 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
575 } 586 }
576 587
577 void Scheduler::OnBeginImplFrameDeadline() { 588 void Scheduler::OnBeginImplFrameDeadline() {
578 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); 589 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline");
579 begin_impl_frame_deadline_task_.Cancel(); 590 begin_impl_frame_deadline_task_.Cancel();
580 591
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 state->BeginDictionary("state_machine"); 701 state->BeginDictionary("state_machine");
691 state_machine_.AsValueInto(state.get()); 702 state_machine_.AsValueInto(state.get());
692 state->EndDictionary(); 703 state->EndDictionary();
693 if (synthetic_begin_frame_source_) { 704 if (synthetic_begin_frame_source_) {
694 state->BeginDictionary("synthetic_begin_frame_source_"); 705 state->BeginDictionary("synthetic_begin_frame_source_");
695 synthetic_begin_frame_source_->AsValueInto(state.get()); 706 synthetic_begin_frame_source_->AsValueInto(state.get());
696 state->EndDictionary(); 707 state->EndDictionary();
697 } 708 }
698 709
699 state->BeginDictionary("scheduler_state"); 710 state->BeginDictionary("scheduler_state");
700 state->SetDouble( 711 state->SetDouble("time_until_anticipated_draw_time_ms",
701 "time_until_anticipated_draw_time_ms", 712 (AnticipatedDrawTime() - Now()).InMillisecondsF());
702 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF());
703 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF()); 713 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
704 state->SetDouble("estimated_parent_draw_time_ms", 714 state->SetDouble("estimated_parent_draw_time_ms",
705 estimated_parent_draw_time_.InMillisecondsF()); 715 estimated_parent_draw_time_.InMillisecondsF());
706 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); 716 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_);
707 state->SetBoolean("begin_unthrottled_frame_posted_", 717 state->SetBoolean("begin_unthrottled_frame_posted_",
708 begin_unthrottled_frame_posted_); 718 begin_unthrottled_frame_posted_);
709 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); 719 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
710 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); 720 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
711 state->SetBoolean("begin_impl_frame_deadline_task_", 721 state->SetBoolean("begin_impl_frame_deadline_task_",
712 !begin_impl_frame_deadline_task_.IsCancelled()); 722 !begin_impl_frame_deadline_task_.IsCancelled());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 } 763 }
754 764
755 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 765 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
756 return (state_machine_.commit_state() == 766 return (state_machine_.commit_state() ==
757 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 767 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
758 state_machine_.commit_state() == 768 state_machine_.commit_state() ==
759 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 769 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
760 } 770 }
761 771
762 } // namespace cc 772 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698