| 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 |