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