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 "cc/scheduler/frame_source.h" | |
15 #include "ui/gfx/frame_time.h" | 16 #include "ui/gfx/frame_time.h" |
16 | 17 |
17 namespace cc { | 18 namespace cc { |
18 | 19 |
19 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( | |
20 Scheduler* scheduler, | |
21 base::SingleThreadTaskRunner* task_runner) | |
22 : scheduler_(scheduler) { | |
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); | |
31 } | |
32 | |
33 Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { | |
34 } | |
35 | |
36 void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters( | |
37 base::TimeTicks timebase, | |
38 base::TimeDelta interval) { | |
39 time_source_->SetTimebaseAndInterval(timebase, interval); | |
40 } | |
41 | |
42 void Scheduler::SyntheticBeginFrameSource::SetNeedsBeginFrame( | |
43 bool needs_begin_frame, | |
44 std::deque<BeginFrameArgs>* begin_retro_frame_args) { | |
45 DCHECK(begin_retro_frame_args); | |
46 base::TimeTicks missed_tick_time = | |
47 time_source_->SetActive(needs_begin_frame); | |
48 if (!missed_tick_time.is_null()) { | |
49 begin_retro_frame_args->push_back( | |
50 CreateSyntheticBeginFrameArgs(missed_tick_time)); | |
51 } | |
52 } | |
53 | |
54 bool Scheduler::SyntheticBeginFrameSource::IsActive() const { | |
55 return time_source_->Active(); | |
56 } | |
57 | |
58 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() { | |
59 BeginFrameArgs begin_frame_args( | |
60 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); | |
61 scheduler_->BeginFrame(begin_frame_args); | |
62 } | |
63 | |
64 scoped_ptr<base::Value> Scheduler::SyntheticBeginFrameSource::AsValue() const { | |
65 return time_source_->AsValue(); | |
66 } | |
67 | |
68 BeginFrameArgs | |
69 Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs( | |
70 base::TimeTicks frame_time) { | |
71 base::TimeTicks deadline = | |
72 time_source_->NextTickTime() - scheduler_->EstimatedParentDrawTime(); | |
73 return BeginFrameArgs::Create( | |
74 frame_time, deadline, scheduler_->VSyncInterval()); | |
75 } | |
76 | |
77 Scheduler::Scheduler( | 20 Scheduler::Scheduler( |
78 SchedulerClient* client, | 21 SchedulerClient* client, |
79 const SchedulerSettings& scheduler_settings, | 22 const SchedulerSettings& scheduler_settings, |
80 int layer_tree_host_id, | 23 int layer_tree_host_id, |
24 BeginFrameSource* external_frame_source, | |
81 const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) | 25 const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) |
82 : settings_(scheduler_settings), | 26 : settings_(scheduler_settings), |
83 client_(client), | 27 client_(client), |
84 layer_tree_host_id_(layer_tree_host_id), | 28 layer_tree_host_id_(layer_tree_host_id), |
85 impl_task_runner_(impl_task_runner), | 29 impl_task_runner_(impl_task_runner), |
86 vsync_interval_(BeginFrameArgs::DefaultInterval()), | |
87 last_set_needs_begin_frame_(false), | |
88 begin_unthrottled_frame_posted_(false), | |
89 begin_retro_frame_posted_(false), | 30 begin_retro_frame_posted_(false), |
90 state_machine_(scheduler_settings), | 31 state_machine_(scheduler_settings), |
91 inside_process_scheduled_actions_(false), | 32 inside_process_scheduled_actions_(false), |
92 inside_action_(SchedulerStateMachine::ACTION_NONE), | 33 inside_action_(SchedulerStateMachine::ACTION_NONE), |
93 weak_factory_(this) { | 34 weak_factory_(this) { |
94 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 35 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
95 "Scheduler::Scheduler", | 36 "Scheduler::Scheduler", |
96 "settings", | 37 "settings", |
97 ToTrace(settings_)); | 38 ToTrace(settings_)); |
98 DCHECK(client_); | 39 DCHECK(client_); |
99 DCHECK(!state_machine_.BeginFrameNeeded()); | 40 DCHECK(!state_machine_.BeginFrameNeeded()); |
100 if (settings_.main_frame_before_activation_enabled) { | 41 if (settings_.main_frame_before_activation_enabled) { |
101 DCHECK(settings_.main_frame_before_draw_enabled); | 42 DCHECK(settings_.main_frame_before_draw_enabled); |
102 } | 43 } |
103 | 44 |
104 begin_retro_frame_closure_ = | 45 begin_retro_frame_closure_ = |
105 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 46 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
106 begin_unthrottled_frame_closure_ = | |
107 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | |
108 begin_impl_frame_deadline_closure_ = base::Bind( | 47 begin_impl_frame_deadline_closure_ = base::Bind( |
109 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 48 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
110 poll_for_draw_triggers_closure_ = base::Bind( | 49 poll_for_draw_triggers_closure_ = base::Bind( |
111 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 50 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
112 advance_commit_state_closure_ = base::Bind( | 51 advance_commit_state_closure_ = base::Bind( |
113 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 52 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
114 | 53 |
115 if (!settings_.begin_frame_scheduling_enabled) { | 54 scoped_ptr<BeginFrameSource> primary_frame_source; |
simonhong
2014/06/12 13:47:39
foreground_frame_source?
| |
116 SetupSyntheticBeginFrames(); | 55 |
56 if (!settings_.throttle_frame_production) { | |
57 TRACE_EVENT0("cc", "Scheduler::Scheduler() BackToBackBeginFrameSource"); | |
58 primary_frame_source = scoped_ptr<BeginFrameSource>( | |
59 new BackToBackBeginFrameSource(this, impl_task_runner_)); | |
60 } else if (settings_.begin_frame_scheduling_enabled) { | |
61 TRACE_EVENT0("cc", "Scheduler::Scheduler() ProxyBeginFrameSource"); | |
62 primary_frame_source = scoped_ptr<BeginFrameSource>( | |
63 new ProxyBeginFrameSource(this, external_frame_source)); | |
64 } else { | |
65 TRACE_EVENT0("cc", "Scheduler::Scheduler() SyntheticBeginFrameSource"); | |
66 primary_frame_source = | |
67 scoped_ptr<BeginFrameSource>(new SyntheticBeginFrameSource( | |
68 this, impl_task_runner_, BeginFrameArgs::DefaultInterval())); | |
117 } | 69 } |
70 scoped_ptr<BeginFrameSource> background_frame_source( | |
71 new SyntheticBeginFrameSource( | |
72 this, impl_task_runner_, base::TimeDelta::FromSeconds(1))); | |
73 | |
74 frame_source_ = scoped_ptr<DualBeginFrameSource>(new DualBeginFrameSource( | |
75 this, primary_frame_source.Pass(), background_frame_source.Pass())); | |
118 } | 76 } |
119 | 77 |
120 Scheduler::~Scheduler() { | 78 Scheduler::~Scheduler() { |
121 if (synthetic_begin_frame_source_) { | 79 frame_source_->SetGenerateFrames(false); |
122 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | |
123 &begin_retro_frame_args_); | |
124 } | |
125 } | |
126 | |
127 void Scheduler::SetupSyntheticBeginFrames() { | |
128 DCHECK(!synthetic_begin_frame_source_); | |
129 synthetic_begin_frame_source_.reset( | |
130 new SyntheticBeginFrameSource(this, impl_task_runner_.get())); | |
131 } | 80 } |
132 | 81 |
133 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 82 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
134 base::TimeDelta interval) { | 83 base::TimeDelta interval) { |
135 // TODO(brianderson): We should not be receiving 0 intervals. | 84 frame_source_->SetTimeBaseAndInterval(timebase, interval); |
136 if (interval == base::TimeDelta()) | |
137 interval = BeginFrameArgs::DefaultInterval(); | |
138 vsync_interval_ = interval; | |
139 if (!settings_.begin_frame_scheduling_enabled) | |
140 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | |
141 } | 85 } |
142 | 86 |
143 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 87 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
144 estimated_parent_draw_time_ = draw_time; | 88 estimated_parent_draw_time_ = draw_time; |
145 } | 89 } |
146 | 90 |
147 void Scheduler::SetCanStart() { | 91 void Scheduler::SetCanStart() { |
148 state_machine_.SetCanStart(); | 92 state_machine_.SetCanStart(); |
149 ProcessScheduledActions(); | 93 ProcessScheduledActions(); |
150 } | 94 } |
151 | 95 |
152 void Scheduler::SetVisible(bool visible) { | 96 void Scheduler::SetVisible(bool visible) { |
153 TRACE_EVENT1("cc", "Scheduler::SetVisible", "visible?", visible); | 97 TRACE_EVENT1("cc", "Scheduler::SetVisible", "visible?", visible); |
154 state_machine_.SetVisible(visible); | 98 state_machine_.SetVisible(visible); |
99 if (visible) { | |
100 frame_source_->SwitchSource(frame_source_->SourceForeground()); | |
brianderson
2014/06/17 06:24:43
SwitchToForeground() and SwitchToBackground()?
| |
101 } else { | |
102 frame_source_->SwitchSource(frame_source_->SourceBackground()); | |
103 } | |
simonhong
2014/06/12 13:47:39
I think Scheduler should manage and switch fourgro
| |
155 ProcessScheduledActions(); | 104 ProcessScheduledActions(); |
156 } | 105 } |
157 | 106 |
158 void Scheduler::SetCanDraw(bool can_draw) { | 107 void Scheduler::SetCanDraw(bool can_draw) { |
159 state_machine_.SetCanDraw(can_draw); | 108 state_machine_.SetCanDraw(can_draw); |
160 ProcessScheduledActions(); | 109 ProcessScheduledActions(); |
161 } | 110 } |
162 | 111 |
163 void Scheduler::NotifyReadyToActivate() { | 112 void Scheduler::NotifyReadyToActivate() { |
164 state_machine_.NotifyReadyToActivate(); | 113 state_machine_.NotifyReadyToActivate(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 ProcessScheduledActions(); | 176 ProcessScheduledActions(); |
228 } | 177 } |
229 | 178 |
230 void Scheduler::DidManageTiles() { | 179 void Scheduler::DidManageTiles() { |
231 state_machine_.DidManageTiles(); | 180 state_machine_.DidManageTiles(); |
232 } | 181 } |
233 | 182 |
234 void Scheduler::DidLoseOutputSurface() { | 183 void Scheduler::DidLoseOutputSurface() { |
235 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 184 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
236 state_machine_.DidLoseOutputSurface(); | 185 state_machine_.DidLoseOutputSurface(); |
237 last_set_needs_begin_frame_ = false; | 186 frame_source_->SetGenerateFrames(false); |
238 if (!settings_.begin_frame_scheduling_enabled) { | |
239 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | |
240 &begin_retro_frame_args_); | |
241 } | |
242 begin_retro_frame_args_.clear(); | 187 begin_retro_frame_args_.clear(); |
243 ProcessScheduledActions(); | 188 ProcessScheduledActions(); |
244 } | 189 } |
245 | 190 |
246 void Scheduler::DidCreateAndInitializeOutputSurface() { | 191 void Scheduler::DidCreateAndInitializeOutputSurface() { |
247 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 192 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
248 DCHECK(!last_set_needs_begin_frame_); | 193 DCHECK(!frame_source_->IsGeneratingFrames()); |
249 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 194 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
250 state_machine_.DidCreateAndInitializeOutputSurface(); | 195 state_machine_.DidCreateAndInitializeOutputSurface(); |
251 ProcessScheduledActions(); | 196 ProcessScheduledActions(); |
252 } | 197 } |
253 | 198 |
254 void Scheduler::NotifyBeginMainFrameStarted() { | 199 void Scheduler::NotifyBeginMainFrameStarted() { |
255 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 200 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
256 state_machine_.NotifyBeginMainFrameStarted(); | 201 state_machine_.NotifyBeginMainFrameStarted(); |
257 } | 202 } |
258 | 203 |
259 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | 204 base::TimeTicks Scheduler::AnticipatedDrawTime() const { |
260 if (!last_set_needs_begin_frame_ || | 205 if (!frame_source_->IsGeneratingFrames() || |
261 begin_impl_frame_args_.interval <= base::TimeDelta()) | 206 begin_impl_frame_args_.interval <= base::TimeDelta()) |
262 return base::TimeTicks(); | 207 return base::TimeTicks(); |
263 | 208 |
264 base::TimeTicks now = gfx::FrameTime::Now(); | 209 base::TimeTicks now = gfx::FrameTime::Now(); |
265 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, | 210 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, |
266 begin_impl_frame_args_.deadline); | 211 begin_impl_frame_args_.deadline); |
267 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); | 212 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); |
268 return timebase + (begin_impl_frame_args_.interval * intervals); | 213 return timebase + (begin_impl_frame_args_.interval * intervals); |
269 } | 214 } |
270 | 215 |
271 base::TimeTicks Scheduler::LastBeginImplFrameTime() { | 216 base::TimeTicks Scheduler::LastBeginImplFrameTime() { |
272 return begin_impl_frame_args_.frame_time; | 217 return begin_impl_frame_args_.frame_time; |
273 } | 218 } |
274 | 219 |
275 void Scheduler::SetupNextBeginFrameIfNeeded() { | 220 void Scheduler::SetupNextBeginFrameIfNeeded() { |
276 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); | 221 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); |
277 | 222 |
278 if (settings_.throttle_frame_production) { | 223 bool at_end_of_deadline = |
279 SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame); | 224 (state_machine_.begin_impl_frame_state() == |
280 } else { | 225 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) || |
281 SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame); | 226 (state_machine_.begin_impl_frame_state() == |
227 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
228 | |
229 bool should_call_set_needs_begin_frame = | |
230 // Always request the BeginFrame immediately if it wasn't needed before. | |
231 needs_begin_frame || | |
232 // Only stop requesting BeginFrames after a deadline. | |
233 (!needs_begin_frame && at_end_of_deadline); | |
234 | |
235 if (should_call_set_needs_begin_frame) { | |
236 frame_source_->SetGenerateFrames(needs_begin_frame); | |
282 } | 237 } |
238 | |
239 // TODO(mithro): Use pending frames properly. | |
240 if (at_end_of_deadline) | |
241 frame_source_->PendingFrames(0); | |
242 | |
243 PostBeginRetroFrameIfNeeded(); | |
283 SetupPollingMechanisms(needs_begin_frame); | 244 SetupPollingMechanisms(needs_begin_frame); |
284 } | 245 } |
285 | 246 |
286 // When we are throttling frame production, we request BeginFrames | |
287 // from the OutputSurface. | |
288 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled( | |
289 bool needs_begin_frame) { | |
290 bool at_end_of_deadline = | |
291 state_machine_.begin_impl_frame_state() == | |
292 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | |
293 | |
294 bool should_call_set_needs_begin_frame = | |
295 // Always request the BeginFrame immediately if it wasn't needed before. | |
296 (needs_begin_frame && !last_set_needs_begin_frame_) || | |
297 // Only stop requesting BeginFrames after a deadline. | |
298 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); | |
299 | |
300 if (should_call_set_needs_begin_frame) { | |
301 if (settings_.begin_frame_scheduling_enabled) { | |
302 client_->SetNeedsBeginFrame(needs_begin_frame); | |
303 } else { | |
304 synthetic_begin_frame_source_->SetNeedsBeginFrame( | |
305 needs_begin_frame, &begin_retro_frame_args_); | |
306 } | |
307 last_set_needs_begin_frame_ = needs_begin_frame; | |
308 } | |
309 | |
310 PostBeginRetroFrameIfNeeded(); | |
311 } | |
312 | |
313 // When we aren't throttling frame production, we initiate a BeginFrame | |
314 // as soon as one is needed. | |
315 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled( | |
316 bool needs_begin_frame) { | |
317 last_set_needs_begin_frame_ = needs_begin_frame; | |
318 | |
319 if (!needs_begin_frame || begin_unthrottled_frame_posted_) | |
320 return; | |
321 | |
322 if (state_machine_.begin_impl_frame_state() != | |
323 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE && | |
324 state_machine_.begin_impl_frame_state() != | |
325 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { | |
326 return; | |
327 } | |
328 | |
329 begin_unthrottled_frame_posted_ = true; | |
330 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); | |
331 } | |
332 | |
333 // BeginUnthrottledFrame is used when we aren't throttling frame production. | |
334 // This will usually be because VSync is disabled. | |
335 void Scheduler::BeginUnthrottledFrame() { | |
336 DCHECK(!settings_.throttle_frame_production); | |
337 DCHECK(begin_retro_frame_args_.empty()); | |
338 | |
339 base::TimeTicks now = gfx::FrameTime::Now(); | |
340 base::TimeTicks deadline = now + vsync_interval_; | |
341 | |
342 BeginFrameArgs begin_frame_args = | |
343 BeginFrameArgs::Create(now, deadline, vsync_interval_); | |
344 BeginImplFrame(begin_frame_args); | |
345 | |
346 begin_unthrottled_frame_posted_ = false; | |
347 } | |
348 | |
349 // We may need to poll when we can't rely on BeginFrame to advance certain | 247 // We may need to poll when we can't rely on BeginFrame to advance certain |
350 // state or to avoid deadlock. | 248 // state or to avoid deadlock. |
351 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { | 249 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { |
352 bool needs_advance_commit_state_timer = false; | 250 bool needs_advance_commit_state_timer = false; |
353 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but | 251 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
354 // aren't expecting any more BeginFrames. This should only be needed by | 252 // aren't expecting any more BeginFrames. This should only be needed by |
355 // the synchronous compositor when BeginFrameNeeded is false. | 253 // the synchronous compositor when BeginFrameNeeded is false. |
356 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { | 254 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { |
357 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); | 255 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); |
358 DCHECK(!needs_begin_frame); | 256 DCHECK(!needs_begin_frame); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 advance_commit_state_task_.Cancel(); | 292 advance_commit_state_task_.Cancel(); |
395 } | 293 } |
396 } | 294 } |
397 | 295 |
398 // BeginFrame is the mechanism that tells us that now is a good time to start | 296 // BeginFrame is the mechanism that tells us that now is a good time to start |
399 // making a frame. Usually this means that user input for the frame is complete. | 297 // making a frame. Usually this means that user input for the frame is complete. |
400 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 298 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
401 // a BeginRetroFrame. | 299 // a BeginRetroFrame. |
402 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 300 void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
403 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args)); | 301 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args)); |
404 DCHECK(settings_.throttle_frame_production); | 302 |
303 BeginFrameArgs adjusted_args(args); | |
304 adjusted_args.deadline -= EstimatedParentDrawTime(); | |
405 | 305 |
406 bool should_defer_begin_frame; | 306 bool should_defer_begin_frame; |
407 if (settings_.using_synchronous_renderer_compositor) { | 307 if (settings_.using_synchronous_renderer_compositor) { |
408 should_defer_begin_frame = false; | 308 should_defer_begin_frame = false; |
409 } else { | 309 } else { |
410 should_defer_begin_frame = | 310 should_defer_begin_frame = |
411 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | 311 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
412 !last_set_needs_begin_frame_ || | 312 !frame_source_->IsGeneratingFrames() || |
413 (state_machine_.begin_impl_frame_state() != | 313 (state_machine_.begin_impl_frame_state() != |
414 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 314 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
415 } | 315 } |
416 | 316 |
417 if (should_defer_begin_frame) { | 317 if (should_defer_begin_frame) { |
418 begin_retro_frame_args_.push_back(args); | 318 begin_retro_frame_args_.push_back(adjusted_args); |
419 TRACE_EVENT_INSTANT0( | 319 TRACE_EVENT_INSTANT1("cc", |
420 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | 320 "Scheduler::BeginFrame deferred", |
321 TRACE_EVENT_SCOPE_THREAD, | |
322 "args", | |
323 ToTrace(adjusted_args)); | |
421 return; | 324 return; |
422 } | 325 } |
423 | 326 |
424 BeginImplFrame(args); | 327 BeginImplFrame(adjusted_args); |
425 } | 328 } |
426 | 329 |
427 // BeginRetroFrame is called for BeginFrames that we've deferred because | 330 // BeginRetroFrame is called for BeginFrames that we've deferred because |
428 // the scheduler was in the middle of processing a previous BeginFrame. | 331 // the scheduler was in the middle of processing a previous BeginFrame. |
429 void Scheduler::BeginRetroFrame() { | 332 void Scheduler::BeginRetroFrame() { |
430 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); | 333 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); |
431 DCHECK(!settings_.using_synchronous_renderer_compositor); | 334 DCHECK(!settings_.using_synchronous_renderer_compositor); |
432 DCHECK(begin_retro_frame_posted_); | 335 DCHECK(begin_retro_frame_posted_); |
433 begin_retro_frame_posted_ = false; | 336 begin_retro_frame_posted_ = false; |
434 | 337 |
(...skipping 10 matching lines...) Expand all Loading... | |
445 // draining the queue if we don't catch up. If we consistently can't catch | 348 // draining the queue if we don't catch up. If we consistently can't catch |
446 // up, our fallback should be to lower our frame rate. | 349 // up, our fallback should be to lower our frame rate. |
447 base::TimeTicks now = gfx::FrameTime::Now(); | 350 base::TimeTicks now = gfx::FrameTime::Now(); |
448 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 351 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
449 while (!begin_retro_frame_args_.empty() && | 352 while (!begin_retro_frame_args_.empty() && |
450 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), | 353 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), |
451 draw_duration_estimate)) { | 354 draw_duration_estimate)) { |
452 TRACE_EVENT1("cc", | 355 TRACE_EVENT1("cc", |
453 "Scheduler::BeginRetroFrame discarding", | 356 "Scheduler::BeginRetroFrame discarding", |
454 "frame_time", | 357 "frame_time", |
455 begin_retro_frame_args_.front().frame_time); | 358 ToTrace(begin_retro_frame_args_.front())); |
456 begin_retro_frame_args_.pop_front(); | 359 begin_retro_frame_args_.pop_front(); |
457 } | 360 } |
458 | 361 |
459 if (begin_retro_frame_args_.empty()) { | 362 if (begin_retro_frame_args_.empty()) { |
460 DCHECK(settings_.throttle_frame_production); | |
brianderson
2014/06/17 06:24:43
Why is this DCHECK removed?
| |
461 TRACE_EVENT_INSTANT0("cc", | 363 TRACE_EVENT_INSTANT0("cc", |
462 "Scheduler::BeginRetroFrames all expired", | 364 "Scheduler::BeginRetroFrames all expired", |
463 TRACE_EVENT_SCOPE_THREAD); | 365 TRACE_EVENT_SCOPE_THREAD); |
464 } else { | 366 } else { |
465 BeginImplFrame(begin_retro_frame_args_.front()); | 367 BeginImplFrame(begin_retro_frame_args_.front()); |
466 begin_retro_frame_args_.pop_front(); | 368 begin_retro_frame_args_.pop_front(); |
467 } | 369 } |
468 } | 370 } |
469 | 371 |
470 // There could be a race between the posted BeginRetroFrame and a new | 372 // There could be a race between the posted BeginRetroFrame and a new |
471 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | 373 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame |
472 // will check if there is a pending BeginRetroFrame to ensure we handle | 374 // will check if there is a pending BeginRetroFrame to ensure we handle |
473 // BeginFrames in FIFO order. | 375 // BeginFrames in FIFO order. |
474 void Scheduler::PostBeginRetroFrameIfNeeded() { | 376 void Scheduler::PostBeginRetroFrameIfNeeded() { |
475 if (!last_set_needs_begin_frame_) | 377 if (!frame_source_->IsGeneratingFrames()) |
476 return; | 378 return; |
477 | 379 |
478 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) | 380 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) |
479 return; | 381 return; |
480 | 382 |
481 // begin_retro_frame_args_ should always be empty for the | 383 // begin_retro_frame_args_ should always be empty for the |
482 // synchronous compositor. | 384 // synchronous compositor. |
483 DCHECK(!settings_.using_synchronous_renderer_compositor); | 385 DCHECK(!settings_.using_synchronous_renderer_compositor); |
484 | 386 |
485 if (state_machine_.begin_impl_frame_state() != | 387 if (state_machine_.begin_impl_frame_state() != |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 } | 576 } |
675 } | 577 } |
676 | 578 |
677 bool Scheduler::WillDrawIfNeeded() const { | 579 bool Scheduler::WillDrawIfNeeded() const { |
678 return !state_machine_.PendingDrawsShouldBeAborted(); | 580 return !state_machine_.PendingDrawsShouldBeAborted(); |
679 } | 581 } |
680 | 582 |
681 scoped_ptr<base::Value> Scheduler::AsValue() const { | 583 scoped_ptr<base::Value> Scheduler::AsValue() const { |
682 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | 584 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); |
683 state->Set("state_machine", state_machine_.AsValue().release()); | 585 state->Set("state_machine", state_machine_.AsValue().release()); |
684 if (synthetic_begin_frame_source_) | 586 state->Set("frame_source", |
685 state->Set("synthetic_begin_frame_source_", | 587 frame_source_->BeginFrameSourceAsValue().release()); |
brianderson
2014/06/17 06:24:43
BeginFrameSourceAsValue -> AsValue()?
| |
686 synthetic_begin_frame_source_->AsValue().release()); | |
687 | 588 |
688 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); | 589 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); |
689 scheduler_state->SetDouble( | 590 scheduler_state->SetDouble( |
690 "time_until_anticipated_draw_time_ms", | 591 "time_until_anticipated_draw_time_ms", |
691 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); | 592 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); |
692 scheduler_state->SetDouble("vsync_interval_ms", | |
693 vsync_interval_.InMillisecondsF()); | |
694 scheduler_state->SetDouble("estimated_parent_draw_time_ms", | 593 scheduler_state->SetDouble("estimated_parent_draw_time_ms", |
695 estimated_parent_draw_time_.InMillisecondsF()); | 594 estimated_parent_draw_time_.InMillisecondsF()); |
696 scheduler_state->SetBoolean("last_set_needs_begin_frame_", | 595 scheduler_state->SetBoolean("last_set_needs_begin_frame_", |
697 last_set_needs_begin_frame_); | 596 frame_source_->IsGeneratingFrames()); |
698 scheduler_state->SetBoolean("begin_unthrottled_frame_posted_", | |
699 begin_unthrottled_frame_posted_); | |
700 scheduler_state->SetBoolean("begin_retro_frame_posted_", | 597 scheduler_state->SetBoolean("begin_retro_frame_posted_", |
701 begin_retro_frame_posted_); | 598 begin_retro_frame_posted_); |
702 scheduler_state->SetInteger("begin_retro_frame_args_", | 599 scheduler_state->SetInteger("begin_retro_frame_args_", |
703 begin_retro_frame_args_.size()); | 600 begin_retro_frame_args_.size()); |
704 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", | 601 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", |
705 !begin_impl_frame_deadline_task_.IsCancelled()); | 602 !begin_impl_frame_deadline_task_.IsCancelled()); |
706 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", | 603 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", |
707 !poll_for_draw_triggers_task_.IsCancelled()); | 604 !poll_for_draw_triggers_task_.IsCancelled()); |
708 scheduler_state->SetBoolean("advance_commit_state_task_", | 605 scheduler_state->SetBoolean("advance_commit_state_task_", |
709 !advance_commit_state_task_.IsCancelled()); | 606 !advance_commit_state_task_.IsCancelled()); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 } | 642 } |
746 | 643 |
747 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 644 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
748 return (state_machine_.commit_state() == | 645 return (state_machine_.commit_state() == |
749 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 646 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
750 state_machine_.commit_state() == | 647 state_machine_.commit_state() == |
751 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 648 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
752 } | 649 } |
753 | 650 |
754 } // namespace cc | 651 } // namespace cc |
OLD | NEW |