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 #include "base/auto_reset.h" | 8 #include "base/auto_reset.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/debug/trace_event_argument.h" |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
12 #include "cc/debug/devtools_instrumentation.h" | 13 #include "cc/debug/devtools_instrumentation.h" |
13 #include "cc/debug/traced_value.h" | 14 #include "cc/debug/traced_value.h" |
14 #include "cc/scheduler/delay_based_time_source.h" | 15 #include "cc/scheduler/delay_based_time_source.h" |
15 #include "ui/gfx/frame_time.h" | 16 #include "ui/gfx/frame_time.h" |
16 | 17 |
17 namespace cc { | 18 namespace cc { |
18 | 19 |
19 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( | 20 Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 bool Scheduler::SyntheticBeginFrameSource::IsActive() const { | 55 bool Scheduler::SyntheticBeginFrameSource::IsActive() const { |
55 return time_source_->Active(); | 56 return time_source_->Active(); |
56 } | 57 } |
57 | 58 |
58 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() { | 59 void Scheduler::SyntheticBeginFrameSource::OnTimerTick() { |
59 BeginFrameArgs begin_frame_args( | 60 BeginFrameArgs begin_frame_args( |
60 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); | 61 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); |
61 scheduler_->BeginFrame(begin_frame_args); | 62 scheduler_->BeginFrame(begin_frame_args); |
62 } | 63 } |
63 | 64 |
64 scoped_ptr<base::Value> Scheduler::SyntheticBeginFrameSource::AsValue() const { | 65 void Scheduler::SyntheticBeginFrameSource::AsValueInto( |
65 return time_source_->AsValue(); | 66 base::debug::TracedValue* state) const { |
| 67 time_source_->AsValueInto(state); |
66 } | 68 } |
67 | 69 |
68 BeginFrameArgs | 70 BeginFrameArgs |
69 Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs( | 71 Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs( |
70 base::TimeTicks frame_time) { | 72 base::TimeTicks frame_time) { |
71 base::TimeTicks deadline = time_source_->NextTickTime(); | 73 base::TimeTicks deadline = time_source_->NextTickTime(); |
72 return BeginFrameArgs::Create( | 74 return BeginFrameArgs::Create( |
73 frame_time, deadline, scheduler_->VSyncInterval()); | 75 frame_time, deadline, scheduler_->VSyncInterval()); |
74 } | 76 } |
75 | 77 |
(...skipping 10 matching lines...) Expand all Loading... |
86 last_set_needs_begin_frame_(false), | 88 last_set_needs_begin_frame_(false), |
87 begin_unthrottled_frame_posted_(false), | 89 begin_unthrottled_frame_posted_(false), |
88 begin_retro_frame_posted_(false), | 90 begin_retro_frame_posted_(false), |
89 state_machine_(scheduler_settings), | 91 state_machine_(scheduler_settings), |
90 inside_process_scheduled_actions_(false), | 92 inside_process_scheduled_actions_(false), |
91 inside_action_(SchedulerStateMachine::ACTION_NONE), | 93 inside_action_(SchedulerStateMachine::ACTION_NONE), |
92 weak_factory_(this) { | 94 weak_factory_(this) { |
93 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 95 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
94 "Scheduler::Scheduler", | 96 "Scheduler::Scheduler", |
95 "settings", | 97 "settings", |
96 ToTrace(settings_)); | 98 settings_.AsValue()); |
97 DCHECK(client_); | 99 DCHECK(client_); |
98 DCHECK(!state_machine_.BeginFrameNeeded()); | 100 DCHECK(!state_machine_.BeginFrameNeeded()); |
99 if (settings_.main_frame_before_activation_enabled) { | 101 if (settings_.main_frame_before_activation_enabled) { |
100 DCHECK(settings_.main_frame_before_draw_enabled); | 102 DCHECK(settings_.main_frame_before_draw_enabled); |
101 } | 103 } |
102 | 104 |
103 begin_retro_frame_closure_ = | 105 begin_retro_frame_closure_ = |
104 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 106 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
105 begin_unthrottled_frame_closure_ = | 107 begin_unthrottled_frame_closure_ = |
106 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | 108 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 } else { | 394 } else { |
393 advance_commit_state_task_.Cancel(); | 395 advance_commit_state_task_.Cancel(); |
394 } | 396 } |
395 } | 397 } |
396 | 398 |
397 // BeginFrame is the mechanism that tells us that now is a good time to start | 399 // BeginFrame is the mechanism that tells us that now is a good time to start |
398 // making a frame. Usually this means that user input for the frame is complete. | 400 // making a frame. Usually this means that user input for the frame is complete. |
399 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 401 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
400 // a BeginRetroFrame. | 402 // a BeginRetroFrame. |
401 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 403 void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
402 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args)); | 404 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); |
403 DCHECK(settings_.throttle_frame_production); | 405 DCHECK(settings_.throttle_frame_production); |
404 | 406 |
405 BeginFrameArgs adjusted_args(args); | 407 BeginFrameArgs adjusted_args(args); |
406 adjusted_args.deadline -= EstimatedParentDrawTime(); | 408 adjusted_args.deadline -= EstimatedParentDrawTime(); |
407 | 409 |
408 bool should_defer_begin_frame; | 410 bool should_defer_begin_frame; |
409 if (settings_.using_synchronous_renderer_compositor) { | 411 if (settings_.using_synchronous_renderer_compositor) { |
410 should_defer_begin_frame = false; | 412 should_defer_begin_frame = false; |
411 } else { | 413 } else { |
412 should_defer_begin_frame = | 414 should_defer_begin_frame = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 return; | 491 return; |
490 | 492 |
491 begin_retro_frame_posted_ = true; | 493 begin_retro_frame_posted_ = true; |
492 impl_task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); | 494 impl_task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); |
493 } | 495 } |
494 | 496 |
495 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 497 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
496 // for a BeginMainFrame+activation to complete before it times out and draws | 498 // for a BeginMainFrame+activation to complete before it times out and draws |
497 // any asynchronous animation and scroll/pinch updates. | 499 // any asynchronous animation and scroll/pinch updates. |
498 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 500 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
499 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", ToTrace(args)); | 501 TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue()); |
500 DCHECK(state_machine_.begin_impl_frame_state() == | 502 DCHECK(state_machine_.begin_impl_frame_state() == |
501 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 503 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
502 DCHECK(state_machine_.HasInitializedOutputSurface()); | 504 DCHECK(state_machine_.HasInitializedOutputSurface()); |
503 | 505 |
504 advance_commit_state_task_.Cancel(); | 506 advance_commit_state_task_.Cancel(); |
505 | 507 |
506 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 508 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
507 begin_impl_frame_args_ = args; | 509 begin_impl_frame_args_ = args; |
508 begin_impl_frame_args_.deadline -= draw_duration_estimate; | 510 begin_impl_frame_args_.deadline -= draw_duration_estimate; |
509 | 511 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 return; | 621 return; |
620 | 622 |
621 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 623 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
622 | 624 |
623 SchedulerStateMachine::Action action; | 625 SchedulerStateMachine::Action action; |
624 do { | 626 do { |
625 action = state_machine_.NextAction(); | 627 action = state_machine_.NextAction(); |
626 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 628 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
627 "SchedulerStateMachine", | 629 "SchedulerStateMachine", |
628 "state", | 630 "state", |
629 ToTrace(this)); | 631 AsValue()); |
630 state_machine_.UpdateState(action); | 632 state_machine_.UpdateState(action); |
631 base::AutoReset<SchedulerStateMachine::Action> | 633 base::AutoReset<SchedulerStateMachine::Action> |
632 mark_inside_action(&inside_action_, action); | 634 mark_inside_action(&inside_action_, action); |
633 switch (action) { | 635 switch (action) { |
634 case SchedulerStateMachine::ACTION_NONE: | 636 case SchedulerStateMachine::ACTION_NONE: |
635 break; | 637 break; |
636 case SchedulerStateMachine::ACTION_ANIMATE: | 638 case SchedulerStateMachine::ACTION_ANIMATE: |
637 client_->ScheduledActionAnimate(); | 639 client_->ScheduledActionAnimate(); |
638 break; | 640 break; |
639 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: | 641 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | 675 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { |
674 DCHECK(!settings_.using_synchronous_renderer_compositor); | 676 DCHECK(!settings_.using_synchronous_renderer_compositor); |
675 ScheduleBeginImplFrameDeadline(base::TimeTicks()); | 677 ScheduleBeginImplFrameDeadline(base::TimeTicks()); |
676 } | 678 } |
677 } | 679 } |
678 | 680 |
679 bool Scheduler::WillDrawIfNeeded() const { | 681 bool Scheduler::WillDrawIfNeeded() const { |
680 return !state_machine_.PendingDrawsShouldBeAborted(); | 682 return !state_machine_.PendingDrawsShouldBeAborted(); |
681 } | 683 } |
682 | 684 |
683 scoped_ptr<base::Value> Scheduler::AsValue() const { | 685 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() |
684 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | 686 const { |
685 state->Set("state_machine", state_machine_.AsValue().release()); | 687 scoped_refptr<base::debug::TracedValue> state = |
686 if (synthetic_begin_frame_source_) | 688 new base::debug::TracedValue(); |
687 state->Set("synthetic_begin_frame_source_", | 689 state->BeginDictionary("state_machine"); |
688 synthetic_begin_frame_source_->AsValue().release()); | 690 state_machine_.AsValueInto(state); |
| 691 state->EndDictionary(); |
| 692 if (synthetic_begin_frame_source_) { |
| 693 state->BeginDictionary("synthetic_begin_frame_source_"); |
| 694 synthetic_begin_frame_source_->AsValueInto(state); |
| 695 state->EndDictionary(); |
| 696 } |
689 | 697 |
690 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); | 698 state->BeginDictionary("scheduler_state"); |
691 scheduler_state->SetDouble( | 699 state->SetDouble( |
692 "time_until_anticipated_draw_time_ms", | 700 "time_until_anticipated_draw_time_ms", |
693 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); | 701 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); |
694 scheduler_state->SetDouble("vsync_interval_ms", | 702 state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF()); |
695 vsync_interval_.InMillisecondsF()); | 703 state->SetDouble("estimated_parent_draw_time_ms", |
696 scheduler_state->SetDouble("estimated_parent_draw_time_ms", | 704 estimated_parent_draw_time_.InMillisecondsF()); |
697 estimated_parent_draw_time_.InMillisecondsF()); | 705 state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_); |
698 scheduler_state->SetBoolean("last_set_needs_begin_frame_", | 706 state->SetBoolean("begin_unthrottled_frame_posted_", |
699 last_set_needs_begin_frame_); | 707 begin_unthrottled_frame_posted_); |
700 scheduler_state->SetBoolean("begin_unthrottled_frame_posted_", | 708 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); |
701 begin_unthrottled_frame_posted_); | 709 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); |
702 scheduler_state->SetBoolean("begin_retro_frame_posted_", | 710 state->SetBoolean("begin_impl_frame_deadline_task_", |
703 begin_retro_frame_posted_); | 711 !begin_impl_frame_deadline_task_.IsCancelled()); |
704 scheduler_state->SetInteger("begin_retro_frame_args_", | 712 state->SetBoolean("poll_for_draw_triggers_task_", |
705 begin_retro_frame_args_.size()); | 713 !poll_for_draw_triggers_task_.IsCancelled()); |
706 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", | 714 state->SetBoolean("advance_commit_state_task_", |
707 !begin_impl_frame_deadline_task_.IsCancelled()); | 715 !advance_commit_state_task_.IsCancelled()); |
708 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", | 716 state->BeginDictionary("begin_impl_frame_args"); |
709 !poll_for_draw_triggers_task_.IsCancelled()); | 717 begin_impl_frame_args_.AsValueInto(state); |
710 scheduler_state->SetBoolean("advance_commit_state_task_", | 718 state->EndDictionary(); |
711 !advance_commit_state_task_.IsCancelled()); | |
712 scheduler_state->Set("begin_impl_frame_args", | |
713 begin_impl_frame_args_.AsValue().release()); | |
714 | 719 |
715 state->Set("scheduler_state", scheduler_state.release()); | 720 state->EndDictionary(); |
716 | 721 |
717 scoped_ptr<base::DictionaryValue> client_state(new base::DictionaryValue); | 722 state->BeginDictionary("client_state"); |
718 client_state->SetDouble("draw_duration_estimate_ms", | 723 state->SetDouble("draw_duration_estimate_ms", |
719 client_->DrawDurationEstimate().InMillisecondsF()); | 724 client_->DrawDurationEstimate().InMillisecondsF()); |
720 client_state->SetDouble( | 725 state->SetDouble( |
721 "begin_main_frame_to_commit_duration_estimate_ms", | 726 "begin_main_frame_to_commit_duration_estimate_ms", |
722 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); | 727 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); |
723 client_state->SetDouble( | 728 state->SetDouble( |
724 "commit_to_activate_duration_estimate_ms", | 729 "commit_to_activate_duration_estimate_ms", |
725 client_->CommitToActivateDurationEstimate().InMillisecondsF()); | 730 client_->CommitToActivateDurationEstimate().InMillisecondsF()); |
726 state->Set("client_state", client_state.release()); | 731 state->EndDictionary(); |
727 return state.PassAs<base::Value>(); | 732 return state; |
728 } | 733 } |
729 | 734 |
730 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 735 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
731 // Check if the main thread computation and commit can be finished before the | 736 // Check if the main thread computation and commit can be finished before the |
732 // impl thread's deadline. | 737 // impl thread's deadline. |
733 base::TimeTicks estimated_draw_time = | 738 base::TimeTicks estimated_draw_time = |
734 begin_impl_frame_args_.frame_time + | 739 begin_impl_frame_args_.frame_time + |
735 client_->BeginMainFrameToCommitDurationEstimate() + | 740 client_->BeginMainFrameToCommitDurationEstimate() + |
736 client_->CommitToActivateDurationEstimate(); | 741 client_->CommitToActivateDurationEstimate(); |
737 | 742 |
738 TRACE_EVENT2( | 743 TRACE_EVENT2( |
739 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 744 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
740 "CanCommitAndActivateBeforeDeadline", | 745 "CanCommitAndActivateBeforeDeadline", |
741 "time_left_after_drawing_ms", | 746 "time_left_after_drawing_ms", |
742 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), | 747 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), |
743 "state", | 748 "state", |
744 ToTrace(this)); | 749 AsValue()); |
745 | 750 |
746 return estimated_draw_time < begin_impl_frame_args_.deadline; | 751 return estimated_draw_time < begin_impl_frame_args_.deadline; |
747 } | 752 } |
748 | 753 |
749 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 754 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
750 return (state_machine_.commit_state() == | 755 return (state_machine_.commit_state() == |
751 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 756 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
752 state_machine_.commit_state() == | 757 state_machine_.commit_state() == |
753 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 758 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
754 } | 759 } |
755 | 760 |
756 } // namespace cc | 761 } // namespace cc |
OLD | NEW |