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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
452 bool main_thread_is_in_high_latency_mode = | 452 bool main_thread_is_in_high_latency_mode = |
453 state_machine_.MainThreadIsInHighLatencyMode(); | 453 state_machine_.MainThreadIsInHighLatencyMode(); |
454 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 454 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
455 args.AsValue(), "main_thread_is_high_latency", | 455 args.AsValue(), "main_thread_is_high_latency", |
456 main_thread_is_in_high_latency_mode); | 456 main_thread_is_in_high_latency_mode); |
457 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 457 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
458 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 458 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
459 | 459 |
460 BeginFrameArgs adjusted_args = args; | 460 BeginFrameArgs adjusted_args = args; |
461 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); | 461 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); |
462 begin_impl_frame_tracker_.Start(adjusted_args); | |
462 | 463 |
463 if (!state_machine_.impl_latency_takes_priority() && | 464 if (ShouldRecoverMainLatency()) { |
464 main_thread_is_in_high_latency_mode && | 465 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", |
465 CanCommitAndActivateBeforeDeadline()) { | 466 TRACE_EVENT_SCOPE_THREAD); |
466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 467 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
468 } else if (ShouldRecoverImplLatency()) { | |
469 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", | |
470 TRACE_EVENT_SCOPE_THREAD); | |
471 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
472 begin_impl_frame_tracker_.Finish(); | |
473 return; | |
467 } | 474 } |
468 | 475 |
469 BeginImplFrame(adjusted_args); | 476 BeginImplFrame(); |
mithro-old
2015/07/06 11:58:42
As discussed, you were going to change this code b
brianderson
2015/07/07 02:04:49
Done.
| |
470 | 477 |
471 // The deadline will be scheduled in ProcessScheduledActions. | 478 // The deadline will be scheduled in ProcessScheduledActions. |
472 state_machine_.OnBeginImplFrameDeadlinePending(); | 479 state_machine_.OnBeginImplFrameDeadlinePending(); |
473 ProcessScheduledActions(); | 480 ProcessScheduledActions(); |
474 } | 481 } |
475 | 482 |
476 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 483 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
477 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 484 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
478 args.AsValue()); | 485 args.AsValue()); |
479 BeginImplFrame(args); | 486 begin_impl_frame_tracker_.Start(args); |
487 BeginImplFrame(); | |
480 FinishImplFrame(); | 488 FinishImplFrame(); |
481 } | 489 } |
482 | 490 |
483 void Scheduler::FinishImplFrame() { | 491 void Scheduler::FinishImplFrame() { |
484 state_machine_.OnBeginImplFrameIdle(); | 492 state_machine_.OnBeginImplFrameIdle(); |
485 ProcessScheduledActions(); | 493 ProcessScheduledActions(); |
486 | 494 |
487 client_->DidFinishImplFrame(); | 495 client_->DidFinishImplFrame(); |
488 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 496 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
489 begin_impl_frame_tracker_.Finish(); | 497 begin_impl_frame_tracker_.Finish(); |
490 } | 498 } |
491 | 499 |
492 // 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 |
493 // 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 |
494 // any asynchronous animation and scroll/pinch updates. | 502 // any asynchronous animation and scroll/pinch updates. |
495 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 503 void Scheduler::BeginImplFrame() { |
496 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 504 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
497 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 505 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
498 DCHECK(!BeginImplFrameDeadlinePending()); | 506 DCHECK(!BeginImplFrameDeadlinePending()); |
499 DCHECK(state_machine_.HasInitializedOutputSurface()); | 507 DCHECK(state_machine_.HasInitializedOutputSurface()); |
500 | 508 |
501 begin_impl_frame_tracker_.Start(args); | |
502 state_machine_.OnBeginImplFrame(); | 509 state_machine_.OnBeginImplFrame(); |
503 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 510 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
504 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); | 511 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); |
505 | 512 |
506 ProcessScheduledActions(); | 513 ProcessScheduledActions(); |
507 } | 514 } |
508 | 515 |
509 void Scheduler::ScheduleBeginImplFrameDeadline() { | 516 void Scheduler::ScheduleBeginImplFrameDeadline() { |
510 // The synchronous compositor does not post a deadline task. | 517 // The synchronous compositor does not post a deadline task. |
511 DCHECK(!settings_.using_synchronous_renderer_compositor); | 518 DCHECK(!settings_.using_synchronous_renderer_compositor); |
512 | 519 |
513 begin_impl_frame_deadline_task_.Cancel(); | 520 begin_impl_frame_deadline_task_.Cancel(); |
514 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 521 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
515 | 522 |
516 begin_impl_frame_deadline_mode_ = | 523 begin_impl_frame_deadline_mode_ = |
517 state_machine_.CurrentBeginImplFrameDeadlineMode(); | 524 state_machine_.CurrentBeginImplFrameDeadlineMode(); |
518 | |
519 base::TimeTicks deadline; | 525 base::TimeTicks deadline; |
520 switch (begin_impl_frame_deadline_mode_) { | 526 switch (begin_impl_frame_deadline_mode_) { |
521 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: | 527 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: |
522 // No deadline. | 528 // No deadline. |
523 return; | 529 return; |
524 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: | 530 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: |
525 // We are ready to draw a new active tree immediately. | 531 // We are ready to draw a new active tree immediately. |
526 // We don't use Now() here because it's somewhat expensive to call. | 532 // We don't use Now() here because it's somewhat expensive to call. |
527 deadline = base::TimeTicks(); | 533 deadline = base::TimeTicks(); |
528 break; | 534 break; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
690 | 696 |
691 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() | 697 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() |
692 const { | 698 const { |
693 scoped_refptr<base::trace_event::TracedValue> state = | 699 scoped_refptr<base::trace_event::TracedValue> state = |
694 new base::trace_event::TracedValue(); | 700 new base::trace_event::TracedValue(); |
695 AsValueInto(state.get()); | 701 AsValueInto(state.get()); |
696 return state; | 702 return state; |
697 } | 703 } |
698 | 704 |
699 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { | 705 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { |
706 base::TimeTicks now = Now(); | |
707 | |
700 state->BeginDictionary("state_machine"); | 708 state->BeginDictionary("state_machine"); |
701 state_machine_.AsValueInto(state); | 709 state_machine_.AsValueInto(state); |
702 state->EndDictionary(); | 710 state->EndDictionary(); |
703 | 711 |
704 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 | 712 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 |
705 bool frame_tracing_enabled = false; | 713 bool frame_tracing_enabled = false; |
706 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 714 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
707 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), | 715 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), |
708 &frame_tracing_enabled); | 716 &frame_tracing_enabled); |
709 if (frame_tracing_enabled) { | 717 if (frame_tracing_enabled) { |
710 state->BeginDictionary("frame_source_"); | 718 state->BeginDictionary("frame_source_"); |
711 frame_source_->AsValueInto(state); | 719 frame_source_->AsValueInto(state); |
712 state->EndDictionary(); | 720 state->EndDictionary(); |
713 } | 721 } |
714 | 722 |
715 state->BeginDictionary("scheduler_state"); | 723 state->BeginDictionary("scheduler_state"); |
716 state->SetDouble("estimated_parent_draw_time_ms", | 724 state->SetDouble("estimated_parent_draw_time_ms", |
717 estimated_parent_draw_time_.InMillisecondsF()); | 725 estimated_parent_draw_time_.InMillisecondsF()); |
718 state->SetBoolean("last_set_needs_begin_frame_", | 726 state->SetBoolean("last_set_needs_begin_frame_", |
719 frame_source_->NeedsBeginFrames()); | 727 frame_source_->NeedsBeginFrames()); |
720 state->SetInteger("begin_retro_frame_args", | 728 state->SetInteger("begin_retro_frame_args", |
721 static_cast<int>(begin_retro_frame_args_.size())); | 729 static_cast<int>(begin_retro_frame_args_.size())); |
722 state->SetBoolean("begin_retro_frame_task", | 730 state->SetBoolean("begin_retro_frame_task", |
723 !begin_retro_frame_task_.IsCancelled()); | 731 !begin_retro_frame_task_.IsCancelled()); |
724 state->SetBoolean("begin_impl_frame_deadline_task", | 732 state->SetBoolean("begin_impl_frame_deadline_task", |
725 !begin_impl_frame_deadline_task_.IsCancelled()); | 733 !begin_impl_frame_deadline_task_.IsCancelled()); |
726 state->SetString("inside_action", | 734 state->SetString("inside_action", |
727 SchedulerStateMachine::ActionToString(inside_action_)); | 735 SchedulerStateMachine::ActionToString(inside_action_)); |
736 | |
728 state->BeginDictionary("begin_impl_frame_args"); | 737 state->BeginDictionary("begin_impl_frame_args"); |
729 begin_impl_frame_tracker_.AsValueInto(Now(), state); | 738 begin_impl_frame_tracker_.AsValueInto(now, state); |
730 state->EndDictionary(); | 739 state->EndDictionary(); |
740 | |
741 state->SetString("begin_impl_frame_deadline_mode_", | |
742 SchedulerStateMachine::BeginImplFrameDeadlineModeToString( | |
743 begin_impl_frame_deadline_mode_)); | |
731 state->EndDictionary(); | 744 state->EndDictionary(); |
732 | 745 |
733 state->BeginDictionary("compositor_timing_history"); | 746 state->BeginDictionary("compositor_timing_history"); |
734 compositor_timing_history_->AsValueInto(state); | 747 compositor_timing_history_->AsValueInto(state); |
735 state->EndDictionary(); | 748 state->EndDictionary(); |
736 } | 749 } |
737 | 750 |
738 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { | 751 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { |
739 compositor_timing_history_->SetRecordingEnabled( | 752 compositor_timing_history_->SetRecordingEnabled( |
740 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); | 753 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); |
741 } | 754 } |
742 | 755 |
756 bool Scheduler::ShouldRecoverMainLatency() const { | |
757 if (!state_machine_.MainThreadIsInHighLatencyMode()) | |
758 return false; | |
759 | |
760 if (state_machine_.impl_latency_takes_priority()) | |
761 return false; | |
762 | |
763 return CanCommitAndActivateBeforeDeadline(); | |
764 } | |
765 | |
766 bool Scheduler::ShouldRecoverImplLatency() const { | |
767 if (!state_machine_.SwapThrottled()) | |
768 return false; | |
769 | |
770 BeginFrameArgs args = | |
771 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); | |
mithro-old
2015/07/06 11:58:42
This seems wrong? Why does this need the *last* Be
brianderson
2015/07/07 02:04:49
Yeah, I should have just called Current(). Latest
| |
772 | |
773 // The deadline may be in the past if our draw time is too long. | |
774 bool frame_time_is_before_deadline = args.frame_time < args.deadline; | |
775 | |
776 SchedulerStateMachine::BeginImplFrameDeadlineMode | |
777 next_begin_impl_frame_deadline_mode = | |
778 state_machine_.CurrentBeginImplFrameDeadlineMode(); | |
779 switch (next_begin_impl_frame_deadline_mode) { | |
780 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: | |
781 return false; | |
782 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: | |
783 return frame_time_is_before_deadline; | |
784 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR: | |
785 return frame_time_is_before_deadline; | |
786 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE: | |
787 return CanCommitAndActivateBeforeDeadline(); | |
788 case SchedulerStateMachine:: | |
789 BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW: | |
790 return false; | |
791 } | |
792 NOTREACHED(); | |
793 return false; | |
794 } | |
795 | |
743 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 796 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
744 BeginFrameArgs args = | 797 BeginFrameArgs args = |
745 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); | 798 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); |
746 | 799 |
747 // Check if the main thread computation and commit can be finished before the | 800 // Check if the main thread computation and commit can be finished before the |
748 // impl thread's deadline. | 801 // impl thread's deadline. |
749 base::TimeTicks estimated_draw_time = | 802 base::TimeTicks estimated_draw_time = |
750 args.frame_time + | 803 args.frame_time + |
751 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + | 804 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + |
752 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + | 805 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + |
753 compositor_timing_history_->ActivateDurationEstimate(); | 806 compositor_timing_history_->ActivateDurationEstimate(); |
754 | 807 |
755 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
756 "CanCommitAndActivateBeforeDeadline", | |
757 "time_left_after_drawing_ms", | |
758 (args.deadline - estimated_draw_time).InMillisecondsF(), "state", | |
759 AsValue()); | |
760 | |
761 return estimated_draw_time < args.deadline; | 808 return estimated_draw_time < args.deadline; |
762 } | 809 } |
763 | 810 |
764 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 811 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
765 return (state_machine_.commit_state() == | 812 return (state_machine_.commit_state() == |
766 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 813 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
767 state_machine_.commit_state() == | 814 state_machine_.commit_state() == |
768 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 815 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
769 } | 816 } |
770 | 817 |
771 } // namespace cc | 818 } // namespace cc |
OLD | NEW |