| 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 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 ProcessScheduledActions(); | 73 ProcessScheduledActions(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 Scheduler::~Scheduler() { | 76 Scheduler::~Scheduler() { |
| 77 SetBeginFrameSource(nullptr); | 77 SetBeginFrameSource(nullptr); |
| 78 } | 78 } |
| 79 | 79 |
| 80 base::TimeTicks Scheduler::Now() const { | 80 base::TimeTicks Scheduler::Now() const { |
| 81 base::TimeTicks now = base::TimeTicks::Now(); | 81 base::TimeTicks now = base::TimeTicks::Now(); |
| 82 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), | 82 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), |
| 83 "Scheduler::Now", | 83 "Scheduler::Now", "now", now); |
| 84 "now", | |
| 85 now); | |
| 86 return now; | 84 return now; |
| 87 } | 85 } |
| 88 | 86 |
| 89 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 87 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
| 90 DCHECK_GE(draw_time.ToInternalValue(), 0); | 88 DCHECK_GE(draw_time.ToInternalValue(), 0); |
| 91 estimated_parent_draw_time_ = draw_time; | 89 estimated_parent_draw_time_ = draw_time; |
| 92 } | 90 } |
| 93 | 91 |
| 94 void Scheduler::SetVisible(bool visible) { | 92 void Scheduler::SetVisible(bool visible) { |
| 95 state_machine_.SetVisible(visible); | 93 state_machine_.SetVisible(visible); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 | 305 |
| 308 bool should_defer_begin_frame = | 306 bool should_defer_begin_frame = |
| 309 !begin_retro_frame_args_.empty() || | 307 !begin_retro_frame_args_.empty() || |
| 310 !begin_retro_frame_task_.IsCancelled() || | 308 !begin_retro_frame_task_.IsCancelled() || |
| 311 !observing_begin_frame_source_ || | 309 !observing_begin_frame_source_ || |
| 312 (state_machine_.begin_impl_frame_state() != | 310 (state_machine_.begin_impl_frame_state() != |
| 313 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 311 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 314 | 312 |
| 315 if (should_defer_begin_frame) { | 313 if (should_defer_begin_frame) { |
| 316 begin_retro_frame_args_.push_back(adjusted_args); | 314 begin_retro_frame_args_.push_back(adjusted_args); |
| 317 TRACE_EVENT_INSTANT0( | 315 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrame deferred", |
| 318 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | 316 TRACE_EVENT_SCOPE_THREAD); |
| 319 // Queuing the frame counts as "using it", so we need to return true. | 317 // Queuing the frame counts as "using it", so we need to return true. |
| 320 } else { | 318 } else { |
| 321 BeginImplFrameWithDeadline(adjusted_args); | 319 BeginImplFrameWithDeadline(adjusted_args); |
| 322 } | 320 } |
| 323 return true; | 321 return true; |
| 324 } | 322 } |
| 325 | 323 |
| 326 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { | 324 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
| 327 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); | 325 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
| 328 ProcessScheduledActions(); | 326 ProcessScheduledActions(); |
| 329 } | 327 } |
| 330 | 328 |
| 331 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { | 329 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { |
| 332 DCHECK(settings_.using_synchronous_renderer_compositor); | 330 DCHECK(settings_.using_synchronous_renderer_compositor); |
| 333 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 331 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 334 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 332 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 335 DCHECK(!BeginImplFrameDeadlinePending()); | 333 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 336 | 334 |
| 337 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); | 335 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); |
| 338 state_machine_.OnBeginImplFrameDeadline(); | 336 state_machine_.OnBeginImplFrameDeadline(); |
| 339 ProcessScheduledActions(); | 337 ProcessScheduledActions(); |
| 340 | 338 |
| 341 state_machine_.OnBeginImplFrameIdle(); | 339 state_machine_.OnBeginImplFrameIdle(); |
| 342 ProcessScheduledActions(); | 340 ProcessScheduledActions(); |
| 343 state_machine_.SetResourcelessSoftwareDraw(false); | 341 state_machine_.SetResourcelessSoftwareDraw(false); |
| 344 } | 342 } |
| 345 | 343 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 372 TRACE_EVENT_INSTANT2( | 370 TRACE_EVENT_INSTANT2( |
| 373 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, | 371 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, |
| 374 "expiration_time - now", (expiration_time - now).InMillisecondsF(), | 372 "expiration_time - now", (expiration_time - now).InMillisecondsF(), |
| 375 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); | 373 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); |
| 376 begin_retro_frame_args_.pop_front(); | 374 begin_retro_frame_args_.pop_front(); |
| 377 if (begin_frame_source_) | 375 if (begin_frame_source_) |
| 378 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); | 376 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); |
| 379 } | 377 } |
| 380 | 378 |
| 381 if (begin_retro_frame_args_.empty()) { | 379 if (begin_retro_frame_args_.empty()) { |
| 382 TRACE_EVENT_INSTANT0("cc", | 380 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginRetroFrames all expired", |
| 383 "Scheduler::BeginRetroFrames all expired", | |
| 384 TRACE_EVENT_SCOPE_THREAD); | 381 TRACE_EVENT_SCOPE_THREAD); |
| 385 } else { | 382 } else { |
| 386 BeginFrameArgs front = begin_retro_frame_args_.front(); | 383 BeginFrameArgs front = begin_retro_frame_args_.front(); |
| 387 begin_retro_frame_args_.pop_front(); | 384 begin_retro_frame_args_.pop_front(); |
| 388 BeginImplFrameWithDeadline(front); | 385 BeginImplFrameWithDeadline(front); |
| 389 } | 386 } |
| 390 } | 387 } |
| 391 | 388 |
| 392 // There could be a race between the posted BeginRetroFrame and a new | 389 // There could be a race between the posted BeginRetroFrame and a new |
| 393 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | 390 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame |
| 394 // will check if there is a pending BeginRetroFrame to ensure we handle | 391 // will check if there is a pending BeginRetroFrame to ensure we handle |
| 395 // BeginFrames in FIFO order. | 392 // BeginFrames in FIFO order. |
| 396 void Scheduler::PostBeginRetroFrameIfNeeded() { | 393 void Scheduler::PostBeginRetroFrameIfNeeded() { |
| 397 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 394 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 398 "Scheduler::PostBeginRetroFrameIfNeeded", | 395 "Scheduler::PostBeginRetroFrameIfNeeded", "state", AsValue()); |
| 399 "state", | |
| 400 AsValue()); | |
| 401 if (!observing_begin_frame_source_) | 396 if (!observing_begin_frame_source_) |
| 402 return; | 397 return; |
| 403 | 398 |
| 404 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) | 399 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) |
| 405 return; | 400 return; |
| 406 | 401 |
| 407 // begin_retro_frame_args_ should always be empty for the | 402 // begin_retro_frame_args_ should always be empty for the |
| 408 // synchronous compositor. | 403 // synchronous compositor. |
| 409 DCHECK(!settings_.using_synchronous_renderer_compositor); | 404 DCHECK(!settings_.using_synchronous_renderer_compositor); |
| 410 | 405 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); | 496 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); |
| 502 begin_impl_frame_tracker_.Finish(); | 497 begin_impl_frame_tracker_.Finish(); |
| 503 } | 498 } |
| 504 | 499 |
| 505 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 500 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
| 506 // for a BeginMainFrame+activation to complete before it times out and draws | 501 // for a BeginMainFrame+activation to complete before it times out and draws |
| 507 // any asynchronous animation and scroll/pinch updates. | 502 // any asynchronous animation and scroll/pinch updates. |
| 508 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 503 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
| 509 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 504 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 510 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 505 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 511 DCHECK(!BeginImplFrameDeadlinePending()); | 506 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 512 DCHECK(state_machine_.HasInitializedOutputSurface()); | 507 DCHECK(state_machine_.HasInitializedOutputSurface()); |
| 513 | 508 |
| 514 begin_impl_frame_tracker_.Start(args); | 509 begin_impl_frame_tracker_.Start(args); |
| 515 state_machine_.OnBeginImplFrame(); | 510 state_machine_.OnBeginImplFrame(); |
| 516 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 511 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
| 517 compositor_timing_history_->WillBeginImplFrame( | 512 compositor_timing_history_->WillBeginImplFrame( |
| 518 state_machine_.NewActiveTreeLikely()); | 513 state_machine_.NewActiveTreeLikely()); |
| 519 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); | 514 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); |
| 520 | 515 |
| 521 ProcessScheduledActions(); | 516 ProcessScheduledActions(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 void Scheduler::ScheduleBeginImplFrameDeadlineIfNeeded() { | 568 void Scheduler::ScheduleBeginImplFrameDeadlineIfNeeded() { |
| 574 if (settings_.using_synchronous_renderer_compositor) | 569 if (settings_.using_synchronous_renderer_compositor) |
| 575 return; | 570 return; |
| 576 | 571 |
| 577 if (state_machine_.begin_impl_frame_state() != | 572 if (state_machine_.begin_impl_frame_state() != |
| 578 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 573 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
| 579 return; | 574 return; |
| 580 | 575 |
| 581 if (begin_impl_frame_deadline_mode_ == | 576 if (begin_impl_frame_deadline_mode_ == |
| 582 state_machine_.CurrentBeginImplFrameDeadlineMode() && | 577 state_machine_.CurrentBeginImplFrameDeadlineMode() && |
| 583 BeginImplFrameDeadlinePending()) | 578 !begin_impl_frame_deadline_task_.IsCancelled()) { |
| 584 return; | 579 return; |
| 580 } |
| 585 | 581 |
| 586 ScheduleBeginImplFrameDeadline(); | 582 ScheduleBeginImplFrameDeadline(); |
| 587 } | 583 } |
| 588 | 584 |
| 589 void Scheduler::OnBeginImplFrameDeadline() { | 585 void Scheduler::OnBeginImplFrameDeadline() { |
| 590 TRACE_EVENT0("cc,benchmark", "Scheduler::OnBeginImplFrameDeadline"); | 586 TRACE_EVENT0("cc,benchmark", "Scheduler::OnBeginImplFrameDeadline"); |
| 591 begin_impl_frame_deadline_task_.Cancel(); | 587 begin_impl_frame_deadline_task_.Cancel(); |
| 592 // We split the deadline actions up into two phases so the state machine | 588 // We split the deadline actions up into two phases so the state machine |
| 593 // has a chance to trigger actions that should occur durring and after | 589 // has a chance to trigger actions that should occur durring and after |
| 594 // the deadline separately. For example: | 590 // the deadline separately. For example: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 compositor_timing_history_->WillDraw(); | 626 compositor_timing_history_->WillDraw(); |
| 631 state_machine_.WillDraw(); | 627 state_machine_.WillDraw(); |
| 632 DrawResult result = client_->ScheduledActionDrawAndSwapForced(); | 628 DrawResult result = client_->ScheduledActionDrawAndSwapForced(); |
| 633 state_machine_.DidDraw(result); | 629 state_machine_.DidDraw(result); |
| 634 compositor_timing_history_->DidDraw( | 630 compositor_timing_history_->DidDraw( |
| 635 drawing_with_new_active_tree, main_thread_missed_last_deadline, | 631 drawing_with_new_active_tree, main_thread_missed_last_deadline, |
| 636 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time); | 632 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time); |
| 637 } | 633 } |
| 638 | 634 |
| 639 void Scheduler::SetDeferCommits(bool defer_commits) { | 635 void Scheduler::SetDeferCommits(bool defer_commits) { |
| 640 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", | 636 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", "defer_commits", |
| 641 "defer_commits", | 637 defer_commits); |
| 642 defer_commits); | |
| 643 state_machine_.SetDeferCommits(defer_commits); | 638 state_machine_.SetDeferCommits(defer_commits); |
| 644 ProcessScheduledActions(); | 639 ProcessScheduledActions(); |
| 645 } | 640 } |
| 646 | 641 |
| 647 void Scheduler::ProcessScheduledActions() { | 642 void Scheduler::ProcessScheduledActions() { |
| 648 // We do not allow ProcessScheduledActions to be recursive. | 643 // We do not allow ProcessScheduledActions to be recursive. |
| 649 // The top-level call will iteratively execute the next action for us anyway. | 644 // The top-level call will iteratively execute the next action for us anyway. |
| 650 if (inside_process_scheduled_actions_) | 645 if (inside_process_scheduled_actions_) |
| 651 return; | 646 return; |
| 652 | 647 |
| 653 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 648 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| 654 | 649 |
| 655 SchedulerStateMachine::Action action; | 650 SchedulerStateMachine::Action action; |
| 656 do { | 651 do { |
| 657 action = state_machine_.NextAction(); | 652 action = state_machine_.NextAction(); |
| 658 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 653 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 659 "SchedulerStateMachine", | 654 "SchedulerStateMachine", "state", AsValue()); |
| 660 "state", | 655 base::AutoReset<SchedulerStateMachine::Action> mark_inside_action( |
| 661 AsValue()); | 656 &inside_action_, action); |
| 662 base::AutoReset<SchedulerStateMachine::Action> | |
| 663 mark_inside_action(&inside_action_, action); | |
| 664 switch (action) { | 657 switch (action) { |
| 665 case SchedulerStateMachine::ACTION_NONE: | 658 case SchedulerStateMachine::ACTION_NONE: |
| 666 break; | 659 break; |
| 667 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: | 660 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
| 668 compositor_timing_history_->WillBeginMainFrame( | 661 compositor_timing_history_->WillBeginMainFrame( |
| 669 begin_main_frame_args_.on_critical_path, | 662 begin_main_frame_args_.on_critical_path, |
| 670 begin_main_frame_args_.frame_time); | 663 begin_main_frame_args_.frame_time); |
| 671 state_machine_.WillSendBeginMainFrame(); | 664 state_machine_.WillSendBeginMainFrame(); |
| 672 // TODO(brianderson): Pass begin_main_frame_args_ directly to client. | 665 // TODO(brianderson): Pass begin_main_frame_args_ directly to client. |
| 673 client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); | 666 client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 } | 834 } |
| 842 | 835 |
| 843 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 836 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 844 return (state_machine_.begin_main_frame_state() == | 837 return (state_machine_.begin_main_frame_state() == |
| 845 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || | 838 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || |
| 846 state_machine_.begin_main_frame_state() == | 839 state_machine_.begin_main_frame_state() == |
| 847 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); | 840 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); |
| 848 } | 841 } |
| 849 | 842 |
| 850 } // namespace cc | 843 } // namespace cc |
| OLD | NEW |