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