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