Chromium Code Reviews| 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 |