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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 | 462 |
463 if (!state_machine_.impl_latency_takes_priority() && | 463 if (ShouldRecoverMainLatency(adjusted_args)) { |
464 main_thread_is_in_high_latency_mode && | 464 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", |
465 CanCommitAndActivateBeforeDeadline()) { | 465 TRACE_EVENT_SCOPE_THREAD); |
466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 466 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
467 } else if (ShouldRecoverImplLatency(adjusted_args)) { | |
468 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", | |
469 TRACE_EVENT_SCOPE_THREAD); | |
470 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
471 return; | |
467 } | 472 } |
468 | 473 |
469 BeginImplFrame(adjusted_args); | 474 BeginImplFrame(adjusted_args); |
470 | 475 |
471 // The deadline will be scheduled in ProcessScheduledActions. | 476 // The deadline will be scheduled in ProcessScheduledActions. |
472 state_machine_.OnBeginImplFrameDeadlinePending(); | 477 state_machine_.OnBeginImplFrameDeadlinePending(); |
473 ProcessScheduledActions(); | 478 ProcessScheduledActions(); |
474 } | 479 } |
475 | 480 |
476 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 481 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 | 513 |
509 void Scheduler::ScheduleBeginImplFrameDeadline() { | 514 void Scheduler::ScheduleBeginImplFrameDeadline() { |
510 // The synchronous compositor does not post a deadline task. | 515 // The synchronous compositor does not post a deadline task. |
511 DCHECK(!settings_.using_synchronous_renderer_compositor); | 516 DCHECK(!settings_.using_synchronous_renderer_compositor); |
512 | 517 |
513 begin_impl_frame_deadline_task_.Cancel(); | 518 begin_impl_frame_deadline_task_.Cancel(); |
514 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 519 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
515 | 520 |
516 begin_impl_frame_deadline_mode_ = | 521 begin_impl_frame_deadline_mode_ = |
517 state_machine_.CurrentBeginImplFrameDeadlineMode(); | 522 state_machine_.CurrentBeginImplFrameDeadlineMode(); |
518 | |
519 base::TimeTicks deadline; | 523 base::TimeTicks deadline; |
520 switch (begin_impl_frame_deadline_mode_) { | 524 switch (begin_impl_frame_deadline_mode_) { |
521 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: | 525 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE: |
522 // No deadline. | 526 // No deadline. |
523 return; | 527 return; |
524 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: | 528 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: |
525 // We are ready to draw a new active tree immediately. | 529 // We are ready to draw a new active tree immediately. |
526 // We don't use Now() here because it's somewhat expensive to call. | 530 // We don't use Now() here because it's somewhat expensive to call. |
527 deadline = base::TimeTicks(); | 531 deadline = base::TimeTicks(); |
528 break; | 532 break; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
690 | 694 |
691 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() | 695 scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue() |
692 const { | 696 const { |
693 scoped_refptr<base::trace_event::TracedValue> state = | 697 scoped_refptr<base::trace_event::TracedValue> state = |
694 new base::trace_event::TracedValue(); | 698 new base::trace_event::TracedValue(); |
695 AsValueInto(state.get()); | 699 AsValueInto(state.get()); |
696 return state; | 700 return state; |
697 } | 701 } |
698 | 702 |
699 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { | 703 void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { |
704 base::TimeTicks now = Now(); | |
705 | |
700 state->BeginDictionary("state_machine"); | 706 state->BeginDictionary("state_machine"); |
701 state_machine_.AsValueInto(state); | 707 state_machine_.AsValueInto(state); |
702 state->EndDictionary(); | 708 state->EndDictionary(); |
703 | 709 |
704 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 | 710 // Only trace frame sources when explicitly enabled - http://crbug.com/420607 |
705 bool frame_tracing_enabled = false; | 711 bool frame_tracing_enabled = false; |
706 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 712 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
707 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), | 713 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), |
708 &frame_tracing_enabled); | 714 &frame_tracing_enabled); |
709 if (frame_tracing_enabled) { | 715 if (frame_tracing_enabled) { |
710 state->BeginDictionary("frame_source_"); | 716 state->BeginDictionary("frame_source_"); |
711 frame_source_->AsValueInto(state); | 717 frame_source_->AsValueInto(state); |
712 state->EndDictionary(); | 718 state->EndDictionary(); |
713 } | 719 } |
714 | 720 |
715 state->BeginDictionary("scheduler_state"); | 721 state->BeginDictionary("scheduler_state"); |
716 state->SetDouble("estimated_parent_draw_time_ms", | 722 state->SetDouble("estimated_parent_draw_time_ms", |
717 estimated_parent_draw_time_.InMillisecondsF()); | 723 estimated_parent_draw_time_.InMillisecondsF()); |
718 state->SetBoolean("last_set_needs_begin_frame_", | 724 state->SetBoolean("last_set_needs_begin_frame_", |
719 frame_source_->NeedsBeginFrames()); | 725 frame_source_->NeedsBeginFrames()); |
720 state->SetInteger("begin_retro_frame_args", | 726 state->SetInteger("begin_retro_frame_args", |
721 static_cast<int>(begin_retro_frame_args_.size())); | 727 static_cast<int>(begin_retro_frame_args_.size())); |
722 state->SetBoolean("begin_retro_frame_task", | 728 state->SetBoolean("begin_retro_frame_task", |
723 !begin_retro_frame_task_.IsCancelled()); | 729 !begin_retro_frame_task_.IsCancelled()); |
724 state->SetBoolean("begin_impl_frame_deadline_task", | 730 state->SetBoolean("begin_impl_frame_deadline_task", |
725 !begin_impl_frame_deadline_task_.IsCancelled()); | 731 !begin_impl_frame_deadline_task_.IsCancelled()); |
726 state->SetString("inside_action", | 732 state->SetString("inside_action", |
727 SchedulerStateMachine::ActionToString(inside_action_)); | 733 SchedulerStateMachine::ActionToString(inside_action_)); |
734 | |
728 state->BeginDictionary("begin_impl_frame_args"); | 735 state->BeginDictionary("begin_impl_frame_args"); |
729 begin_impl_frame_tracker_.AsValueInto(Now(), state); | 736 begin_impl_frame_tracker_.AsValueInto(now, state); |
730 state->EndDictionary(); | 737 state->EndDictionary(); |
738 | |
739 state->SetString("begin_impl_frame_deadline_mode_", | |
740 SchedulerStateMachine::BeginImplFrameDeadlineModeToString( | |
741 begin_impl_frame_deadline_mode_)); | |
731 state->EndDictionary(); | 742 state->EndDictionary(); |
732 | 743 |
733 state->BeginDictionary("compositor_timing_history"); | 744 state->BeginDictionary("compositor_timing_history"); |
734 compositor_timing_history_->AsValueInto(state); | 745 compositor_timing_history_->AsValueInto(state); |
735 state->EndDictionary(); | 746 state->EndDictionary(); |
736 } | 747 } |
737 | 748 |
738 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { | 749 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { |
739 compositor_timing_history_->SetRecordingEnabled( | 750 compositor_timing_history_->SetRecordingEnabled( |
740 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); | 751 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); |
741 } | 752 } |
742 | 753 |
743 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 754 bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const { |
744 BeginFrameArgs args = | 755 DCHECK(!settings_.using_synchronous_renderer_compositor); |
745 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); | |
746 | 756 |
757 if (!state_machine_.MainThreadIsInHighLatencyMode()) | |
758 return false; | |
759 | |
760 // When prioritizing impl thread latency, we currently put the | |
761 // main thread in a high latency mode. Don't try to fight it. | |
762 if (state_machine_.impl_latency_takes_priority()) | |
763 return false; | |
764 | |
765 return CanCommitAndActivateBeforeDeadline(args); | |
766 } | |
767 | |
768 bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const { | |
769 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
770 | |
771 // If we are swap throttled at the BeginFrame, that means the impl thread is | |
772 // very likely in a high latency mode. | |
773 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled(); | |
774 if (!impl_thread_is_likely_high_latency) | |
775 return false; | |
776 | |
777 // The deadline may be in the past if our draw time is too long. | |
778 bool frame_time_is_before_deadline = args.frame_time < args.deadline; | |
779 | |
780 // When prioritizing impl thread latency, the deadline doesn't wait | |
781 // for the main thread. | |
782 if (state_machine_.impl_latency_takes_priority()) | |
783 return frame_time_is_before_deadline; | |
784 | |
785 // If we only have impl-side updates, the deadline doesn't wait for | |
786 // the main thread. | |
787 if (state_machine_.OnlyImplSideUpdatesExpected()) | |
788 return frame_time_is_before_deadline; | |
789 | |
790 // If the active tree hasn't been drawn at the BeginFrame, it means | |
791 // the main thread is in a high latency mode but was still | |
792 // fast enough to give us a new active tree before this BeginFrame. | |
793 if (state_machine_.active_tree_needs_first_draw()) | |
brianderson
2015/07/09 05:44:06
Hmm. I think there are a lot of issues with this c
brianderson
2015/07/09 17:55:37
Removed.
| |
794 return frame_time_is_before_deadline; | |
795 | |
796 // If we get here, we know the main thread is in a low-latency mode relative | |
797 // to the impl thread. In this case, only try to also recover impl thread | |
798 // latency if both the main and impl threads can run serially before the | |
799 // deadline. | |
800 return CanCommitAndActivateBeforeDeadline(args); | |
801 } | |
802 | |
803 bool Scheduler::CanCommitAndActivateBeforeDeadline( | |
804 const BeginFrameArgs& args) const { | |
747 // Check if the main thread computation and commit can be finished before the | 805 // Check if the main thread computation and commit can be finished before the |
748 // impl thread's deadline. | 806 // impl thread's deadline. |
749 base::TimeTicks estimated_draw_time = | 807 base::TimeTicks estimated_draw_time = |
750 args.frame_time + | 808 args.frame_time + |
751 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + | 809 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + |
752 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + | 810 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + |
753 compositor_timing_history_->ActivateDurationEstimate(); | 811 compositor_timing_history_->ActivateDurationEstimate(); |
754 | 812 |
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; | 813 return estimated_draw_time < args.deadline; |
762 } | 814 } |
763 | 815 |
764 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 816 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
765 return (state_machine_.commit_state() == | 817 return (state_machine_.commit_state() == |
766 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 818 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
767 state_machine_.commit_state() == | 819 state_machine_.commit_state() == |
768 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 820 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
769 } | 821 } |
770 | 822 |
771 } // namespace cc | 823 } // namespace cc |
OLD | NEW |