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_state_machine.h" | 5 #include "cc/scheduler/scheduler_state_machine.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 scroll_handler_state_( | 53 scroll_handler_state_( |
54 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER), | 54 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER), |
55 critical_begin_main_frame_to_activate_is_fast_(true), | 55 critical_begin_main_frame_to_activate_is_fast_(true), |
56 main_thread_missed_last_deadline_(false), | 56 main_thread_missed_last_deadline_(false), |
57 skip_next_begin_main_frame_to_reduce_latency_(false), | 57 skip_next_begin_main_frame_to_reduce_latency_(false), |
58 defer_commits_(false), | 58 defer_commits_(false), |
59 video_needs_begin_frames_(false), | 59 video_needs_begin_frames_(false), |
60 last_commit_had_no_updates_(false), | 60 last_commit_had_no_updates_(false), |
61 wait_for_ready_to_draw_(false), | 61 wait_for_ready_to_draw_(false), |
62 did_draw_in_last_frame_(false), | 62 did_draw_in_last_frame_(false), |
63 did_submit_in_last_frame_(false) {} | 63 did_submit_in_last_frame_(false), |
| 64 begin_frame_allows_latency_optimizations_(true) {} |
64 | 65 |
65 const char* SchedulerStateMachine::CompositorFrameSinkStateToString( | 66 const char* SchedulerStateMachine::CompositorFrameSinkStateToString( |
66 CompositorFrameSinkState state) { | 67 CompositorFrameSinkState state) { |
67 switch (state) { | 68 switch (state) { |
68 case COMPOSITOR_FRAME_SINK_NONE: | 69 case COMPOSITOR_FRAME_SINK_NONE: |
69 return "COMPOSITOR_FRAME_SINK_NONE"; | 70 return "COMPOSITOR_FRAME_SINK_NONE"; |
70 case COMPOSITOR_FRAME_SINK_ACTIVE: | 71 case COMPOSITOR_FRAME_SINK_ACTIVE: |
71 return "COMPOSITOR_FRAME_SINK_ACTIVE"; | 72 return "COMPOSITOR_FRAME_SINK_ACTIVE"; |
72 case COMPOSITOR_FRAME_SINK_CREATING: | 73 case COMPOSITOR_FRAME_SINK_CREATING: |
73 return "COMPOSITOR_FRAME_SINK_CREATING"; | 74 return "COMPOSITOR_FRAME_SINK_CREATING"; |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 if (wait_for_ready_to_draw_) { | 368 if (wait_for_ready_to_draw_) { |
368 DCHECK(settings_.commit_to_active_tree); | 369 DCHECK(settings_.commit_to_active_tree); |
369 return false; | 370 return false; |
370 } | 371 } |
371 | 372 |
372 // Browser compositor commit steals any resources submitted in draw. Therefore | 373 // Browser compositor commit steals any resources submitted in draw. Therefore |
373 // drawing while a commit is pending is wasteful. | 374 // drawing while a commit is pending is wasteful. |
374 if (settings_.commit_to_active_tree && CommitPending()) | 375 if (settings_.commit_to_active_tree && CommitPending()) |
375 return false; | 376 return false; |
376 | 377 |
377 // Only handle forced redraws due to timeouts on the regular deadline. | 378 // Only handle forced redraws due to timeouts on the regular deadline and |
378 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 379 // (temporarily) for |!begin_frame_allows_latency_optimizations_|. |
| 380 if (ShouldForceDraw()) |
379 return true; | 381 return true; |
380 | 382 |
381 return needs_redraw_; | 383 return needs_redraw_; |
382 } | 384 } |
383 | 385 |
| 386 bool SchedulerStateMachine::ShouldForceDraw() const { |
| 387 // Browser compositor doesn't support forced draws. |
| 388 if (settings_.commit_to_active_tree) |
| 389 return false; |
| 390 |
| 391 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
| 392 return true; |
| 393 |
| 394 // |!begin_frame_allows_latency_optimizations_| is typically used with long |
| 395 // deadlines, for which we depend on a timely acknowledgment of the BeginFrame |
| 396 // in the browser. Since we currently don't have a unified acknowledgment for |
| 397 // unsuccessful draws, we force a draw and wait for surface damage in the |
| 398 // browser's DisplayScheduler. |
| 399 // TODO(eseckler): Remove once we have unified BeginFrame acknowledgments. |
| 400 if (!begin_frame_allows_latency_optimizations_) |
| 401 return true; |
| 402 |
| 403 return false; |
| 404 } |
| 405 |
384 bool SchedulerStateMachine::ShouldActivatePendingTree() const { | 406 bool SchedulerStateMachine::ShouldActivatePendingTree() const { |
385 // There is nothing to activate. | 407 // There is nothing to activate. |
386 if (!has_pending_tree_) | 408 if (!has_pending_tree_) |
387 return false; | 409 return false; |
388 | 410 |
389 // We should not activate a second tree before drawing the first one. | 411 // We should not activate a second tree before drawing the first one. |
390 // Even if we need to force activation of the pending tree, we should abort | 412 // Even if we need to force activation of the pending tree, we should abort |
391 // drawing the active tree first. | 413 // drawing the active tree first. |
392 if (active_tree_needs_first_draw_) | 414 if (active_tree_needs_first_draw_) |
393 return false; | 415 return false; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 } | 569 } |
548 | 570 |
549 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { | 571 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
550 if (ShouldActivatePendingTree()) | 572 if (ShouldActivatePendingTree()) |
551 return ACTION_ACTIVATE_SYNC_TREE; | 573 return ACTION_ACTIVATE_SYNC_TREE; |
552 if (ShouldCommit()) | 574 if (ShouldCommit()) |
553 return ACTION_COMMIT; | 575 return ACTION_COMMIT; |
554 if (ShouldDraw()) { | 576 if (ShouldDraw()) { |
555 if (PendingDrawsShouldBeAborted()) | 577 if (PendingDrawsShouldBeAborted()) |
556 return ACTION_DRAW_ABORT; | 578 return ACTION_DRAW_ABORT; |
557 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 579 else if (ShouldForceDraw()) |
558 return ACTION_DRAW_FORCED; | 580 return ACTION_DRAW_FORCED; |
559 else | 581 else |
560 return ACTION_DRAW_IF_POSSIBLE; | 582 return ACTION_DRAW_IF_POSSIBLE; |
561 } | 583 } |
562 if (ShouldPrepareTiles()) | 584 if (ShouldPrepareTiles()) |
563 return ACTION_PREPARE_TILES; | 585 return ACTION_PREPARE_TILES; |
564 if (ShouldSendBeginMainFrame()) | 586 if (ShouldSendBeginMainFrame()) |
565 return ACTION_SEND_BEGIN_MAIN_FRAME; | 587 return ACTION_SEND_BEGIN_MAIN_FRAME; |
566 if (ShouldInvalidateCompositorFrameSink()) | 588 if (ShouldInvalidateCompositorFrameSink()) |
567 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; | 589 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 | 782 |
761 void SchedulerStateMachine::SetVideoNeedsBeginFrames( | 783 void SchedulerStateMachine::SetVideoNeedsBeginFrames( |
762 bool video_needs_begin_frames) { | 784 bool video_needs_begin_frames) { |
763 video_needs_begin_frames_ = video_needs_begin_frames; | 785 video_needs_begin_frames_ = video_needs_begin_frames; |
764 } | 786 } |
765 | 787 |
766 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { | 788 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { |
767 defer_commits_ = defer_commits; | 789 defer_commits_ = defer_commits; |
768 } | 790 } |
769 | 791 |
| 792 void SchedulerStateMachine::SetBeginFrameAllowsLatencyOptimizations( |
| 793 bool allow_latency_optimizations) { |
| 794 // In this mode, we ensure that we don't skip the BeginFrame/BeginMainFrame |
| 795 // and that we don't prioritize impl thread latency. Thus, we first give the |
| 796 // main thread a chance to produce updates, and only if it doesn't (or doesn't |
| 797 // respond in time for the deadline), we produce an impl frame. |
| 798 |
| 799 // |!allow_latency_optimizations| is often used in combination with long or |
| 800 // infinite BeginFrame deadlines. To respond timely, we rely on triggering the |
| 801 // BeginFrame deadline immediately if the main frame has no updates or as soon |
| 802 // as it was activated (see ShouldTriggerBeginImplFrameDeadlineImmediately()). |
| 803 |
| 804 begin_frame_allows_latency_optimizations_ = allow_latency_optimizations; |
| 805 } |
| 806 |
770 // These are the cases where we require a BeginFrame message to make progress | 807 // These are the cases where we require a BeginFrame message to make progress |
771 // on requested actions. | 808 // on requested actions. |
772 bool SchedulerStateMachine::BeginFrameRequiredForAction() const { | 809 bool SchedulerStateMachine::BeginFrameRequiredForAction() const { |
773 // The forced draw respects our normal draw scheduling, so we need to | 810 // The forced draw respects our normal draw scheduling, so we need to |
774 // request a BeginImplFrame for it. | 811 // request a BeginImplFrame for it. |
775 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 812 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
776 return true; | 813 return true; |
777 | 814 |
778 return needs_redraw_ || needs_one_begin_impl_frame_ || | 815 return needs_redraw_ || needs_one_begin_impl_frame_ || |
779 (needs_begin_main_frame_ && !defer_commits_); | 816 (needs_begin_main_frame_ && !defer_commits_); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 912 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
876 if (settings_.using_synchronous_renderer_compositor) { | 913 if (settings_.using_synchronous_renderer_compositor) { |
877 // No deadline for synchronous compositor. | 914 // No deadline for synchronous compositor. |
878 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; | 915 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; |
879 } else if (wait_for_ready_to_draw_) { | 916 } else if (wait_for_ready_to_draw_) { |
880 // In browser compositor, wait for active tree to be rasterized. | 917 // In browser compositor, wait for active tree to be rasterized. |
881 DCHECK(settings_.commit_to_active_tree); | 918 DCHECK(settings_.commit_to_active_tree); |
882 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; | 919 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; |
883 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { | 920 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { |
884 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; | 921 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; |
885 } else if (needs_redraw_) { | 922 } else if (needs_redraw_ && begin_frame_allows_latency_optimizations_) { |
886 // We have an animation or fast input path on the impl thread that wants | 923 // We have an animation or fast input path on the impl thread that wants |
887 // to draw, so don't wait too long for a new active tree. | 924 // to draw, so don't wait too long for a new active tree. |
888 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; | 925 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; |
889 } else { | 926 } else { |
890 // The impl thread doesn't have anything it wants to draw and we are just | 927 // The impl thread doesn't have anything it wants to draw and we are just |
891 // waiting for a new active tree. In short we are blocked. | 928 // waiting for a new active tree. In short we are blocked. |
892 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; | 929 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; |
893 } | 930 } |
894 } | 931 } |
895 | 932 |
896 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() | 933 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() |
897 const { | 934 const { |
898 // If we just forced activation, we should end the deadline right now. | 935 // If we just forced activation, we should end the deadline right now. |
899 if (PendingActivationsShouldBeForced() && !has_pending_tree_) | 936 if (PendingActivationsShouldBeForced() && !has_pending_tree_) |
900 return true; | 937 return true; |
901 | 938 |
902 // Throttle the deadline on CompositorFrameAck since we wont draw and submit | 939 // Throttle the deadline on CompositorFrameAck since we wont draw and submit |
903 // anyway. | 940 // anyway. |
904 if (IsDrawThrottled()) | 941 if (IsDrawThrottled()) |
905 return false; | 942 return false; |
906 | 943 |
907 if (active_tree_needs_first_draw_) | 944 if (active_tree_needs_first_draw_) |
908 return true; | 945 return true; |
909 | 946 |
| 947 // Immediately respond to the BeginFrame if the main frame isn't producing |
| 948 // anything, e.g., after an aborted commit. We also check that we don't have a |
| 949 // pending tree -- otherwise we should give it a chance to activate. We |
| 950 // trigger an immediate deadline even if the impl thread doesn't want to draw |
| 951 // anything either, because we don't want to stall the BeginFrame |
| 952 // acknowledgment unnecessarily. |
| 953 // TODO(skyostil): Revisit this when we have more accurate deadline estimates. |
| 954 if (!CommitPending() && !has_pending_tree_) |
| 955 return true; |
| 956 |
910 if (!needs_redraw_) | 957 if (!needs_redraw_) |
911 return false; | 958 return false; |
912 | 959 |
913 // This is used to prioritize impl-thread draws when the main thread isn't | |
914 // producing anything, e.g., after an aborted commit. We also check that we | |
915 // don't have a pending tree -- otherwise we should give it a chance to | |
916 // activate. | |
917 // TODO(skyostil): Revisit this when we have more accurate deadline estimates. | |
918 if (!CommitPending() && !has_pending_tree_) | |
919 return true; | |
920 | |
921 // Prioritize impl-thread draws in ImplLatencyTakesPriority mode. | 960 // Prioritize impl-thread draws in ImplLatencyTakesPriority mode. |
922 if (ImplLatencyTakesPriority()) | 961 if (ImplLatencyTakesPriority()) |
923 return true; | 962 return true; |
924 | 963 |
925 return false; | 964 return false; |
926 } | 965 } |
927 | 966 |
928 bool SchedulerStateMachine::IsDrawThrottled() const { | 967 bool SchedulerStateMachine::IsDrawThrottled() const { |
929 return pending_submit_frames_ >= kMaxPendingSubmitFrames; | 968 return pending_submit_frames_ >= kMaxPendingSubmitFrames; |
930 } | 969 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 tree_priority_ = tree_priority; | 1038 tree_priority_ = tree_priority; |
1000 scroll_handler_state_ = scroll_handler_state; | 1039 scroll_handler_state_ = scroll_handler_state; |
1001 } | 1040 } |
1002 | 1041 |
1003 void SchedulerStateMachine::SetCriticalBeginMainFrameToActivateIsFast( | 1042 void SchedulerStateMachine::SetCriticalBeginMainFrameToActivateIsFast( |
1004 bool is_fast) { | 1043 bool is_fast) { |
1005 critical_begin_main_frame_to_activate_is_fast_ = is_fast; | 1044 critical_begin_main_frame_to_activate_is_fast_ = is_fast; |
1006 } | 1045 } |
1007 | 1046 |
1008 bool SchedulerStateMachine::ImplLatencyTakesPriority() const { | 1047 bool SchedulerStateMachine::ImplLatencyTakesPriority() const { |
| 1048 // Wait for main frame if requested by BeginFrameArgs. |
| 1049 if (!begin_frame_allows_latency_optimizations_) |
| 1050 return false; |
| 1051 |
1009 // Attempt to synchronize with the main thread if it has a scroll listener | 1052 // Attempt to synchronize with the main thread if it has a scroll listener |
1010 // and is fast. | 1053 // and is fast. |
1011 if (ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER == | 1054 if (ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER == |
1012 scroll_handler_state_ && | 1055 scroll_handler_state_ && |
1013 critical_begin_main_frame_to_activate_is_fast_) | 1056 critical_begin_main_frame_to_activate_is_fast_) |
1014 return false; | 1057 return false; |
1015 | 1058 |
1016 // Don't wait for the main thread if we are prioritizing smoothness. | 1059 // Don't wait for the main thread if we are prioritizing smoothness. |
1017 if (SMOOTHNESS_TAKES_PRIORITY == tree_priority_) | 1060 if (SMOOTHNESS_TAKES_PRIORITY == tree_priority_) |
1018 return true; | 1061 return true; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 case COMPOSITOR_FRAME_SINK_ACTIVE: | 1155 case COMPOSITOR_FRAME_SINK_ACTIVE: |
1113 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: | 1156 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: |
1114 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: | 1157 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: |
1115 return true; | 1158 return true; |
1116 } | 1159 } |
1117 NOTREACHED(); | 1160 NOTREACHED(); |
1118 return false; | 1161 return false; |
1119 } | 1162 } |
1120 | 1163 |
1121 } // namespace cc | 1164 } // namespace cc |
OLD | NEW |