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