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/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( | |
21 Scheduler* scheduler, | |
22 scoped_refptr<DelayBasedTimeSource> time_source) | |
23 : scheduler_(scheduler), time_source_(time_source) { | |
24 time_source_->SetClient(this); | |
25 } | |
26 | |
27 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { | |
28 } | |
29 | |
30 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters( | |
31 base::TimeTicks timebase, | |
32 base::TimeDelta interval) { | |
33 time_source_->SetTimebaseAndInterval(timebase, interval); | |
34 } | |
35 | |
36 void Scheduler::SyntheticBeginFrameSource::SetNeedsBeginFrame( | |
37 bool needs_begin_frame, | |
38 std::deque<BeginFrameArgs>* begin_retro_frame_args) { | |
39 DCHECK(begin_retro_frame_args); | |
40 base::TimeTicks missed_tick_time = | |
41 time_source_->SetActive(needs_begin_frame); | |
42 if (!missed_tick_time.is_null()) { | |
43 begin_retro_frame_args->push_back( | |
44 CreateSyntheticBeginFrameArgs(missed_tick_time)); | |
45 } | |
46 } | |
47 | |
48 bool Scheduler::SyntheticBeginFrameSource::IsActive() const { | |
49 return time_source_->Active(); | |
50 } | |
51 | |
52 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() { | |
53 BeginFrameArgs begin_frame_args( | |
54 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); | |
55 scheduler_->BeginFrame(begin_frame_args); | |
56 } | |
57 | |
58 void Scheduler::SyntheticBeginFrameSource::AsValueInto( | |
59 base::debug::TracedValue* state) const { | |
60 time_source_->AsValueInto(state); | |
61 } | |
62 | |
63 BeginFrameArgs | |
64 Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs( | |
65 base::TimeTicks frame_time) { | |
66 base::TimeTicks deadline = time_source_->NextTickTime(); | |
67 return BeginFrameArgs::Create( | |
68 frame_time, deadline, scheduler_->VSyncInterval()); | |
69 } | |
70 | |
71 Scheduler::Scheduler( | 20 Scheduler::Scheduler( |
72 SchedulerClient* client, | 21 SchedulerClient* client, |
73 const SchedulerSettings& scheduler_settings, | 22 const SchedulerSettings& scheduler_settings, |
74 int layer_tree_host_id, | 23 int layer_tree_host_id, |
75 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 24 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
76 : settings_(scheduler_settings), | 25 : settings_(scheduler_settings), |
77 client_(client), | 26 client_(client), |
78 layer_tree_host_id_(layer_tree_host_id), | 27 layer_tree_host_id_(layer_tree_host_id), |
79 task_runner_(task_runner), | 28 task_runner_(task_runner), |
80 vsync_interval_(BeginFrameArgs::DefaultInterval()), | |
81 last_set_needs_begin_frame_(false), | |
82 begin_unthrottled_frame_posted_(false), | |
83 begin_retro_frame_posted_(false), | 29 begin_retro_frame_posted_(false), |
84 state_machine_(scheduler_settings), | 30 state_machine_(scheduler_settings), |
85 inside_process_scheduled_actions_(false), | 31 inside_process_scheduled_actions_(false), |
86 inside_action_(SchedulerStateMachine::ACTION_NONE), | 32 inside_action_(SchedulerStateMachine::ACTION_NONE), |
87 weak_factory_(this) { | 33 weak_factory_(this) { |
88 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 34 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
89 "Scheduler::Scheduler", | 35 "Scheduler::Scheduler", |
90 "settings", | 36 "settings", |
91 settings_.AsValue()); | 37 settings_.AsValue()); |
92 DCHECK(client_); | 38 DCHECK(client_); |
93 DCHECK(!state_machine_.BeginFrameNeeded()); | 39 DCHECK(!state_machine_.BeginFrameNeeded()); |
94 if (settings_.main_frame_before_activation_enabled) { | 40 if (settings_.main_frame_before_activation_enabled) { |
95 DCHECK(settings_.main_frame_before_draw_enabled); | 41 DCHECK(settings_.main_frame_before_draw_enabled); |
96 } | 42 } |
97 | 43 |
98 begin_retro_frame_closure_ = | 44 begin_retro_frame_closure_ = |
99 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 45 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
100 begin_unthrottled_frame_closure_ = | |
101 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | |
102 begin_impl_frame_deadline_closure_ = base::Bind( | 46 begin_impl_frame_deadline_closure_ = base::Bind( |
103 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 47 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
104 poll_for_draw_triggers_closure_ = base::Bind( | 48 poll_for_draw_triggers_closure_ = base::Bind( |
105 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 49 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
106 advance_commit_state_closure_ = base::Bind( | 50 advance_commit_state_closure_ = base::Bind( |
107 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 51 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
52 } | |
108 | 53 |
109 if (!settings_.begin_frame_scheduling_enabled) { | 54 BeginFrameSource* Scheduler::GetPrimaryBeginFrameSource() { |
110 SetupSyntheticBeginFrames(); | 55 if (!settings_.throttle_frame_production) { |
56 TRACE_EVENT1("cc", | |
57 "Scheduler::Scheduler()", | |
58 "PrimaryFrameSource", | |
59 "BackToBackBeginFrameSource"); | |
60 primary_frame_source_internal_ = | |
61 BackToBackBeginFrameSource::Create(task_runner_.get()); | |
62 return primary_frame_source_internal_.get(); | |
63 } else if (settings_.begin_frame_scheduling_enabled) { | |
64 TRACE_EVENT1("cc", | |
65 "Scheduler::Scheduler()", | |
66 "PrimaryFrameSource", | |
67 "SchedulerClient"); | |
68 return client_->GetExternalBeginFrameSource(); | |
69 } else { | |
70 TRACE_EVENT1("cc", | |
71 "Scheduler::Scheduler()", | |
72 "PrimaryFrameSource", | |
73 "SyntheticBeginFrameSource"); | |
74 scoped_ptr<SyntheticBeginFrameSource> synthetic_source = | |
75 SyntheticBeginFrameSource::Create( | |
76 task_runner_.get(), Now(), BeginFrameArgs::DefaultInterval()); | |
77 vsync_observer_ = synthetic_source.get(); | |
78 primary_frame_source_internal_ = synthetic_source.Pass(); | |
79 return primary_frame_source_internal_.get(); | |
111 } | 80 } |
112 } | 81 } |
113 | 82 |
114 Scheduler::~Scheduler() { | 83 BeginFrameSource* Scheduler::GetBackgroundBeginFrameSource() { |
115 if (synthetic_begin_frame_source_) { | 84 TRACE_EVENT1("cc", |
116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 85 "Scheduler::Scheduler()", |
117 &begin_retro_frame_args_); | 86 "BackgroundFrameSource", |
118 } | 87 "SyntheticBeginFrameSource"); |
88 background_frame_source_internal_ = SyntheticBeginFrameSource::Create( | |
89 task_runner_.get(), Now(), base::TimeDelta::FromSeconds(1)); | |
90 return background_frame_source_internal_.get(); | |
119 } | 91 } |
120 | 92 |
121 void Scheduler::SetupSyntheticBeginFrames() { | 93 void Scheduler::FinalizeSetup() { |
122 scoped_refptr<DelayBasedTimeSource> time_source; | 94 frame_source_ = BeginFrameSourceMultiplexer::Create(); |
123 if (gfx::FrameTime::TimestampsAreHighRes()) { | 95 frame_source_->AddObserver(this); |
124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), | 96 |
125 task_runner_.get()); | 97 // Primary frame source |
126 } else { | 98 primary_frame_source_ = GetPrimaryBeginFrameSource(); |
127 time_source = | 99 frame_source_->AddSource(primary_frame_source_); |
128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); | 100 |
129 } | 101 // Background ticking frame source |
130 DCHECK(!synthetic_begin_frame_source_); | 102 background_frame_source_ = GetBackgroundBeginFrameSource(); |
131 synthetic_begin_frame_source_.reset( | 103 frame_source_->AddSource(background_frame_source_); |
132 new SyntheticBeginFrameSource(this, time_source)); | 104 } |
105 | |
106 Scheduler::~Scheduler() { | |
133 } | 107 } |
134 | 108 |
135 base::TimeTicks Scheduler::Now() const { | 109 base::TimeTicks Scheduler::Now() const { |
136 return gfx::FrameTime::Now(); | 110 return gfx::FrameTime::Now(); |
137 } | 111 } |
138 | 112 |
139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 113 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
140 base::TimeDelta interval) { | 114 base::TimeDelta interval) { |
141 // TODO(brianderson): We should not be receiving 0 intervals. | 115 // TODO(brianderson): We should not be receiving 0 intervals. |
142 if (interval == base::TimeDelta()) | 116 if (interval == base::TimeDelta()) |
143 interval = BeginFrameArgs::DefaultInterval(); | 117 interval = BeginFrameArgs::DefaultInterval(); |
144 vsync_interval_ = interval; | 118 |
145 if (!settings_.begin_frame_scheduling_enabled) | 119 if (vsync_observer_) |
146 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 120 vsync_observer_->OnUpdateVSyncParameters(timebase, interval); |
147 } | 121 } |
148 | 122 |
149 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 123 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
150 DCHECK_GE(draw_time.ToInternalValue(), 0); | 124 DCHECK_GE(draw_time.ToInternalValue(), 0); |
151 estimated_parent_draw_time_ = draw_time; | 125 estimated_parent_draw_time_ = draw_time; |
152 } | 126 } |
153 | 127 |
154 void Scheduler::SetCanStart() { | 128 void Scheduler::SetCanStart() { |
155 state_machine_.SetCanStart(); | 129 state_machine_.SetCanStart(); |
156 ProcessScheduledActions(); | 130 ProcessScheduledActions(); |
157 } | 131 } |
158 | 132 |
159 void Scheduler::SetVisible(bool visible) { | 133 void Scheduler::SetVisible(bool visible) { |
160 state_machine_.SetVisible(visible); | 134 state_machine_.SetVisible(visible); |
135 if (visible) { | |
136 frame_source_->SetActiveSource(primary_frame_source_); | |
137 } else { | |
138 frame_source_->SetActiveSource(background_frame_source_); | |
139 } | |
161 ProcessScheduledActions(); | 140 ProcessScheduledActions(); |
162 } | 141 } |
163 | 142 |
164 void Scheduler::SetCanDraw(bool can_draw) { | 143 void Scheduler::SetCanDraw(bool can_draw) { |
165 state_machine_.SetCanDraw(can_draw); | 144 state_machine_.SetCanDraw(can_draw); |
166 ProcessScheduledActions(); | 145 ProcessScheduledActions(); |
167 } | 146 } |
168 | 147 |
169 void Scheduler::NotifyReadyToActivate() { | 148 void Scheduler::NotifyReadyToActivate() { |
170 state_machine_.NotifyReadyToActivate(); | 149 state_machine_.NotifyReadyToActivate(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 ProcessScheduledActions(); | 212 ProcessScheduledActions(); |
234 } | 213 } |
235 | 214 |
236 void Scheduler::DidManageTiles() { | 215 void Scheduler::DidManageTiles() { |
237 state_machine_.DidManageTiles(); | 216 state_machine_.DidManageTiles(); |
238 } | 217 } |
239 | 218 |
240 void Scheduler::DidLoseOutputSurface() { | 219 void Scheduler::DidLoseOutputSurface() { |
241 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 220 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
242 state_machine_.DidLoseOutputSurface(); | 221 state_machine_.DidLoseOutputSurface(); |
243 last_set_needs_begin_frame_ = false; | 222 if (frame_source_->NeedsBeginFrames()) |
244 if (!settings_.begin_frame_scheduling_enabled) { | 223 frame_source_->SetNeedsBeginFrames(false); |
245 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | |
246 &begin_retro_frame_args_); | |
247 } | |
248 begin_retro_frame_args_.clear(); | 224 begin_retro_frame_args_.clear(); |
249 ProcessScheduledActions(); | 225 ProcessScheduledActions(); |
250 } | 226 } |
251 | 227 |
252 void Scheduler::DidCreateAndInitializeOutputSurface() { | 228 void Scheduler::DidCreateAndInitializeOutputSurface() { |
253 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 229 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
254 DCHECK(!last_set_needs_begin_frame_); | 230 DCHECK(!frame_source_->NeedsBeginFrames()); |
255 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 231 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
256 state_machine_.DidCreateAndInitializeOutputSurface(); | 232 state_machine_.DidCreateAndInitializeOutputSurface(); |
257 ProcessScheduledActions(); | 233 ProcessScheduledActions(); |
258 } | 234 } |
259 | 235 |
260 void Scheduler::NotifyBeginMainFrameStarted() { | 236 void Scheduler::NotifyBeginMainFrameStarted() { |
261 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 237 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
262 state_machine_.NotifyBeginMainFrameStarted(); | 238 state_machine_.NotifyBeginMainFrameStarted(); |
263 } | 239 } |
264 | 240 |
265 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | 241 base::TimeTicks Scheduler::AnticipatedDrawTime() const { |
266 if (!last_set_needs_begin_frame_ || | 242 if (!frame_source_->NeedsBeginFrames() || |
267 begin_impl_frame_args_.interval <= base::TimeDelta()) | 243 begin_impl_frame_args_.interval <= base::TimeDelta()) |
268 return base::TimeTicks(); | 244 return base::TimeTicks(); |
269 | 245 |
270 base::TimeTicks now = Now(); | 246 base::TimeTicks now = Now(); |
271 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, | 247 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, |
272 begin_impl_frame_args_.deadline); | 248 begin_impl_frame_args_.deadline); |
273 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); | 249 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); |
274 return timebase + (begin_impl_frame_args_.interval * intervals); | 250 return timebase + (begin_impl_frame_args_.interval * intervals); |
275 } | 251 } |
276 | 252 |
253 const BeginFrameArgs& Scheduler::LastBeginFrameArgs() const { | |
254 return last_begin_frame_args_; | |
255 } | |
256 | |
277 base::TimeTicks Scheduler::LastBeginImplFrameTime() { | 257 base::TimeTicks Scheduler::LastBeginImplFrameTime() { |
278 return begin_impl_frame_args_.frame_time; | 258 return begin_impl_frame_args_.frame_time; |
279 } | 259 } |
280 | 260 |
281 void Scheduler::SetupNextBeginFrameIfNeeded() { | 261 void Scheduler::SetupNextBeginFrameIfNeeded() { |
282 if (!task_runner_.get()) | 262 if (!task_runner_.get()) |
283 return; | 263 return; |
284 | 264 |
285 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); | 265 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); |
286 | 266 |
287 if (settings_.throttle_frame_production) { | 267 bool at_end_of_deadline = |
288 SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame); | 268 (state_machine_.begin_impl_frame_state() == |
289 } else { | 269 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); |
290 SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame); | 270 |
271 bool should_call_set_needs_begin_frame = | |
272 // Always request the BeginFrame immediately if it wasn't needed before. | |
273 (needs_begin_frame && !frame_source_->NeedsBeginFrames()) || | |
274 // Only stop requesting BeginFrames after a deadline. | |
275 (!needs_begin_frame && frame_source_->NeedsBeginFrames() && | |
276 at_end_of_deadline); | |
277 | |
278 if (should_call_set_needs_begin_frame) { | |
279 frame_source_->SetNeedsBeginFrames(needs_begin_frame); | |
291 } | 280 } |
281 | |
282 bool at_state_idle = (state_machine_.begin_impl_frame_state() != | |
283 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
284 if (at_end_of_deadline || at_state_idle) { | |
285 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
286 } | |
287 | |
288 PostBeginRetroFrameIfNeeded(); | |
292 SetupPollingMechanisms(needs_begin_frame); | 289 SetupPollingMechanisms(needs_begin_frame); |
293 } | 290 } |
294 | 291 |
295 // When we are throttling frame production, we request BeginFrames | |
296 // from the OutputSurface. | |
297 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled( | |
298 bool needs_begin_frame) { | |
299 bool at_end_of_deadline = | |
300 state_machine_.begin_impl_frame_state() == | |
301 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | |
302 | |
303 bool should_call_set_needs_begin_frame = | |
304 // Always request the BeginFrame immediately if it wasn't needed before. | |
305 (needs_begin_frame && !last_set_needs_begin_frame_) || | |
306 // Only stop requesting BeginFrames after a deadline. | |
307 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); | |
308 | |
309 if (should_call_set_needs_begin_frame) { | |
310 if (settings_.begin_frame_scheduling_enabled) { | |
311 client_->SetNeedsBeginFrame(needs_begin_frame); | |
312 } else { | |
313 synthetic_begin_frame_source_->SetNeedsBeginFrame( | |
314 needs_begin_frame, &begin_retro_frame_args_); | |
315 } | |
316 last_set_needs_begin_frame_ = needs_begin_frame; | |
317 } | |
318 | |
319 PostBeginRetroFrameIfNeeded(); | |
320 } | |
321 | |
322 // When we aren't throttling frame production, we initiate a BeginFrame | |
323 // as soon as one is needed. | |
324 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled( | |
325 bool needs_begin_frame) { | |
326 last_set_needs_begin_frame_ = needs_begin_frame; | |
327 | |
328 if (!needs_begin_frame || begin_unthrottled_frame_posted_) | |
329 return; | |
330 | |
331 if (state_machine_.begin_impl_frame_state() != | |
332 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE && | |
333 state_machine_.begin_impl_frame_state() != | |
334 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { | |
335 return; | |
336 } | |
337 | |
338 begin_unthrottled_frame_posted_ = true; | |
339 task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); | |
340 } | |
341 | |
342 // BeginUnthrottledFrame is used when we aren't throttling frame production. | |
343 // This will usually be because VSync is disabled. | |
344 void Scheduler::BeginUnthrottledFrame() { | |
345 DCHECK(!settings_.throttle_frame_production); | |
346 DCHECK(begin_retro_frame_args_.empty()); | |
347 | |
348 base::TimeTicks now = Now(); | |
349 base::TimeTicks deadline = now + vsync_interval_; | |
350 | |
351 BeginFrameArgs begin_frame_args = | |
352 BeginFrameArgs::Create(now, deadline, vsync_interval_); | |
353 BeginImplFrame(begin_frame_args); | |
354 | |
355 begin_unthrottled_frame_posted_ = false; | |
356 } | |
357 | |
358 // We may need to poll when we can't rely on BeginFrame to advance certain | 292 // We may need to poll when we can't rely on BeginFrame to advance certain |
359 // state or to avoid deadlock. | 293 // state or to avoid deadlock. |
360 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { | 294 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { |
361 bool needs_advance_commit_state_timer = false; | 295 bool needs_advance_commit_state_timer = false; |
362 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but | 296 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
363 // aren't expecting any more BeginFrames. This should only be needed by | 297 // aren't expecting any more BeginFrames. This should only be needed by |
364 // the synchronous compositor when BeginFrameNeeded is false. | 298 // the synchronous compositor when BeginFrameNeeded is false. |
365 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { | 299 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { |
366 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); | 300 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); |
367 DCHECK(!needs_begin_frame); | 301 DCHECK(!needs_begin_frame); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 } | 335 } |
402 } else { | 336 } else { |
403 advance_commit_state_task_.Cancel(); | 337 advance_commit_state_task_.Cancel(); |
404 } | 338 } |
405 } | 339 } |
406 | 340 |
407 // BeginFrame is the mechanism that tells us that now is a good time to start | 341 // BeginFrame is the mechanism that tells us that now is a good time to start |
408 // making a frame. Usually this means that user input for the frame is complete. | 342 // making a frame. Usually this means that user input for the frame is complete. |
409 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 343 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
410 // a BeginRetroFrame. | 344 // a BeginRetroFrame. |
411 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 345 void Scheduler::OnBeginFrame(const BeginFrameArgs& args) { |
412 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); | 346 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); |
413 DCHECK(settings_.throttle_frame_production); | |
414 | 347 |
415 BeginFrameArgs adjusted_args(args); | 348 BeginFrameArgs adjusted_args(args); |
416 adjusted_args.deadline -= EstimatedParentDrawTime(); | 349 adjusted_args.deadline -= EstimatedParentDrawTime(); |
417 | 350 |
418 bool should_defer_begin_frame; | 351 bool should_defer_begin_frame; |
419 if (settings_.using_synchronous_renderer_compositor) { | 352 if (settings_.using_synchronous_renderer_compositor) { |
420 should_defer_begin_frame = false; | 353 should_defer_begin_frame = false; |
421 } else { | 354 } else { |
422 should_defer_begin_frame = | 355 should_defer_begin_frame = |
423 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | 356 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
424 !last_set_needs_begin_frame_ || | 357 !frame_source_->NeedsBeginFrames() || |
425 (state_machine_.begin_impl_frame_state() != | 358 (state_machine_.begin_impl_frame_state() != |
426 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 359 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
427 } | 360 } |
428 | 361 |
429 if (should_defer_begin_frame) { | 362 if (should_defer_begin_frame) { |
430 begin_retro_frame_args_.push_back(adjusted_args); | 363 begin_retro_frame_args_.push_back(adjusted_args); |
431 TRACE_EVENT_INSTANT0( | 364 TRACE_EVENT_INSTANT0( |
432 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | 365 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); |
433 return; | 366 return; |
434 } | 367 } |
(...skipping 19 matching lines...) Expand all Loading... | |
454 // because deadlines will not be greater than the next frame time. We don't | 387 // because deadlines will not be greater than the next frame time. We don't |
455 // DCHECK though because some systems don't always have monotonic timestamps. | 388 // DCHECK though because some systems don't always have monotonic timestamps. |
456 // TODO(brianderson): In the future, long deadlines could result in us not | 389 // TODO(brianderson): In the future, long deadlines could result in us not |
457 // draining the queue if we don't catch up. If we consistently can't catch | 390 // draining the queue if we don't catch up. If we consistently can't catch |
458 // up, our fallback should be to lower our frame rate. | 391 // up, our fallback should be to lower our frame rate. |
459 base::TimeTicks now = Now(); | 392 base::TimeTicks now = Now(); |
460 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 393 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
461 while (!begin_retro_frame_args_.empty() && | 394 while (!begin_retro_frame_args_.empty() && |
462 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), | 395 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), |
463 draw_duration_estimate)) { | 396 draw_duration_estimate)) { |
464 TRACE_EVENT1("cc", | 397 TRACE_EVENT2("cc", |
465 "Scheduler::BeginRetroFrame discarding", | 398 "Scheduler::BeginRetroFrame discarding", |
399 "now", | |
400 Now(), | |
brianderson
2014/09/18 00:27:24
Now() -> now ?
mithro-old
2014/09/18 13:33:37
Done.
Move this bit into https://codereview.chrom
| |
466 "frame_time", | 401 "frame_time", |
467 begin_retro_frame_args_.front().frame_time); | 402 begin_retro_frame_args_.front().frame_time); |
brianderson
2014/09/18 00:27:24
begin_retro_frame_args_.front().AsValue()?
mithro-old
2014/09/18 13:33:37
Done.
Move this bit into https://codereview.chrom
| |
468 begin_retro_frame_args_.pop_front(); | 403 begin_retro_frame_args_.pop_front(); |
404 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
469 } | 405 } |
470 | 406 |
471 if (begin_retro_frame_args_.empty()) { | 407 if (begin_retro_frame_args_.empty()) { |
472 DCHECK(settings_.throttle_frame_production); | |
473 TRACE_EVENT_INSTANT0("cc", | 408 TRACE_EVENT_INSTANT0("cc", |
474 "Scheduler::BeginRetroFrames all expired", | 409 "Scheduler::BeginRetroFrames all expired", |
475 TRACE_EVENT_SCOPE_THREAD); | 410 TRACE_EVENT_SCOPE_THREAD); |
476 } else { | 411 } else { |
477 BeginImplFrame(begin_retro_frame_args_.front()); | 412 BeginImplFrame(begin_retro_frame_args_.front()); |
478 begin_retro_frame_args_.pop_front(); | 413 begin_retro_frame_args_.pop_front(); |
479 } | 414 } |
480 } | 415 } |
481 | 416 |
482 // There could be a race between the posted BeginRetroFrame and a new | 417 // There could be a race between the posted BeginRetroFrame and a new |
483 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | 418 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame |
484 // will check if there is a pending BeginRetroFrame to ensure we handle | 419 // will check if there is a pending BeginRetroFrame to ensure we handle |
485 // BeginFrames in FIFO order. | 420 // BeginFrames in FIFO order. |
486 void Scheduler::PostBeginRetroFrameIfNeeded() { | 421 void Scheduler::PostBeginRetroFrameIfNeeded() { |
487 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 422 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
488 "Scheduler::PostBeginRetroFrameIfNeeded", | 423 "Scheduler::PostBeginRetroFrameIfNeeded", |
489 "state", | 424 "state", |
490 AsValue()); | 425 AsValue()); |
491 if (!last_set_needs_begin_frame_) | 426 if (!frame_source_->NeedsBeginFrames()) |
492 return; | 427 return; |
493 | 428 |
494 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) | 429 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) |
495 return; | 430 return; |
496 | 431 |
497 // begin_retro_frame_args_ should always be empty for the | 432 // begin_retro_frame_args_ should always be empty for the |
498 // synchronous compositor. | 433 // synchronous compositor. |
499 DCHECK(!settings_.using_synchronous_renderer_compositor); | 434 DCHECK(!settings_.using_synchronous_renderer_compositor); |
500 | 435 |
501 if (state_machine_.begin_impl_frame_state() != | 436 if (state_machine_.begin_impl_frame_state() != |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 } | 626 } |
692 | 627 |
693 bool Scheduler::WillDrawIfNeeded() const { | 628 bool Scheduler::WillDrawIfNeeded() const { |
694 return !state_machine_.PendingDrawsShouldBeAborted(); | 629 return !state_machine_.PendingDrawsShouldBeAborted(); |
695 } | 630 } |
696 | 631 |
697 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() | 632 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() |
698 const { | 633 const { |
699 scoped_refptr<base::debug::TracedValue> state = | 634 scoped_refptr<base::debug::TracedValue> state = |
700 new base::debug::TracedValue(); | 635 new base::debug::TracedValue(); |
636 AsValueInto(state.get()); | |
637 return state; | |
638 } | |
639 | |
640 void Scheduler::AsValueInto(base::debug::TracedValue* state) const { | |
701 state->BeginDictionary("state_machine"); | 641 state->BeginDictionary("state_machine"); |
702 state_machine_.AsValueInto(state.get()); | 642 state_machine_.AsValueInto(state); |
703 state->EndDictionary(); | 643 state->EndDictionary(); |
704 if (synthetic_begin_frame_source_) { | 644 |
705 state->BeginDictionary("synthetic_begin_frame_source_"); | 645 state->BeginDictionary("frame_source_"); |
706 synthetic_begin_frame_source_->AsValueInto(state.get()); | 646 frame_source_->AsValueInto(state); |
707 state->EndDictionary(); | 647 state->EndDictionary(); |
708 } | |
709 | 648 |
710 state->BeginDictionary("scheduler_state"); | 649 state->BeginDictionary("scheduler_state"); |
711 state->SetDouble("time_until_anticipated_draw_time_ms", | 650 state->SetDouble("time_until_anticipated_draw_time_ms", |
712 (AnticipatedDrawTime() - Now()).InMillisecondsF()); | 651 (AnticipatedDrawTime() - Now()).InMillisecondsF()); |
713 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF()); | |
714 state->SetDouble("estimated_parent_draw_time_ms", | 652 state->SetDouble("estimated_parent_draw_time_ms", |
715 estimated_parent_draw_time_.InMillisecondsF()); | 653 estimated_parent_draw_time_.InMillisecondsF()); |
716 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); | 654 state->SetBoolean("last_set_needs_begin_frame_", |
717 state->SetBoolean("begin_unthrottled_frame_posted_", | 655 frame_source_->NeedsBeginFrames()); |
718 begin_unthrottled_frame_posted_); | |
719 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); | 656 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); |
720 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); | 657 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); |
721 state->SetBoolean("begin_impl_frame_deadline_task_", | 658 state->SetBoolean("begin_impl_frame_deadline_task_", |
722 !begin_impl_frame_deadline_task_.IsCancelled()); | 659 !begin_impl_frame_deadline_task_.IsCancelled()); |
723 state->SetBoolean("poll_for_draw_triggers_task_", | 660 state->SetBoolean("poll_for_draw_triggers_task_", |
724 !poll_for_draw_triggers_task_.IsCancelled()); | 661 !poll_for_draw_triggers_task_.IsCancelled()); |
725 state->SetBoolean("advance_commit_state_task_", | 662 state->SetBoolean("advance_commit_state_task_", |
726 !advance_commit_state_task_.IsCancelled()); | 663 !advance_commit_state_task_.IsCancelled()); |
727 state->BeginDictionary("begin_impl_frame_args"); | 664 state->BeginDictionary("begin_impl_frame_args"); |
728 begin_impl_frame_args_.AsValueInto(state.get()); | 665 begin_impl_frame_args_.AsValueInto(state); |
729 state->EndDictionary(); | 666 state->EndDictionary(); |
730 | 667 |
731 state->EndDictionary(); | 668 state->EndDictionary(); |
732 | 669 |
733 state->BeginDictionary("client_state"); | 670 state->BeginDictionary("client_state"); |
734 state->SetDouble("draw_duration_estimate_ms", | 671 state->SetDouble("draw_duration_estimate_ms", |
735 client_->DrawDurationEstimate().InMillisecondsF()); | 672 client_->DrawDurationEstimate().InMillisecondsF()); |
736 state->SetDouble( | 673 state->SetDouble( |
737 "begin_main_frame_to_commit_duration_estimate_ms", | 674 "begin_main_frame_to_commit_duration_estimate_ms", |
738 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); | 675 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); |
739 state->SetDouble( | 676 state->SetDouble( |
740 "commit_to_activate_duration_estimate_ms", | 677 "commit_to_activate_duration_estimate_ms", |
741 client_->CommitToActivateDurationEstimate().InMillisecondsF()); | 678 client_->CommitToActivateDurationEstimate().InMillisecondsF()); |
742 state->EndDictionary(); | 679 state->EndDictionary(); |
743 return state; | |
744 } | 680 } |
745 | 681 |
746 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 682 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
747 // Check if the main thread computation and commit can be finished before the | 683 // Check if the main thread computation and commit can be finished before the |
748 // impl thread's deadline. | 684 // impl thread's deadline. |
749 base::TimeTicks estimated_draw_time = | 685 base::TimeTicks estimated_draw_time = |
750 begin_impl_frame_args_.frame_time + | 686 begin_impl_frame_args_.frame_time + |
751 client_->BeginMainFrameToCommitDurationEstimate() + | 687 client_->BeginMainFrameToCommitDurationEstimate() + |
752 client_->CommitToActivateDurationEstimate(); | 688 client_->CommitToActivateDurationEstimate(); |
753 | 689 |
754 TRACE_EVENT2( | 690 TRACE_EVENT2( |
755 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 691 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
756 "CanCommitAndActivateBeforeDeadline", | 692 "CanCommitAndActivateBeforeDeadline", |
757 "time_left_after_drawing_ms", | 693 "time_left_after_drawing_ms", |
758 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), | 694 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), |
759 "state", | 695 "state", |
760 AsValue()); | 696 AsValue()); |
761 | 697 |
762 return estimated_draw_time < begin_impl_frame_args_.deadline; | 698 return estimated_draw_time < begin_impl_frame_args_.deadline; |
763 } | 699 } |
764 | 700 |
765 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 701 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
766 return (state_machine_.commit_state() == | 702 return (state_machine_.commit_state() == |
767 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 703 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
768 state_machine_.commit_state() == | 704 state_machine_.commit_state() == |
769 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 705 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
770 } | 706 } |
771 | 707 |
772 } // namespace cc | 708 } // namespace cc |
OLD | NEW |