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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 return; | 463 return; |
464 | 464 |
465 // Discard expired BeginRetroFrames | 465 // Discard expired BeginRetroFrames |
466 // Today, we should always end up with at most one un-expired BeginRetroFrame | 466 // Today, we should always end up with at most one un-expired BeginRetroFrame |
467 // because deadlines will not be greater than the next frame time. We don't | 467 // because deadlines will not be greater than the next frame time. We don't |
468 // DCHECK though because some systems don't always have monotonic timestamps. | 468 // DCHECK though because some systems don't always have monotonic timestamps. |
469 // TODO(brianderson): In the future, long deadlines could result in us not | 469 // TODO(brianderson): In the future, long deadlines could result in us not |
470 // draining the queue if we don't catch up. If we consistently can't catch | 470 // draining the queue if we don't catch up. If we consistently can't catch |
471 // up, our fallback should be to lower our frame rate. | 471 // up, our fallback should be to lower our frame rate. |
472 base::TimeTicks now = Now(); | 472 base::TimeTicks now = Now(); |
473 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 473 |
474 while (!begin_retro_frame_args_.empty()) { | 474 while (!begin_retro_frame_args_.empty()) { |
475 base::TimeTicks adjusted_deadline = AdjustedBeginImplFrameDeadline( | 475 const BeginFrameArgs& args = begin_retro_frame_args_.front(); |
476 begin_retro_frame_args_.front(), draw_duration_estimate); | 476 base::TimeTicks expiration_time = args.frame_time + args.interval; |
477 if (now <= adjusted_deadline) | 477 if (now <= expiration_time) |
478 break; | 478 break; |
479 | 479 TRACE_EVENT_INSTANT2( |
480 TRACE_EVENT_INSTANT2("cc", | 480 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, |
481 "Scheduler::BeginRetroFrame discarding", | 481 "expiration_time - now", (expiration_time - now).InMillisecondsF(), |
482 TRACE_EVENT_SCOPE_THREAD, | 482 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); |
483 "deadline - now", | |
484 (adjusted_deadline - now).InMicroseconds(), | |
485 "BeginFrameArgs", | |
486 begin_retro_frame_args_.front().AsValue()); | |
487 begin_retro_frame_args_.pop_front(); | 483 begin_retro_frame_args_.pop_front(); |
488 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 484 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
489 } | 485 } |
490 | 486 |
491 if (begin_retro_frame_args_.empty()) { | 487 if (begin_retro_frame_args_.empty()) { |
492 TRACE_EVENT_INSTANT0("cc", | 488 TRACE_EVENT_INSTANT0("cc", |
493 "Scheduler::BeginRetroFrames all expired", | 489 "Scheduler::BeginRetroFrames all expired", |
494 TRACE_EVENT_SCOPE_THREAD); | 490 TRACE_EVENT_SCOPE_THREAD); |
495 } else { | 491 } else { |
496 BeginFrameArgs front = begin_retro_frame_args_.front(); | 492 BeginFrameArgs front = begin_retro_frame_args_.front(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 553 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
558 } | 554 } |
559 | 555 |
560 client_->WillBeginImplFrame(begin_impl_frame_args_); | 556 client_->WillBeginImplFrame(begin_impl_frame_args_); |
561 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); | 557 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); |
562 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 558 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
563 | 559 |
564 ProcessScheduledActions(); | 560 ProcessScheduledActions(); |
565 | 561 |
566 state_machine_.OnBeginImplFrameDeadlinePending(); | 562 state_machine_.OnBeginImplFrameDeadlinePending(); |
567 ScheduleBeginImplFrameDeadline( | 563 |
568 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | 564 if (settings_.using_synchronous_renderer_compositor) { |
| 565 // The synchronous renderer compositor has to make its GL calls |
| 566 // within this call. |
| 567 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks |
| 568 // so the synchronous renderer compositor can take advantage of splitting |
| 569 // up the BeginImplFrame and deadline as well. |
| 570 OnBeginImplFrameDeadline(); |
| 571 } else { |
| 572 ScheduleBeginImplFrameDeadline( |
| 573 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); |
| 574 } |
569 } | 575 } |
570 | 576 |
571 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( | 577 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( |
572 const BeginFrameArgs& args, | 578 const BeginFrameArgs& args, |
573 base::TimeDelta draw_duration_estimate) const { | 579 base::TimeDelta draw_duration_estimate) const { |
574 if (settings_.using_synchronous_renderer_compositor) { | 580 // The synchronous compositor does not post a deadline task. |
575 // The synchronous compositor needs to draw right away. | 581 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. |
576 return base::TimeTicks(); | 584 return base::TimeTicks(); |
577 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | 585 } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { |
578 // We are ready to draw a new active tree immediately. | 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. |
579 return base::TimeTicks(); | 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; |
580 } else if (state_machine_.needs_redraw()) { | 595 } else if (state_machine_.needs_redraw()) { |
581 // We have an animation or fast input path on the impl thread that wants | 596 // We have an animation or fast input path on the impl thread that wants |
582 // to draw, so don't wait too long for a new active tree. | 597 // to draw, so don't wait too long for a new active tree. |
583 return args.deadline - draw_duration_estimate; | 598 return args.deadline - draw_duration_estimate; |
584 } else { | 599 } else { |
585 // The impl thread doesn't have anything it wants to draw and we are just | 600 // The impl thread doesn't have anything it wants to draw and we are just |
586 // waiting for a new active tree, so post the deadline for the next | 601 // waiting for a new active tree, so post the deadline for the next |
587 // expected BeginImplFrame start. This allows us to draw immediately when | 602 // expected BeginImplFrame start. This allows us to draw immediately when |
588 // there is a new active tree, instead of waiting for the next | 603 // there is a new active tree, instead of waiting for the next |
589 // BeginImplFrame. | 604 // BeginImplFrame. |
590 // TODO(brianderson): Handle long deadlines (that are past the next frame's | 605 // TODO(brianderson): Handle long deadlines (that are past the next frame's |
591 // frame time) properly instead of using this hack. | 606 // frame time) properly instead of using this hack. |
592 return args.frame_time + args.interval; | 607 return args.frame_time + args.interval; |
593 } | 608 } |
594 } | 609 } |
595 | 610 |
596 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | 611 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { |
597 TRACE_EVENT1( | 612 TRACE_EVENT1( |
598 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); | 613 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); |
599 if (settings_.using_synchronous_renderer_compositor) { | |
600 // The synchronous renderer compositor has to make its GL calls | |
601 // within this call. | |
602 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
603 // so the sychronous renderer compositor can take advantage of splitting | |
604 // up the BeginImplFrame and deadline as well. | |
605 OnBeginImplFrameDeadline(); | |
606 return; | |
607 } | |
608 begin_impl_frame_deadline_task_.Cancel(); | 614 begin_impl_frame_deadline_task_.Cancel(); |
609 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | 615 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
610 | 616 |
611 base::TimeDelta delta = deadline - Now(); | 617 base::TimeDelta delta = deadline - Now(); |
612 if (delta <= base::TimeDelta()) | 618 if (delta <= base::TimeDelta()) |
613 delta = base::TimeDelta(); | 619 delta = base::TimeDelta(); |
614 task_runner_->PostDelayedTask( | 620 task_runner_->PostDelayedTask( |
615 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 621 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
616 } | 622 } |
617 | 623 |
618 void Scheduler::OnBeginImplFrameDeadline() { | 624 void Scheduler::OnBeginImplFrameDeadline() { |
619 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); | 625 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); |
620 begin_impl_frame_deadline_task_.Cancel(); | 626 begin_impl_frame_deadline_task_.Cancel(); |
621 | |
622 // We split the deadline actions up into two phases so the state machine | 627 // We split the deadline actions up into two phases so the state machine |
623 // has a chance to trigger actions that should occur durring and after | 628 // has a chance to trigger actions that should occur durring and after |
624 // the deadline separately. For example: | 629 // the deadline separately. For example: |
625 // * Sending the BeginMainFrame will not occur after the deadline in | 630 // * Sending the BeginMainFrame will not occur after the deadline in |
626 // order to wait for more user-input before starting the next commit. | 631 // order to wait for more user-input before starting the next commit. |
627 // * Creating a new OuputSurface will not occur during the deadline in | 632 // * Creating a new OuputSurface will not occur during the deadline in |
628 // order to allow the state machine to "settle" first. | 633 // order to allow the state machine to "settle" first. |
629 state_machine_.OnBeginImplFrameDeadline(); | 634 state_machine_.OnBeginImplFrameDeadline(); |
630 ProcessScheduledActions(); | 635 ProcessScheduledActions(); |
631 state_machine_.OnBeginImplFrameIdle(); | 636 state_machine_.OnBeginImplFrameIdle(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 } | 803 } |
799 | 804 |
800 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 805 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
801 return (state_machine_.commit_state() == | 806 return (state_machine_.commit_state() == |
802 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 807 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
803 state_machine_.commit_state() == | 808 state_machine_.commit_state() == |
804 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 809 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
805 } | 810 } |
806 | 811 |
807 } // namespace cc | 812 } // namespace cc |
OLD | NEW |