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

Side by Side Diff: cc/scheduler/scheduler.cc

Issue 2392113003: Reland of cc: Remove frame queuing from the scheduler. (Closed)
Patch Set: rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_state_machine.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/scheduler/scheduler.h" 5 #include "cc/scheduler/scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 28 matching lines...) Expand all
39 task_runner_(task_runner), 39 task_runner_(task_runner),
40 begin_frame_source_(nullptr), 40 begin_frame_source_(nullptr),
41 observing_begin_frame_source_(false), 41 observing_begin_frame_source_(false),
42 compositor_timing_history_(std::move(compositor_timing_history)), 42 compositor_timing_history_(std::move(compositor_timing_history)),
43 begin_impl_frame_deadline_mode_( 43 begin_impl_frame_deadline_mode_(
44 SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE), 44 SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE),
45 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), 45 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE),
46 state_machine_(settings), 46 state_machine_(settings),
47 inside_process_scheduled_actions_(false), 47 inside_process_scheduled_actions_(false),
48 inside_action_(SchedulerStateMachine::ACTION_NONE), 48 inside_action_(SchedulerStateMachine::ACTION_NONE),
49 stopped_(false),
49 weak_factory_(this) { 50 weak_factory_(this) {
50 TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue()); 51 TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue());
51 DCHECK(client_); 52 DCHECK(client_);
52 DCHECK(!state_machine_.BeginFrameNeeded()); 53 DCHECK(!state_machine_.BeginFrameNeeded());
53 54
54 begin_retro_frame_closure_ =
55 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
56 begin_impl_frame_deadline_closure_ = base::Bind( 55 begin_impl_frame_deadline_closure_ = base::Bind(
57 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); 56 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
58 57
59 ProcessScheduledActions(); 58 ProcessScheduledActions();
60 } 59 }
61 60
62 Scheduler::~Scheduler() { 61 Scheduler::~Scheduler() {
63 SetBeginFrameSource(nullptr); 62 SetBeginFrameSource(nullptr);
64 } 63 }
65 64
65 void Scheduler::Stop() {
66 stopped_ = true;
67 }
68
66 base::TimeTicks Scheduler::Now() const { 69 base::TimeTicks Scheduler::Now() const {
67 base::TimeTicks now = base::TimeTicks::Now(); 70 base::TimeTicks now = base::TimeTicks::Now();
68 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), 71 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
69 "Scheduler::Now", "now", now); 72 "Scheduler::Now", "now", now);
70 return now; 73 return now;
71 } 74 }
72 75
73 void Scheduler::SetVisible(bool visible) { 76 void Scheduler::SetVisible(bool visible) {
74 state_machine_.SetVisible(visible); 77 state_machine_.SetVisible(visible);
75 UpdateCompositorTimingHistoryRecordingEnabled(); 78 UpdateCompositorTimingHistoryRecordingEnabled();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 compositor_timing_history_->WillPrepareTiles(); 177 compositor_timing_history_->WillPrepareTiles();
175 } 178 }
176 179
177 void Scheduler::DidPrepareTiles() { 180 void Scheduler::DidPrepareTiles() {
178 compositor_timing_history_->DidPrepareTiles(); 181 compositor_timing_history_->DidPrepareTiles();
179 state_machine_.DidPrepareTiles(); 182 state_machine_.DidPrepareTiles();
180 } 183 }
181 184
182 void Scheduler::DidLoseCompositorFrameSink() { 185 void Scheduler::DidLoseCompositorFrameSink() {
183 TRACE_EVENT0("cc", "Scheduler::DidLoseCompositorFrameSink"); 186 TRACE_EVENT0("cc", "Scheduler::DidLoseCompositorFrameSink");
184 begin_retro_frame_args_.clear();
185 begin_retro_frame_task_.Cancel();
186 state_machine_.DidLoseCompositorFrameSink(); 187 state_machine_.DidLoseCompositorFrameSink();
187 UpdateCompositorTimingHistoryRecordingEnabled(); 188 UpdateCompositorTimingHistoryRecordingEnabled();
188 ProcessScheduledActions(); 189 ProcessScheduledActions();
189 } 190 }
190 191
191 void Scheduler::DidCreateAndInitializeCompositorFrameSink() { 192 void Scheduler::DidCreateAndInitializeCompositorFrameSink() {
192 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeCompositorFrameSink"); 193 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeCompositorFrameSink");
193 DCHECK(!observing_begin_frame_source_); 194 DCHECK(!observing_begin_frame_source_);
194 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); 195 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
195 state_machine_.DidCreateAndInitializeCompositorFrameSink(); 196 state_machine_.DidCreateAndInitializeCompositorFrameSink();
(...skipping 16 matching lines...) Expand all
212 void Scheduler::BeginImplFrameNotExpectedSoon() { 213 void Scheduler::BeginImplFrameNotExpectedSoon() {
213 compositor_timing_history_->BeginImplFrameNotExpectedSoon(); 214 compositor_timing_history_->BeginImplFrameNotExpectedSoon();
214 215
215 // Tying this to SendBeginMainFrameNotExpectedSoon will have some 216 // Tying this to SendBeginMainFrameNotExpectedSoon will have some
216 // false negatives, but we want to avoid running long idle tasks when 217 // false negatives, but we want to avoid running long idle tasks when
217 // we are actually active. 218 // we are actually active.
218 client_->SendBeginMainFrameNotExpectedSoon(); 219 client_->SendBeginMainFrameNotExpectedSoon();
219 } 220 }
220 221
221 void Scheduler::SetupNextBeginFrameIfNeeded() { 222 void Scheduler::SetupNextBeginFrameIfNeeded() {
222 // Never call SetNeedsBeginFrames if the frame source already has the right 223 if (state_machine_.begin_impl_frame_state() !=
223 // value. 224 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) {
224 if (observing_begin_frame_source_ != state_machine_.BeginFrameNeeded()) { 225 return;
225 if (state_machine_.BeginFrameNeeded()) {
226 // Call AddObserver as soon as possible.
227 observing_begin_frame_source_ = true;
228 if (begin_frame_source_)
229 begin_frame_source_->AddObserver(this);
230 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
231 true);
232 } else if (state_machine_.begin_impl_frame_state() ==
233 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) {
234 // Call RemoveObserver in between frames only.
235 observing_begin_frame_source_ = false;
236 if (begin_frame_source_)
237 begin_frame_source_->RemoveObserver(this);
238 BeginImplFrameNotExpectedSoon();
239 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
240 false);
241 }
242 } 226 }
243 227
244 PostBeginRetroFrameIfNeeded(); 228 bool needs_begin_frames = state_machine_.BeginFrameNeeded();
229 if (needs_begin_frames && !observing_begin_frame_source_) {
230 observing_begin_frame_source_ = true;
231 if (begin_frame_source_)
232 begin_frame_source_->AddObserver(this);
233 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, true);
234 } else if (!needs_begin_frames && observing_begin_frame_source_) {
235 observing_begin_frame_source_ = false;
236 if (begin_frame_source_)
237 begin_frame_source_->RemoveObserver(this);
238 missed_begin_frame_task_.Cancel();
239 BeginImplFrameNotExpectedSoon();
240 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
241 false);
242 }
245 } 243 }
246 244
247 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { 245 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) {
248 if (state_machine_.begin_frame_source_paused() == paused) 246 if (state_machine_.begin_frame_source_paused() == paused)
249 return; 247 return;
250 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused", 248 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused",
251 TRACE_EVENT_SCOPE_THREAD, "paused", paused); 249 TRACE_EVENT_SCOPE_THREAD, "paused", paused);
252 state_machine_.SetBeginFrameSourcePaused(paused); 250 state_machine_.SetBeginFrameSourcePaused(paused);
253 ProcessScheduledActions(); 251 ProcessScheduledActions();
254 } 252 }
255 253
256 // BeginFrame is the mechanism that tells us that now is a good time to start 254 // BeginFrame is the mechanism that tells us that now is a good time to start
257 // making a frame. Usually this means that user input for the frame is complete. 255 // making a frame. Usually this means that user input for the frame is complete.
258 // If the scheduler is busy, we queue the BeginFrame to be handled later as 256 // If the scheduler is busy, we queue the BeginFrame to be handled later as
259 // a BeginRetroFrame. 257 // a BeginRetroFrame.
260 bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { 258 bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
261 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); 259 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue());
262 260
261 if (!state_machine_.BeginFrameNeeded()) {
262 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped",
263 TRACE_EVENT_SCOPE_THREAD);
264 return false;
265 }
266
263 // Trace this begin frame time through the Chrome stack 267 // Trace this begin frame time through the Chrome stack
264 TRACE_EVENT_FLOW_BEGIN0( 268 TRACE_EVENT_FLOW_BEGIN0(
265 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", 269 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
266 args.frame_time.ToInternalValue()); 270 args.frame_time.ToInternalValue());
267 271
268 if (settings_.using_synchronous_renderer_compositor) { 272 if (settings_.using_synchronous_renderer_compositor) {
269 BeginImplFrameSynchronous(args); 273 BeginImplFrameSynchronous(args);
270 return true; 274 return true;
271 } 275 }
272 276
273 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has 277 if (inside_process_scheduled_actions_) {
274 // sent us the last BeginFrame we have missed. As we might not be able to 278 // The BFS can send a missed begin frame inside AddObserver. We can't handle
275 // actually make rendering for this call, handle it like a "retro frame". 279 // a begin frame inside ProcessScheduledActions so post a task.
276 // TODO(brainderson): Add a test for this functionality ASAP! 280 DCHECK_EQ(args.type, BeginFrameArgs::MISSED);
277 if (args.type == BeginFrameArgs::MISSED) { 281 DCHECK(missed_begin_frame_task_.IsCancelled());
278 begin_retro_frame_args_.push_back(args); 282 missed_begin_frame_task_.Reset(base::Bind(
279 PostBeginRetroFrameIfNeeded(); 283 &Scheduler::BeginImplFrameWithDeadline, base::Unretained(this), args));
284 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
280 return true; 285 return true;
281 } 286 }
282 287
283 bool should_defer_begin_frame = 288 BeginImplFrameWithDeadline(args);
284 !begin_retro_frame_args_.empty() ||
285 !begin_retro_frame_task_.IsCancelled() ||
286 !observing_begin_frame_source_ ||
287 (state_machine_.begin_impl_frame_state() !=
288 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
289
290 if (should_defer_begin_frame) {
291 begin_retro_frame_args_.push_back(args);
292 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrame deferred",
293 TRACE_EVENT_SCOPE_THREAD);
294 // Queuing the frame counts as "using it", so we need to return true.
295 } else {
296 BeginImplFrameWithDeadline(args);
297 }
298 return true; 289 return true;
299 } 290 }
300 291
301 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { 292 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) {
302 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); 293 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames);
303 ProcessScheduledActions(); 294 ProcessScheduledActions();
304 } 295 }
305 296
306 void Scheduler::OnDrawForCompositorFrameSink(bool resourceless_software_draw) { 297 void Scheduler::OnDrawForCompositorFrameSink(bool resourceless_software_draw) {
307 DCHECK(settings_.using_synchronous_renderer_compositor); 298 DCHECK(settings_.using_synchronous_renderer_compositor);
308 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 299 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
309 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 300 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
310 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); 301 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
311 302
312 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); 303 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw);
313 state_machine_.OnBeginImplFrameDeadline(); 304 state_machine_.OnBeginImplFrameDeadline();
314 ProcessScheduledActions(); 305 ProcessScheduledActions();
315 306
316 state_machine_.OnBeginImplFrameIdle(); 307 state_machine_.OnBeginImplFrameIdle();
317 ProcessScheduledActions(); 308 ProcessScheduledActions();
318 state_machine_.SetResourcelessSoftwareDraw(false); 309 state_machine_.SetResourcelessSoftwareDraw(false);
319 } 310 }
320 311
321 // BeginRetroFrame is called for BeginFrames that we've deferred because 312 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
322 // the scheduler was in the middle of processing a previous BeginFrame. 313 // The storage for |args| is owned by the missed begin frame task. Therefore
323 void Scheduler::BeginRetroFrame() { 314 // save |args| before cancelling the task either here or in the deadline.
324 TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame"); 315 BeginFrameArgs adjusted_args = args;
325 DCHECK(!settings_.using_synchronous_renderer_compositor); 316 // Cancel the missed begin frame task in case the BFS sends a begin frame
326 DCHECK(!begin_retro_frame_args_.empty()); 317 // before the missed frame task runs.
327 DCHECK(!begin_retro_frame_task_.IsCancelled()); 318 missed_begin_frame_task_.Cancel();
319
320 // Discard missed begin frames if they are too late.
321 if (adjusted_args.type == BeginFrameArgs::MISSED &&
322 Now() > adjusted_args.deadline) {
323 begin_frame_source_->DidFinishFrame(this, 0);
324 return;
325 }
326
327 // Run the previous deadline if any.
328 if (state_machine_.begin_impl_frame_state() ==
329 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) {
330 OnBeginImplFrameDeadline();
331 // We may not need begin frames any longer.
332 if (!observing_begin_frame_source_) {
333 begin_frame_source_->DidFinishFrame(this, 0);
334 return;
335 }
336 }
328 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 337 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
329 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 338 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
330 339
331 begin_retro_frame_task_.Cancel();
332
333 // Discard expired BeginRetroFrames
334 // Today, we should always end up with at most one un-expired BeginRetroFrame
335 // because deadlines will not be greater than the next frame time. We don't
336 // DCHECK though because some systems don't always have monotonic timestamps.
337 // TODO(brianderson): In the future, long deadlines could result in us not
338 // draining the queue if we don't catch up. If we consistently can't catch
339 // up, our fallback should be to lower our frame rate.
340 base::TimeTicks now = Now();
341
342 while (!begin_retro_frame_args_.empty()) {
343 const BeginFrameArgs& args = begin_retro_frame_args_.front();
344 base::TimeTicks expiration_time = args.deadline;
345 if (now <= expiration_time)
346 break;
347 TRACE_EVENT_INSTANT2(
348 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD,
349 "expiration_time - now", (expiration_time - now).InMillisecondsF(),
350 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue());
351 begin_retro_frame_args_.pop_front();
352 if (begin_frame_source_)
353 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size());
354 }
355
356 if (begin_retro_frame_args_.empty()) {
357 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginRetroFrames all expired",
358 TRACE_EVENT_SCOPE_THREAD);
359 } else {
360 BeginFrameArgs front = begin_retro_frame_args_.front();
361 begin_retro_frame_args_.pop_front();
362 BeginImplFrameWithDeadline(front);
363 }
364 }
365
366 // There could be a race between the posted BeginRetroFrame and a new
367 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
368 // will check if there is a pending BeginRetroFrame to ensure we handle
369 // BeginFrames in FIFO order.
370 void Scheduler::PostBeginRetroFrameIfNeeded() {
371 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
372 "Scheduler::PostBeginRetroFrameIfNeeded", "state", AsValue());
373 if (!observing_begin_frame_source_)
374 return;
375
376 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled())
377 return;
378
379 // begin_retro_frame_args_ should always be empty for the
380 // synchronous compositor.
381 DCHECK(!settings_.using_synchronous_renderer_compositor);
382
383 if (state_machine_.begin_impl_frame_state() !=
384 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE)
385 return;
386
387 begin_retro_frame_task_.Reset(begin_retro_frame_closure_);
388
389 task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback());
390 }
391
392 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
393 bool main_thread_is_in_high_latency_mode = 340 bool main_thread_is_in_high_latency_mode =
394 state_machine_.main_thread_missed_last_deadline(); 341 state_machine_.main_thread_missed_last_deadline();
395 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", 342 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
396 args.AsValue(), "main_thread_missed_last_deadline", 343 adjusted_args.AsValue(), "main_thread_missed_last_deadline",
397 main_thread_is_in_high_latency_mode); 344 main_thread_is_in_high_latency_mode);
398 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), 345 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
399 "MainThreadLatency", main_thread_is_in_high_latency_mode); 346 "MainThreadLatency", main_thread_is_in_high_latency_mode);
400 347
401 BeginFrameArgs adjusted_args = args; 348 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
349 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
350
402 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); 351 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
403 adjusted_args.deadline -= kDeadlineFudgeFactor; 352 adjusted_args.deadline -= kDeadlineFudgeFactor;
404 353
405 base::TimeDelta bmf_start_to_activate = 354 base::TimeDelta bmf_start_to_activate =
406 compositor_timing_history_ 355 compositor_timing_history_
407 ->BeginMainFrameStartToCommitDurationEstimate() + 356 ->BeginMainFrameStartToCommitDurationEstimate() +
408 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + 357 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
409 compositor_timing_history_->ActivateDurationEstimate(); 358 compositor_timing_history_->ActivateDurationEstimate();
410 359
411 base::TimeDelta bmf_to_activate_estimate_critical = 360 base::TimeDelta bmf_to_activate_estimate_critical =
412 bmf_start_to_activate + 361 bmf_start_to_activate +
413 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate(); 362 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate();
414 363
415 state_machine_.SetCriticalBeginMainFrameToActivateIsFast( 364 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(
416 bmf_to_activate_estimate_critical < args.interval); 365 bmf_to_activate_estimate_critical < adjusted_args.interval);
417 366
418 // Update the BeginMainFrame args now that we know whether the main 367 // Update the BeginMainFrame args now that we know whether the main
419 // thread will be on the critical path or not. 368 // thread will be on the critical path or not.
420 begin_main_frame_args_ = adjusted_args; 369 begin_main_frame_args_ = adjusted_args;
421 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); 370 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
422 371
423 base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical; 372 base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical;
424 if (!begin_main_frame_args_.on_critical_path) { 373 if (!begin_main_frame_args_.on_critical_path) {
425 bmf_to_activate_estimate = 374 bmf_to_activate_estimate =
426 bmf_start_to_activate + 375 bmf_start_to_activate +
427 compositor_timing_history_ 376 compositor_timing_history_
428 ->BeginMainFrameQueueDurationNotCriticalEstimate(); 377 ->BeginMainFrameQueueDurationNotCriticalEstimate();
429 } 378 }
430 379
431 bool can_activate_before_deadline = 380 bool can_activate_before_deadline =
432 CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args, 381 CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args,
433 bmf_to_activate_estimate); 382 bmf_to_activate_estimate);
434 383
435 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { 384 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) {
436 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", 385 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
437 TRACE_EVENT_SCOPE_THREAD); 386 TRACE_EVENT_SCOPE_THREAD);
438 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); 387 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
439 } else if (ShouldRecoverImplLatency(adjusted_args, 388 } else if (ShouldRecoverImplLatency(adjusted_args,
440 can_activate_before_deadline)) { 389 can_activate_before_deadline)) {
441 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", 390 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
442 TRACE_EVENT_SCOPE_THREAD); 391 TRACE_EVENT_SCOPE_THREAD);
443 if (begin_frame_source_) 392 if (begin_frame_source_)
444 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); 393 begin_frame_source_->DidFinishFrame(this, 0);
445 return; 394 return;
446 } 395 }
447 396
448 BeginImplFrame(adjusted_args); 397 BeginImplFrame(adjusted_args);
449 } 398 }
450 399
451 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { 400 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
452 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", 401 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
453 args.AsValue()); 402 args.AsValue());
454 403
455 // The main thread currently can't commit before we draw with the 404 // The main thread currently can't commit before we draw with the
456 // synchronous compositor, so never consider the BeginMainFrame fast. 405 // synchronous compositor, so never consider the BeginMainFrame fast.
457 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); 406 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false);
458 begin_main_frame_args_ = args; 407 begin_main_frame_args_ = args;
459 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); 408 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
460 409
461 BeginImplFrame(args); 410 BeginImplFrame(args);
462 compositor_timing_history_->WillFinishImplFrame( 411 compositor_timing_history_->WillFinishImplFrame(
463 state_machine_.needs_redraw()); 412 state_machine_.needs_redraw());
464 FinishImplFrame(); 413 FinishImplFrame();
465 } 414 }
466 415
467 void Scheduler::FinishImplFrame() { 416 void Scheduler::FinishImplFrame() {
468 state_machine_.OnBeginImplFrameIdle(); 417 state_machine_.OnBeginImplFrameIdle();
469 ProcessScheduledActions(); 418 ProcessScheduledActions();
470 419
471 client_->DidFinishImplFrame(); 420 client_->DidFinishImplFrame();
472 if (begin_frame_source_) 421 if (begin_frame_source_)
473 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); 422 begin_frame_source_->DidFinishFrame(this, 0);
474 begin_impl_frame_tracker_.Finish(); 423 begin_impl_frame_tracker_.Finish();
475 } 424 }
476 425
477 // BeginImplFrame starts a compositor frame that will wait up until a deadline 426 // BeginImplFrame starts a compositor frame that will wait up until a deadline
478 // for a BeginMainFrame+activation to complete before it times out and draws 427 // for a BeginMainFrame+activation to complete before it times out and draws
479 // any asynchronous animation and scroll/pinch updates. 428 // any asynchronous animation and scroll/pinch updates.
480 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { 429 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
481 DCHECK_EQ(state_machine_.begin_impl_frame_state(), 430 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
482 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); 431 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
483 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); 432 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 554 }
606 555
607 void Scheduler::SetDeferCommits(bool defer_commits) { 556 void Scheduler::SetDeferCommits(bool defer_commits) {
608 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", "defer_commits", 557 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", "defer_commits",
609 defer_commits); 558 defer_commits);
610 state_machine_.SetDeferCommits(defer_commits); 559 state_machine_.SetDeferCommits(defer_commits);
611 ProcessScheduledActions(); 560 ProcessScheduledActions();
612 } 561 }
613 562
614 void Scheduler::ProcessScheduledActions() { 563 void Scheduler::ProcessScheduledActions() {
564 // Do not perform actions during compositor shutdown.
565 if (stopped_)
566 return;
567
615 // We do not allow ProcessScheduledActions to be recursive. 568 // We do not allow ProcessScheduledActions to be recursive.
616 // The top-level call will iteratively execute the next action for us anyway. 569 // The top-level call will iteratively execute the next action for us anyway.
617 if (inside_process_scheduled_actions_) 570 if (inside_process_scheduled_actions_)
618 return; 571 return;
619 572
620 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); 573 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true);
621 574
622 SchedulerStateMachine::Action action; 575 SchedulerStateMachine::Action action;
623 do { 576 do {
624 action = state_machine_.NextAction(); 577 action = state_machine_.NextAction();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 new base::trace_event::TracedValue()); 641 new base::trace_event::TracedValue());
689 base::TimeTicks now = Now(); 642 base::TimeTicks now = Now();
690 643
691 state->BeginDictionary("state_machine"); 644 state->BeginDictionary("state_machine");
692 state_machine_.AsValueInto(state.get()); 645 state_machine_.AsValueInto(state.get());
693 state->EndDictionary(); 646 state->EndDictionary();
694 647
695 state->BeginDictionary("scheduler_state"); 648 state->BeginDictionary("scheduler_state");
696 state->SetBoolean("observing_begin_frame_source", 649 state->SetBoolean("observing_begin_frame_source",
697 observing_begin_frame_source_); 650 observing_begin_frame_source_);
698 state->SetInteger("begin_retro_frame_args",
699 static_cast<int>(begin_retro_frame_args_.size()));
700 state->SetBoolean("begin_retro_frame_task",
701 !begin_retro_frame_task_.IsCancelled());
702 state->SetBoolean("begin_impl_frame_deadline_task", 651 state->SetBoolean("begin_impl_frame_deadline_task",
703 !begin_impl_frame_deadline_task_.IsCancelled()); 652 !begin_impl_frame_deadline_task_.IsCancelled());
653 state->SetBoolean("missed_begin_frame_task",
654 !missed_begin_frame_task_.IsCancelled());
704 state->SetString("inside_action", 655 state->SetString("inside_action",
705 SchedulerStateMachine::ActionToString(inside_action_)); 656 SchedulerStateMachine::ActionToString(inside_action_));
706 657
707 state->BeginDictionary("begin_impl_frame_args"); 658 state->BeginDictionary("begin_impl_frame_args");
708 begin_impl_frame_tracker_.AsValueInto(now, state.get()); 659 begin_impl_frame_tracker_.AsValueInto(now, state.get());
709 state->EndDictionary(); 660 state->EndDictionary();
710 661
711 state->SetString("begin_impl_frame_deadline_mode_", 662 state->SetString("begin_impl_frame_deadline_mode_",
712 SchedulerStateMachine::BeginImplFrameDeadlineModeToString( 663 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
713 begin_impl_frame_deadline_mode_)); 664 begin_impl_frame_deadline_mode_));
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 } 749 }
799 750
800 bool Scheduler::IsBeginMainFrameSentOrStarted() const { 751 bool Scheduler::IsBeginMainFrameSentOrStarted() const {
801 return (state_machine_.begin_main_frame_state() == 752 return (state_machine_.begin_main_frame_state() ==
802 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || 753 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT ||
803 state_machine_.begin_main_frame_state() == 754 state_machine_.begin_main_frame_state() ==
804 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); 755 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED);
805 } 756 }
806 757
807 } // namespace cc 758 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_state_machine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698