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