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/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 main_thread_is_in_high_latency_mode); | 536 main_thread_is_in_high_latency_mode); |
537 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 537 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
538 "MainThreadLatency", | 538 "MainThreadLatency", |
539 main_thread_is_in_high_latency_mode); | 539 main_thread_is_in_high_latency_mode); |
540 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 540 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
541 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 541 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
542 DCHECK(state_machine_.HasInitializedOutputSurface()); | 542 DCHECK(state_machine_.HasInitializedOutputSurface()); |
543 | 543 |
544 advance_commit_state_task_.Cancel(); | 544 advance_commit_state_task_.Cancel(); |
545 | 545 |
546 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | |
547 begin_impl_frame_args_ = args; | 546 begin_impl_frame_args_ = args; |
548 begin_impl_frame_args_.deadline -= draw_duration_estimate; | 547 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); |
549 | 548 |
550 if (!state_machine_.impl_latency_takes_priority() && | 549 if (!state_machine_.impl_latency_takes_priority() && |
551 main_thread_is_in_high_latency_mode && | 550 main_thread_is_in_high_latency_mode && |
552 CanCommitAndActivateBeforeDeadline()) { | 551 CanCommitAndActivateBeforeDeadline()) { |
553 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 552 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
554 } | 553 } |
555 | 554 |
556 client_->WillBeginImplFrame(begin_impl_frame_args_); | 555 client_->WillBeginImplFrame(begin_impl_frame_args_); |
557 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); | 556 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); |
558 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 557 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
559 | 558 |
560 ProcessScheduledActions(); | 559 ProcessScheduledActions(); |
561 | 560 |
562 state_machine_.OnBeginImplFrameDeadlinePending(); | 561 state_machine_.OnBeginImplFrameDeadlinePending(); |
563 | 562 |
564 if (settings_.using_synchronous_renderer_compositor) { | 563 if (settings_.using_synchronous_renderer_compositor) { |
565 // The synchronous renderer compositor has to make its GL calls | 564 // The synchronous renderer compositor has to make its GL calls |
566 // within this call. | 565 // within this call. |
567 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | 566 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks |
568 // so the synchronous renderer compositor can take advantage of splitting | 567 // so the synchronous renderer compositor can take advantage of splitting |
569 // up the BeginImplFrame and deadline as well. | 568 // up the BeginImplFrame and deadline as well. |
570 OnBeginImplFrameDeadline(); | 569 OnBeginImplFrameDeadline(); |
571 } else { | 570 } else { |
572 ScheduleBeginImplFrameDeadline( | 571 ScheduleBeginImplFrameDeadline(); |
573 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | |
574 } | 572 } |
575 } | 573 } |
576 | 574 |
577 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( | 575 void Scheduler::ScheduleBeginImplFrameDeadline() { |
578 const BeginFrameArgs& args, | |
579 base::TimeDelta draw_duration_estimate) const { | |
580 // The synchronous compositor does not post a deadline task. | 576 // The synchronous compositor does not post a deadline task. |
581 DCHECK(!settings_.using_synchronous_renderer_compositor); | 577 DCHECK(!settings_.using_synchronous_renderer_compositor); |
582 if (settings_.main_thread_should_always_be_low_latency) { | |
583 // In main thread low latency mode, always start deadline early. | |
584 return base::TimeTicks(); | |
585 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | |
586 // We are ready to draw a new active tree immediately. | |
587 // We don't use Now() here because it's somewhat expensive to call. | |
588 return base::TimeTicks(); | |
589 } else if (settings_.main_thread_should_always_be_low_latency) { | |
590 // Post long deadline to keep advancing during idle period. After activation | |
591 // we will be able to trigger deadline early. | |
592 // TODO(weiliangc): Don't post deadline once input is deferred with | |
593 // BeginRetroFrames. | |
594 return args.frame_time + args.interval; | |
595 } else if (state_machine_.needs_redraw()) { | |
596 // We have an animation or fast input path on the impl thread that wants | |
597 // to draw, so don't wait too long for a new active tree. | |
598 return args.deadline - draw_duration_estimate; | |
599 } else { | |
600 // The impl thread doesn't have anything it wants to draw and we are just | |
601 // waiting for a new active tree, so post the deadline for the next | |
602 // expected BeginImplFrame start. This allows us to draw immediately when | |
603 // there is a new active tree, instead of waiting for the next | |
604 // BeginImplFrame. | |
605 // TODO(brianderson): Handle long deadlines (that are past the next frame's | |
606 // frame time) properly instead of using this hack. | |
607 return args.frame_time + args.interval; | |
608 } | |
609 } | |
610 | 578 |
611 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | |
612 TRACE_EVENT1( | |
613 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); | |
614 begin_impl_frame_deadline_task_.Cancel(); | 579 begin_impl_frame_deadline_task_.Cancel(); |
615 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 580 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
616 | 581 |
| 582 begin_impl_frame_deadline_mode_ = |
| 583 state_machine_.CurrentBeginImplFrameDeadlineMode(); |
| 584 |
| 585 base::TimeTicks deadline; |
| 586 switch (begin_impl_frame_deadline_mode_) { |
| 587 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE: |
| 588 // We are ready to draw a new active tree immediately. |
| 589 // We don't use Now() here because it's somewhat expensive to call. |
| 590 deadline = base::TimeTicks(); |
| 591 break; |
| 592 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR: |
| 593 // We are animating on the impl thread but we can wait for some time. |
| 594 deadline = begin_impl_frame_args_.deadline; |
| 595 break; |
| 596 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE: |
| 597 // We are blocked for one reason or another and we should wait. |
| 598 // TODO(brianderson): Handle long deadlines (that are past the next |
| 599 // frame's frame time) properly instead of using this hack. |
| 600 deadline = |
| 601 begin_impl_frame_args_.frame_time + begin_impl_frame_args_.interval; |
| 602 break; |
| 603 } |
| 604 |
| 605 TRACE_EVENT1( |
| 606 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); |
| 607 |
617 base::TimeDelta delta = deadline - Now(); | 608 base::TimeDelta delta = deadline - Now(); |
618 if (delta <= base::TimeDelta()) | 609 if (delta <= base::TimeDelta()) |
619 delta = base::TimeDelta(); | 610 delta = base::TimeDelta(); |
620 task_runner_->PostDelayedTask( | 611 task_runner_->PostDelayedTask( |
621 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 612 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
622 } | 613 } |
623 | 614 |
| 615 void Scheduler::RescheduleBeginImplFrameDeadlineIfNeeded() { |
| 616 if (settings_.using_synchronous_renderer_compositor) |
| 617 return; |
| 618 |
| 619 if (state_machine_.begin_impl_frame_state() != |
| 620 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
| 621 return; |
| 622 |
| 623 if (begin_impl_frame_deadline_mode_ != |
| 624 state_machine_.CurrentBeginImplFrameDeadlineMode()) |
| 625 ScheduleBeginImplFrameDeadline(); |
| 626 } |
| 627 |
624 void Scheduler::OnBeginImplFrameDeadline() { | 628 void Scheduler::OnBeginImplFrameDeadline() { |
625 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); | 629 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); |
626 begin_impl_frame_deadline_task_.Cancel(); | 630 begin_impl_frame_deadline_task_.Cancel(); |
627 // We split the deadline actions up into two phases so the state machine | 631 // We split the deadline actions up into two phases so the state machine |
628 // has a chance to trigger actions that should occur durring and after | 632 // has a chance to trigger actions that should occur durring and after |
629 // the deadline separately. For example: | 633 // the deadline separately. For example: |
630 // * Sending the BeginMainFrame will not occur after the deadline in | 634 // * Sending the BeginMainFrame will not occur after the deadline in |
631 // order to wait for more user-input before starting the next commit. | 635 // order to wait for more user-input before starting the next commit. |
632 // * Creating a new OuputSurface will not occur during the deadline in | 636 // * Creating a new OuputSurface will not occur during the deadline in |
633 // order to allow the state machine to "settle" first. | 637 // order to allow the state machine to "settle" first. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 break; | 713 break; |
710 case SchedulerStateMachine::ACTION_MANAGE_TILES: | 714 case SchedulerStateMachine::ACTION_MANAGE_TILES: |
711 client_->ScheduledActionManageTiles(); | 715 client_->ScheduledActionManageTiles(); |
712 break; | 716 break; |
713 } | 717 } |
714 } while (action != SchedulerStateMachine::ACTION_NONE); | 718 } while (action != SchedulerStateMachine::ACTION_NONE); |
715 | 719 |
716 SetupNextBeginFrameIfNeeded(); | 720 SetupNextBeginFrameIfNeeded(); |
717 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); | 721 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); |
718 | 722 |
719 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | 723 RescheduleBeginImplFrameDeadlineIfNeeded(); |
720 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
721 ScheduleBeginImplFrameDeadline(base::TimeTicks()); | |
722 } | |
723 } | 724 } |
724 | 725 |
725 bool Scheduler::WillDrawIfNeeded() const { | 726 bool Scheduler::WillDrawIfNeeded() const { |
726 return !state_machine_.PendingDrawsShouldBeAborted(); | 727 return !state_machine_.PendingDrawsShouldBeAborted(); |
727 } | 728 } |
728 | 729 |
729 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() | 730 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() |
730 const { | 731 const { |
731 scoped_refptr<base::debug::TracedValue> state = | 732 scoped_refptr<base::debug::TracedValue> state = |
732 new base::debug::TracedValue(); | 733 new base::debug::TracedValue(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 } | 804 } |
804 | 805 |
805 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 806 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
806 return (state_machine_.commit_state() == | 807 return (state_machine_.commit_state() == |
807 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 808 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
808 state_machine_.commit_state() == | 809 state_machine_.commit_state() == |
809 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 810 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
810 } | 811 } |
811 | 812 |
812 } // namespace cc | 813 } // namespace cc |
OLD | NEW |