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/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 base::SingleThreadTaskRunner* task_runner) |
22 : scheduler_(scheduler) { | 21 : scheduler_(scheduler) { |
23 if (gfx::FrameTime::TimestampsAreHighRes()) { | 22 if (gfx::FrameTime::TimestampsAreHighRes()) { |
24 time_source_ = DelayBasedTimeSourceHighRes::Create( | 23 time_source_ = DelayBasedTimeSourceHighRes::Create( |
25 scheduler_->VSyncInterval(), task_runner); | 24 scheduler_->VSyncInterval(), task_runner); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 &begin_retro_frame_args_); | 121 &begin_retro_frame_args_); |
123 } | 122 } |
124 } | 123 } |
125 | 124 |
126 void Scheduler::SetupSyntheticBeginFrames() { | 125 void Scheduler::SetupSyntheticBeginFrames() { |
127 DCHECK(!synthetic_begin_frame_source_); | 126 DCHECK(!synthetic_begin_frame_source_); |
128 synthetic_begin_frame_source_.reset( | 127 synthetic_begin_frame_source_.reset( |
129 new SyntheticBeginFrameSource(this, impl_task_runner_.get())); | 128 new SyntheticBeginFrameSource(this, impl_task_runner_.get())); |
130 } | 129 } |
131 | 130 |
| 131 base::TimeTicks Scheduler::Now() const { |
| 132 return gfx::FrameTime::Now(); |
| 133 } |
| 134 |
132 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 135 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
133 base::TimeDelta interval) { | 136 base::TimeDelta interval) { |
134 // TODO(brianderson): We should not be receiving 0 intervals. | 137 // TODO(brianderson): We should not be receiving 0 intervals. |
135 if (interval == base::TimeDelta()) | 138 if (interval == base::TimeDelta()) |
136 interval = BeginFrameArgs::DefaultInterval(); | 139 interval = BeginFrameArgs::DefaultInterval(); |
137 vsync_interval_ = interval; | 140 vsync_interval_ = interval; |
138 if (!settings_.begin_frame_scheduling_enabled) | 141 if (!settings_.begin_frame_scheduling_enabled) |
139 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 142 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); |
140 } | 143 } |
141 | 144 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 void Scheduler::NotifyBeginMainFrameStarted() { | 256 void Scheduler::NotifyBeginMainFrameStarted() { |
254 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 257 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
255 state_machine_.NotifyBeginMainFrameStarted(); | 258 state_machine_.NotifyBeginMainFrameStarted(); |
256 } | 259 } |
257 | 260 |
258 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | 261 base::TimeTicks Scheduler::AnticipatedDrawTime() const { |
259 if (!last_set_needs_begin_frame_ || | 262 if (!last_set_needs_begin_frame_ || |
260 begin_impl_frame_args_.interval <= base::TimeDelta()) | 263 begin_impl_frame_args_.interval <= base::TimeDelta()) |
261 return base::TimeTicks(); | 264 return base::TimeTicks(); |
262 | 265 |
263 base::TimeTicks now = gfx::FrameTime::Now(); | 266 base::TimeTicks now = Now(); |
264 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, | 267 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, |
265 begin_impl_frame_args_.deadline); | 268 begin_impl_frame_args_.deadline); |
266 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); | 269 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); |
267 return timebase + (begin_impl_frame_args_.interval * intervals); | 270 return timebase + (begin_impl_frame_args_.interval * intervals); |
268 } | 271 } |
269 | 272 |
270 base::TimeTicks Scheduler::LastBeginImplFrameTime() { | 273 base::TimeTicks Scheduler::LastBeginImplFrameTime() { |
271 return begin_impl_frame_args_.frame_time; | 274 return begin_impl_frame_args_.frame_time; |
272 } | 275 } |
273 | 276 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 begin_unthrottled_frame_posted_ = true; | 331 begin_unthrottled_frame_posted_ = true; |
329 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); | 332 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); |
330 } | 333 } |
331 | 334 |
332 // BeginUnthrottledFrame is used when we aren't throttling frame production. | 335 // BeginUnthrottledFrame is used when we aren't throttling frame production. |
333 // This will usually be because VSync is disabled. | 336 // This will usually be because VSync is disabled. |
334 void Scheduler::BeginUnthrottledFrame() { | 337 void Scheduler::BeginUnthrottledFrame() { |
335 DCHECK(!settings_.throttle_frame_production); | 338 DCHECK(!settings_.throttle_frame_production); |
336 DCHECK(begin_retro_frame_args_.empty()); | 339 DCHECK(begin_retro_frame_args_.empty()); |
337 | 340 |
338 base::TimeTicks now = gfx::FrameTime::Now(); | 341 base::TimeTicks now = Now(); |
339 base::TimeTicks deadline = now + vsync_interval_; | 342 base::TimeTicks deadline = now + vsync_interval_; |
340 | 343 |
341 BeginFrameArgs begin_frame_args = | 344 BeginFrameArgs begin_frame_args = |
342 BeginFrameArgs::Create(now, deadline, vsync_interval_); | 345 BeginFrameArgs::Create(now, deadline, vsync_interval_); |
343 BeginImplFrame(begin_frame_args); | 346 BeginImplFrame(begin_frame_args); |
344 | 347 |
345 begin_unthrottled_frame_posted_ = false; | 348 begin_unthrottled_frame_posted_ = false; |
346 } | 349 } |
347 | 350 |
348 // We may need to poll when we can't rely on BeginFrame to advance certain | 351 // 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 Loading... |
439 if (begin_retro_frame_args_.empty()) | 442 if (begin_retro_frame_args_.empty()) |
440 return; | 443 return; |
441 | 444 |
442 // Discard expired BeginRetroFrames | 445 // Discard expired BeginRetroFrames |
443 // Today, we should always end up with at most one un-expired BeginRetroFrame | 446 // 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 | 447 // 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. | 448 // DCHECK though because some systems don't always have monotonic timestamps. |
446 // TODO(brianderson): In the future, long deadlines could result in us not | 449 // 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 | 450 // 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. | 451 // up, our fallback should be to lower our frame rate. |
449 base::TimeTicks now = gfx::FrameTime::Now(); | 452 base::TimeTicks now = Now(); |
450 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 453 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
451 while (!begin_retro_frame_args_.empty() && | 454 while (!begin_retro_frame_args_.empty() && |
452 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), | 455 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), |
453 draw_duration_estimate)) { | 456 draw_duration_estimate)) { |
454 TRACE_EVENT1("cc", | 457 TRACE_EVENT1("cc", |
455 "Scheduler::BeginRetroFrame discarding", | 458 "Scheduler::BeginRetroFrame discarding", |
456 "frame_time", | 459 "frame_time", |
457 begin_retro_frame_args_.front().frame_time); | 460 begin_retro_frame_args_.front().frame_time); |
458 begin_retro_frame_args_.pop_front(); | 461 begin_retro_frame_args_.pop_front(); |
459 } | 462 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 // within this call. | 558 // within this call. |
556 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | 559 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks |
557 // so the sychronous renderer compositor can take advantage of splitting | 560 // so the sychronous renderer compositor can take advantage of splitting |
558 // up the BeginImplFrame and deadline as well. | 561 // up the BeginImplFrame and deadline as well. |
559 OnBeginImplFrameDeadline(); | 562 OnBeginImplFrameDeadline(); |
560 return; | 563 return; |
561 } | 564 } |
562 begin_impl_frame_deadline_task_.Cancel(); | 565 begin_impl_frame_deadline_task_.Cancel(); |
563 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 566 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
564 | 567 |
565 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); | 568 base::TimeDelta delta = deadline - Now(); |
566 if (delta <= base::TimeDelta()) | 569 if (delta <= base::TimeDelta()) |
567 delta = base::TimeDelta(); | 570 delta = base::TimeDelta(); |
568 impl_task_runner_->PostDelayedTask( | 571 impl_task_runner_->PostDelayedTask( |
569 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 572 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
570 } | 573 } |
571 | 574 |
572 void Scheduler::OnBeginImplFrameDeadline() { | 575 void Scheduler::OnBeginImplFrameDeadline() { |
573 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); | 576 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); |
574 begin_impl_frame_deadline_task_.Cancel(); | 577 begin_impl_frame_deadline_task_.Cancel(); |
575 | 578 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
OLD | NEW |