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

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: Fixing the gn build. Created 6 years, 4 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/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 impl_task_runner_.get());
126 } else {
127 time_source =
128 DelayBasedTimeSource::Create(VSyncInterval(), impl_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, impl_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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 begin_unthrottled_frame_posted_ = true; 335 begin_unthrottled_frame_posted_ = true;
331 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); 336 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
332 } 337 }
333 338
334 // BeginUnthrottledFrame is used when we aren't throttling frame production. 339 // BeginUnthrottledFrame is used when we aren't throttling frame production.
335 // This will usually be because VSync is disabled. 340 // This will usually be because VSync is disabled.
336 void Scheduler::BeginUnthrottledFrame() { 341 void Scheduler::BeginUnthrottledFrame() {
337 DCHECK(!settings_.throttle_frame_production); 342 DCHECK(!settings_.throttle_frame_production);
338 DCHECK(begin_retro_frame_args_.empty()); 343 DCHECK(begin_retro_frame_args_.empty());
339 344
340 base::TimeTicks now = gfx::FrameTime::Now(); 345 base::TimeTicks now = Now();
341 base::TimeTicks deadline = now + vsync_interval_; 346 base::TimeTicks deadline = now + vsync_interval_;
342 347
343 BeginFrameArgs begin_frame_args = 348 BeginFrameArgs begin_frame_args =
344 BeginFrameArgs::Create(now, deadline, vsync_interval_); 349 BeginFrameArgs::Create(now, deadline, vsync_interval_);
345 BeginImplFrame(begin_frame_args); 350 BeginImplFrame(begin_frame_args);
346 351
347 begin_unthrottled_frame_posted_ = false; 352 begin_unthrottled_frame_posted_ = false;
348 } 353 }
349 354
350 // We may need to poll when we can't rely on BeginFrame to advance certain 355 // 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
441 if (begin_retro_frame_args_.empty()) 446 if (begin_retro_frame_args_.empty())
442 return; 447 return;
443 448
444 // Discard expired BeginRetroFrames 449 // Discard expired BeginRetroFrames
445 // Today, we should always end up with at most one un-expired BeginRetroFrame 450 // Today, we should always end up with at most one un-expired BeginRetroFrame
446 // because deadlines will not be greater than the next frame time. We don't 451 // because deadlines will not be greater than the next frame time. We don't
447 // DCHECK though because some systems don't always have monotonic timestamps. 452 // DCHECK though because some systems don't always have monotonic timestamps.
448 // TODO(brianderson): In the future, long deadlines could result in us not 453 // TODO(brianderson): In the future, long deadlines could result in us not
449 // draining the queue if we don't catch up. If we consistently can't catch 454 // draining the queue if we don't catch up. If we consistently can't catch
450 // up, our fallback should be to lower our frame rate. 455 // up, our fallback should be to lower our frame rate.
451 base::TimeTicks now = gfx::FrameTime::Now(); 456 base::TimeTicks now = Now();
452 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); 457 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate();
453 while (!begin_retro_frame_args_.empty() && 458 while (!begin_retro_frame_args_.empty() &&
454 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), 459 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(),
455 draw_duration_estimate)) { 460 draw_duration_estimate)) {
456 TRACE_EVENT1("cc", 461 TRACE_EVENT1("cc",
457 "Scheduler::BeginRetroFrame discarding", 462 "Scheduler::BeginRetroFrame discarding",
458 "frame_time", 463 "frame_time",
459 begin_retro_frame_args_.front().frame_time); 464 begin_retro_frame_args_.front().frame_time);
460 begin_retro_frame_args_.pop_front(); 465 begin_retro_frame_args_.pop_front();
461 } 466 }
462 467
463 if (begin_retro_frame_args_.empty()) { 468 if (begin_retro_frame_args_.empty()) {
464 DCHECK(settings_.throttle_frame_production); 469 DCHECK(settings_.throttle_frame_production);
465 TRACE_EVENT_INSTANT0("cc", 470 TRACE_EVENT_INSTANT0("cc",
466 "Scheduler::BeginRetroFrames all expired", 471 "Scheduler::BeginRetroFrames all expired",
467 TRACE_EVENT_SCOPE_THREAD); 472 TRACE_EVENT_SCOPE_THREAD);
468 } else { 473 } else {
469 BeginImplFrame(begin_retro_frame_args_.front()); 474 BeginImplFrame(begin_retro_frame_args_.front());
470 begin_retro_frame_args_.pop_front(); 475 begin_retro_frame_args_.pop_front();
471 } 476 }
472 } 477 }
473 478
474 // There could be a race between the posted BeginRetroFrame and a new 479 // There could be a race between the posted BeginRetroFrame and a new
475 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame 480 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
476 // will check if there is a pending BeginRetroFrame to ensure we handle 481 // will check if there is a pending BeginRetroFrame to ensure we handle
477 // BeginFrames in FIFO order. 482 // BeginFrames in FIFO order.
478 void Scheduler::PostBeginRetroFrameIfNeeded() { 483 void Scheduler::PostBeginRetroFrameIfNeeded() {
484 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
485 "Scheduler::PostBeginRetroFrameIfNeeded",
486 "state",
487 AsValue());
479 if (!last_set_needs_begin_frame_) 488 if (!last_set_needs_begin_frame_)
480 return; 489 return;
481 490
482 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) 491 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
483 return; 492 return;
484 493
485 // begin_retro_frame_args_ should always be empty for the 494 // begin_retro_frame_args_ should always be empty for the
486 // synchronous compositor. 495 // synchronous compositor.
487 DCHECK(!settings_.using_synchronous_renderer_compositor); 496 DCHECK(!settings_.using_synchronous_renderer_compositor);
488 497
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 // expected BeginImplFrame start. This allows us to draw immediately when 554 // expected BeginImplFrame start. This allows us to draw immediately when
546 // there is a new active tree, instead of waiting for the next 555 // there is a new active tree, instead of waiting for the next
547 // BeginImplFrame. 556 // BeginImplFrame.
548 // TODO(brianderson): Handle long deadlines (that are past the next frame's 557 // TODO(brianderson): Handle long deadlines (that are past the next frame's
549 // frame time) properly instead of using this hack. 558 // frame time) properly instead of using this hack.
550 return args.frame_time + args.interval; 559 return args.frame_time + args.interval;
551 } 560 }
552 } 561 }
553 562
554 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { 563 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) {
564 TRACE_EVENT1(
565 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline);
555 if (settings_.using_synchronous_renderer_compositor) { 566 if (settings_.using_synchronous_renderer_compositor) {
556 // The synchronous renderer compositor has to make its GL calls 567 // The synchronous renderer compositor has to make its GL calls
557 // within this call. 568 // within this call.
558 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks 569 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
559 // so the sychronous renderer compositor can take advantage of splitting 570 // so the sychronous renderer compositor can take advantage of splitting
560 // up the BeginImplFrame and deadline as well. 571 // up the BeginImplFrame and deadline as well.
561 OnBeginImplFrameDeadline(); 572 OnBeginImplFrameDeadline();
562 return; 573 return;
563 } 574 }
564 begin_impl_frame_deadline_task_.Cancel(); 575 begin_impl_frame_deadline_task_.Cancel();
565 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); 576 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
566 577
567 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); 578 base::TimeDelta delta = deadline - Now();
568 if (delta <= base::TimeDelta()) 579 if (delta <= base::TimeDelta())
569 delta = base::TimeDelta(); 580 delta = base::TimeDelta();
570 impl_task_runner_->PostDelayedTask( 581 impl_task_runner_->PostDelayedTask(
571 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); 582 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
572 } 583 }
573 584
574 void Scheduler::OnBeginImplFrameDeadline() { 585 void Scheduler::OnBeginImplFrameDeadline() {
575 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); 586 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline");
576 begin_impl_frame_deadline_task_.Cancel(); 587 begin_impl_frame_deadline_task_.Cancel();
577 588
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 state->BeginDictionary("state_machine"); 700 state->BeginDictionary("state_machine");
690 state_machine_.AsValueInto(state); 701 state_machine_.AsValueInto(state);
691 state->EndDictionary(); 702 state->EndDictionary();
692 if (synthetic_begin_frame_source_) { 703 if (synthetic_begin_frame_source_) {
693 state->BeginDictionary("synthetic_begin_frame_source_"); 704 state->BeginDictionary("synthetic_begin_frame_source_");
694 synthetic_begin_frame_source_->AsValueInto(state); 705 synthetic_begin_frame_source_->AsValueInto(state);
695 state->EndDictionary(); 706 state->EndDictionary();
696 } 707 }
697 708
698 state->BeginDictionary("scheduler_state"); 709 state->BeginDictionary("scheduler_state");
699 state->SetDouble( 710 state->SetDouble("time_until_anticipated_draw_time_ms",
700 "time_until_anticipated_draw_time_ms", 711 (AnticipatedDrawTime() - Now()).InMillisecondsF());
701 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF());
702 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF()); 712 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
703 state->SetDouble("estimated_parent_draw_time_ms", 713 state->SetDouble("estimated_parent_draw_time_ms",
704 estimated_parent_draw_time_.InMillisecondsF()); 714 estimated_parent_draw_time_.InMillisecondsF());
705 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); 715 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_);
706 state->SetBoolean("begin_unthrottled_frame_posted_", 716 state->SetBoolean("begin_unthrottled_frame_posted_",
707 begin_unthrottled_frame_posted_); 717 begin_unthrottled_frame_posted_);
708 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); 718 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
709 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); 719 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
710 state->SetBoolean("begin_impl_frame_deadline_task_", 720 state->SetBoolean("begin_impl_frame_deadline_task_",
711 !begin_impl_frame_deadline_task_.IsCancelled()); 721 !begin_impl_frame_deadline_task_.IsCancelled());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 } 762 }
753 763
754 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 764 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
755 return (state_machine_.commit_state() == 765 return (state_machine_.commit_state() ==
756 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 766 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
757 state_machine_.commit_state() == 767 state_machine_.commit_state() ==
758 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); 768 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
759 } 769 }
760 770
761 } // namespace cc 771 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698