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/logging.h" | 10 #include "base/logging.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } | 204 } |
205 } | 205 } |
206 | 206 |
207 void Scheduler::DidSwapBuffersComplete() { | 207 void Scheduler::DidSwapBuffersComplete() { |
208 DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString(); | 208 DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString(); |
209 compositor_timing_history_->DidSwapBuffersComplete(); | 209 compositor_timing_history_->DidSwapBuffersComplete(); |
210 state_machine_.DidSwapBuffersComplete(); | 210 state_machine_.DidSwapBuffersComplete(); |
211 ProcessScheduledActions(); | 211 ProcessScheduledActions(); |
212 } | 212 } |
213 | 213 |
214 void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) { | 214 void Scheduler::SetTreePrioritiesAndScrollState( |
215 state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority); | 215 TreePriority tree_priority, |
| 216 ScrollHandlerState scroll_handler_state) { |
| 217 state_machine_.SetTreePrioritiesAndScrollState(tree_priority, |
| 218 scroll_handler_state); |
216 ProcessScheduledActions(); | 219 ProcessScheduledActions(); |
217 } | 220 } |
218 | 221 |
219 void Scheduler::NotifyReadyToCommit() { | 222 void Scheduler::NotifyReadyToCommit() { |
220 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit"); | 223 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit"); |
221 state_machine_.NotifyReadyToCommit(); | 224 state_machine_.NotifyReadyToCommit(); |
222 ProcessScheduledActions(); | 225 ProcessScheduledActions(); |
223 } | 226 } |
224 | 227 |
225 void Scheduler::DidCommit() { | 228 void Scheduler::DidCommit() { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); | 306 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); |
304 | 307 |
305 // Trace this begin frame time through the Chrome stack | 308 // Trace this begin frame time through the Chrome stack |
306 TRACE_EVENT_FLOW_BEGIN0( | 309 TRACE_EVENT_FLOW_BEGIN0( |
307 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", | 310 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", |
308 args.frame_time.ToInternalValue()); | 311 args.frame_time.ToInternalValue()); |
309 | 312 |
310 // TODO(brianderson): Adjust deadline in the DisplayScheduler. | 313 // TODO(brianderson): Adjust deadline in the DisplayScheduler. |
311 BeginFrameArgs adjusted_args(args); | 314 BeginFrameArgs adjusted_args(args); |
312 adjusted_args.deadline -= EstimatedParentDrawTime(); | 315 adjusted_args.deadline -= EstimatedParentDrawTime(); |
313 adjusted_args.on_critical_path = !ImplLatencyTakesPriority(); | |
314 | 316 |
315 // Deliver BeginFrames to children. | 317 // Deliver BeginFrames to children. |
316 // TODO(brianderson): Move this responsibility to the DisplayScheduler. | 318 // TODO(brianderson): Move this responsibility to the DisplayScheduler. |
317 if (state_machine_.children_need_begin_frames()) | 319 if (state_machine_.children_need_begin_frames()) |
318 client_->SendBeginFramesToChildren(adjusted_args); | 320 client_->SendBeginFramesToChildren(adjusted_args); |
319 | 321 |
320 if (settings_.using_synchronous_renderer_compositor) { | 322 if (settings_.using_synchronous_renderer_compositor) { |
321 BeginImplFrameSynchronous(adjusted_args); | 323 BeginImplFrameSynchronous(adjusted_args); |
322 return true; | 324 return true; |
323 } | 325 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 462 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
461 args.AsValue(), "main_thread_missed_last_deadline", | 463 args.AsValue(), "main_thread_missed_last_deadline", |
462 main_thread_is_in_high_latency_mode); | 464 main_thread_is_in_high_latency_mode); |
463 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 465 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
464 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 466 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
465 | 467 |
466 BeginFrameArgs adjusted_args = args; | 468 BeginFrameArgs adjusted_args = args; |
467 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); | 469 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); |
468 adjusted_args.deadline -= kDeadlineFudgeFactor; | 470 adjusted_args.deadline -= kDeadlineFudgeFactor; |
469 | 471 |
470 if (ShouldRecoverMainLatency(adjusted_args)) { | 472 base::TimeDelta bmf_start_to_activate = |
| 473 compositor_timing_history_ |
| 474 ->BeginMainFrameStartToCommitDurationEstimate() + |
| 475 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + |
| 476 compositor_timing_history_->ActivateDurationEstimate(); |
| 477 |
| 478 base::TimeDelta bmf_to_activate_estimate_if_critical = |
| 479 bmf_start_to_activate + |
| 480 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate(); |
| 481 |
| 482 bool can_activate_before_deadline_if_critical = |
| 483 CanBeginMainFrameAndActivateBeforeDeadline( |
| 484 adjusted_args, bmf_to_activate_estimate_if_critical); |
| 485 state_machine_.SetCriticalBeginMainFrameToActivateIsFast( |
| 486 can_activate_before_deadline_if_critical); |
| 487 |
| 488 // Update the BeginMainFrame args now that we know whether the main |
| 489 // thread will be on the critical path or not. |
| 490 begin_main_frame_args_ = adjusted_args; |
| 491 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); |
| 492 |
| 493 bool can_activate_before_deadline = can_activate_before_deadline_if_critical; |
| 494 if (!begin_main_frame_args_.on_critical_path) { |
| 495 base::TimeDelta bmf_to_activate_estimate = |
| 496 bmf_start_to_activate + |
| 497 compositor_timing_history_ |
| 498 ->BeginMainFrameQueueDurationNotCriticalEstimate(); |
| 499 |
| 500 can_activate_before_deadline = CanBeginMainFrameAndActivateBeforeDeadline( |
| 501 adjusted_args, bmf_to_activate_estimate); |
| 502 } |
| 503 |
| 504 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { |
471 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", | 505 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", |
472 TRACE_EVENT_SCOPE_THREAD); | 506 TRACE_EVENT_SCOPE_THREAD); |
473 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 507 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
474 } else if (ShouldRecoverImplLatency(adjusted_args)) { | 508 } else if (ShouldRecoverImplLatency(adjusted_args, |
| 509 can_activate_before_deadline)) { |
475 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", | 510 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", |
476 TRACE_EVENT_SCOPE_THREAD); | 511 TRACE_EVENT_SCOPE_THREAD); |
477 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 512 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
478 return; | 513 return; |
479 } | 514 } |
480 | 515 |
481 BeginImplFrame(adjusted_args); | 516 BeginImplFrame(adjusted_args); |
482 | 517 |
483 // The deadline will be scheduled in ProcessScheduledActions. | 518 // The deadline will be scheduled in ProcessScheduledActions. |
484 state_machine_.OnBeginImplFrameDeadlinePending(); | 519 state_machine_.OnBeginImplFrameDeadlinePending(); |
485 ProcessScheduledActions(); | 520 ProcessScheduledActions(); |
486 } | 521 } |
487 | 522 |
488 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 523 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
489 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 524 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
490 args.AsValue()); | 525 args.AsValue()); |
| 526 |
| 527 // The main thread currently can't commit before we draw with the |
| 528 // synchronous compositor, so never consider the BeginMainFrame fast. |
| 529 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); |
| 530 begin_main_frame_args_ = args; |
| 531 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); |
| 532 |
491 BeginImplFrame(args); | 533 BeginImplFrame(args); |
492 FinishImplFrame(); | 534 FinishImplFrame(); |
493 } | 535 } |
494 | 536 |
495 void Scheduler::FinishImplFrame() { | 537 void Scheduler::FinishImplFrame() { |
496 state_machine_.OnBeginImplFrameIdle(); | 538 state_machine_.OnBeginImplFrameIdle(); |
497 ProcessScheduledActions(); | 539 ProcessScheduledActions(); |
498 | 540 |
499 client_->DidFinishImplFrame(); | 541 client_->DidFinishImplFrame(); |
500 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 542 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
501 begin_impl_frame_tracker_.Finish(); | 543 begin_impl_frame_tracker_.Finish(); |
502 } | 544 } |
503 | 545 |
504 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 546 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
505 // for a BeginMainFrame+activation to complete before it times out and draws | 547 // for a BeginMainFrame+activation to complete before it times out and draws |
506 // any asynchronous animation and scroll/pinch updates. | 548 // any asynchronous animation and scroll/pinch updates. |
507 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 549 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
508 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 550 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
509 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 551 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
510 DCHECK(!BeginImplFrameDeadlinePending()); | 552 DCHECK(!BeginImplFrameDeadlinePending()); |
511 DCHECK(state_machine_.HasInitializedOutputSurface()); | 553 DCHECK(state_machine_.HasInitializedOutputSurface()); |
512 | 554 |
513 begin_impl_frame_tracker_.Start(args); | 555 begin_impl_frame_tracker_.Start(args); |
514 begin_main_frame_args_ = args; | |
515 state_machine_.OnBeginImplFrame(); | 556 state_machine_.OnBeginImplFrame(); |
516 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | 557 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); |
517 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); | 558 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); |
518 | 559 |
519 ProcessScheduledActions(); | 560 ProcessScheduledActions(); |
520 } | 561 } |
521 | 562 |
522 void Scheduler::ScheduleBeginImplFrameDeadline() { | 563 void Scheduler::ScheduleBeginImplFrameDeadline() { |
523 // The synchronous compositor does not post a deadline task. | 564 // The synchronous compositor does not post a deadline task. |
524 DCHECK(!settings_.using_synchronous_renderer_compositor); | 565 DCHECK(!settings_.using_synchronous_renderer_compositor); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 state->BeginDictionary("compositor_timing_history"); | 817 state->BeginDictionary("compositor_timing_history"); |
777 compositor_timing_history_->AsValueInto(state); | 818 compositor_timing_history_->AsValueInto(state); |
778 state->EndDictionary(); | 819 state->EndDictionary(); |
779 } | 820 } |
780 | 821 |
781 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { | 822 void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() { |
782 compositor_timing_history_->SetRecordingEnabled( | 823 compositor_timing_history_->SetRecordingEnabled( |
783 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); | 824 state_machine_.HasInitializedOutputSurface() && state_machine_.visible()); |
784 } | 825 } |
785 | 826 |
786 bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const { | 827 bool Scheduler::ShouldRecoverMainLatency( |
| 828 const BeginFrameArgs& args, |
| 829 bool can_activate_before_deadline) const { |
787 DCHECK(!settings_.using_synchronous_renderer_compositor); | 830 DCHECK(!settings_.using_synchronous_renderer_compositor); |
788 | 831 |
789 if (!state_machine_.main_thread_missed_last_deadline()) | 832 if (!state_machine_.main_thread_missed_last_deadline()) |
790 return false; | 833 return false; |
791 | 834 |
792 // When prioritizing impl thread latency, we currently put the | 835 // When prioritizing impl thread latency, we currently put the |
793 // main thread in a high latency mode. Don't try to fight it. | 836 // main thread in a high latency mode. Don't try to fight it. |
794 if (state_machine_.impl_latency_takes_priority()) | 837 if (state_machine_.ImplLatencyTakesPriority()) |
795 return false; | 838 return false; |
796 | 839 |
797 return CanCommitAndActivateBeforeDeadline(args); | 840 return can_activate_before_deadline; |
798 } | 841 } |
799 | 842 |
800 bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const { | 843 bool Scheduler::ShouldRecoverImplLatency( |
| 844 const BeginFrameArgs& args, |
| 845 bool can_activate_before_deadline) const { |
801 DCHECK(!settings_.using_synchronous_renderer_compositor); | 846 DCHECK(!settings_.using_synchronous_renderer_compositor); |
802 | 847 |
803 // Disable impl thread latency recovery when using the unthrottled | 848 // Disable impl thread latency recovery when using the unthrottled |
804 // begin frame source since we will always get a BeginFrame before | 849 // begin frame source since we will always get a BeginFrame before |
805 // the swap ack and our heuristics below will not work. | 850 // the swap ack and our heuristics below will not work. |
806 if (!throttle_frame_production_) | 851 if (!throttle_frame_production_) |
807 return false; | 852 return false; |
808 | 853 |
809 // If we are swap throttled at the BeginFrame, that means the impl thread is | 854 // If we are swap throttled at the BeginFrame, that means the impl thread is |
810 // very likely in a high latency mode. | 855 // very likely in a high latency mode. |
811 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled(); | 856 bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled(); |
812 if (!impl_thread_is_likely_high_latency) | 857 if (!impl_thread_is_likely_high_latency) |
813 return false; | 858 return false; |
814 | 859 |
815 // The deadline may be in the past if our draw time is too long. | 860 // The deadline may be in the past if our draw time is too long. |
816 bool can_draw_before_deadline = args.frame_time < args.deadline; | 861 bool can_draw_before_deadline = args.frame_time < args.deadline; |
817 | 862 |
818 // When prioritizing impl thread latency, the deadline doesn't wait | 863 // When prioritizing impl thread latency, the deadline doesn't wait |
819 // for the main thread. | 864 // for the main thread. |
820 if (state_machine_.impl_latency_takes_priority()) | 865 if (state_machine_.ImplLatencyTakesPriority()) |
821 return can_draw_before_deadline; | 866 return can_draw_before_deadline; |
822 | 867 |
823 // If we only have impl-side updates, the deadline doesn't wait for | 868 // If we only have impl-side updates, the deadline doesn't wait for |
824 // the main thread. | 869 // the main thread. |
825 if (state_machine_.OnlyImplSideUpdatesExpected()) | 870 if (state_machine_.OnlyImplSideUpdatesExpected()) |
826 return can_draw_before_deadline; | 871 return can_draw_before_deadline; |
827 | 872 |
828 // If we get here, we know the main thread is in a low-latency mode relative | 873 // If we get here, we know the main thread is in a low-latency mode relative |
829 // to the impl thread. In this case, only try to also recover impl thread | 874 // to the impl thread. In this case, only try to also recover impl thread |
830 // latency if both the main and impl threads can run serially before the | 875 // latency if both the main and impl threads can run serially before the |
831 // deadline. | 876 // deadline. |
832 return CanCommitAndActivateBeforeDeadline(args); | 877 return can_activate_before_deadline; |
833 } | 878 } |
834 | 879 |
835 bool Scheduler::CanCommitAndActivateBeforeDeadline( | 880 bool Scheduler::CanBeginMainFrameAndActivateBeforeDeadline( |
836 const BeginFrameArgs& args) const { | 881 const BeginFrameArgs& args, |
| 882 base::TimeDelta bmf_to_activate_estimate) const { |
837 // Check if the main thread computation and commit can be finished before the | 883 // Check if the main thread computation and commit can be finished before the |
838 // impl thread's deadline. | 884 // impl thread's deadline. |
839 base::TimeTicks estimated_draw_time = | 885 base::TimeTicks estimated_draw_time = |
840 args.frame_time + | 886 args.frame_time + bmf_to_activate_estimate; |
841 compositor_timing_history_->BeginMainFrameToCommitDurationEstimate() + | |
842 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + | |
843 compositor_timing_history_->ActivateDurationEstimate(); | |
844 | 887 |
845 return estimated_draw_time < args.deadline; | 888 return estimated_draw_time < args.deadline; |
846 } | 889 } |
847 | 890 |
848 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 891 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
849 return (state_machine_.begin_main_frame_state() == | 892 return (state_machine_.begin_main_frame_state() == |
850 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || | 893 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || |
851 state_machine_.begin_main_frame_state() == | 894 state_machine_.begin_main_frame_state() == |
852 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); | 895 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); |
853 } | 896 } |
854 | 897 |
855 } // namespace cc | 898 } // namespace cc |
OLD | NEW |