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 29 matching lines...) Expand all Loading... |
40 needs_prepare_tiles_(false), | 40 needs_prepare_tiles_(false), |
41 needs_commit_(false), | 41 needs_commit_(false), |
42 visible_(false), | 42 visible_(false), |
43 can_start_(false), | 43 can_start_(false), |
44 can_draw_(false), | 44 can_draw_(false), |
45 has_pending_tree_(false), | 45 has_pending_tree_(false), |
46 pending_tree_is_ready_for_activation_(false), | 46 pending_tree_is_ready_for_activation_(false), |
47 active_tree_needs_first_draw_(false), | 47 active_tree_needs_first_draw_(false), |
48 did_create_and_initialize_first_output_surface_(false), | 48 did_create_and_initialize_first_output_surface_(false), |
49 impl_latency_takes_priority_(false), | 49 impl_latency_takes_priority_(false), |
| 50 main_thread_missed_last_deadline_(false), |
50 skip_next_begin_main_frame_to_reduce_latency_(false), | 51 skip_next_begin_main_frame_to_reduce_latency_(false), |
51 continuous_painting_(false), | 52 continuous_painting_(false), |
52 children_need_begin_frames_(false), | 53 children_need_begin_frames_(false), |
53 defer_commits_(false), | 54 defer_commits_(false), |
54 video_needs_begin_frames_(false), | 55 video_needs_begin_frames_(false), |
55 last_commit_had_no_updates_(false), | 56 last_commit_had_no_updates_(false), |
56 wait_for_active_tree_ready_to_draw_(false), | 57 wait_for_active_tree_ready_to_draw_(false), |
57 did_request_swap_in_last_frame_(false), | 58 did_request_swap_in_last_frame_(false), |
58 did_perform_swap_in_last_draw_(false) { | 59 did_perform_swap_in_last_draw_(false) {} |
59 } | |
60 | 60 |
61 const char* SchedulerStateMachine::OutputSurfaceStateToString( | 61 const char* SchedulerStateMachine::OutputSurfaceStateToString( |
62 OutputSurfaceState state) { | 62 OutputSurfaceState state) { |
63 switch (state) { | 63 switch (state) { |
64 case OUTPUT_SURFACE_ACTIVE: | 64 case OUTPUT_SURFACE_ACTIVE: |
65 return "OUTPUT_SURFACE_ACTIVE"; | 65 return "OUTPUT_SURFACE_ACTIVE"; |
66 case OUTPUT_SURFACE_LOST: | 66 case OUTPUT_SURFACE_LOST: |
67 return "OUTPUT_SURFACE_LOST"; | 67 return "OUTPUT_SURFACE_LOST"; |
68 case OUTPUT_SURFACE_CREATING: | 68 case OUTPUT_SURFACE_CREATING: |
69 return "OUTPUT_SURFACE_CREATING"; | 69 return "OUTPUT_SURFACE_CREATING"; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 state->SetBoolean("pending_tree_is_ready_for_activation", | 230 state->SetBoolean("pending_tree_is_ready_for_activation", |
231 pending_tree_is_ready_for_activation_); | 231 pending_tree_is_ready_for_activation_); |
232 state->SetBoolean("active_tree_needs_first_draw", | 232 state->SetBoolean("active_tree_needs_first_draw", |
233 active_tree_needs_first_draw_); | 233 active_tree_needs_first_draw_); |
234 state->SetBoolean("wait_for_active_tree_ready_to_draw", | 234 state->SetBoolean("wait_for_active_tree_ready_to_draw", |
235 wait_for_active_tree_ready_to_draw_); | 235 wait_for_active_tree_ready_to_draw_); |
236 state->SetBoolean("did_create_and_initialize_first_output_surface", | 236 state->SetBoolean("did_create_and_initialize_first_output_surface", |
237 did_create_and_initialize_first_output_surface_); | 237 did_create_and_initialize_first_output_surface_); |
238 state->SetBoolean("impl_latency_takes_priority", | 238 state->SetBoolean("impl_latency_takes_priority", |
239 impl_latency_takes_priority_); | 239 impl_latency_takes_priority_); |
240 state->SetBoolean("main_thread_is_in_high_latency_mode", | 240 state->SetBoolean("main_thread_missed_last_deadline", |
241 MainThreadIsInHighLatencyMode()); | 241 main_thread_missed_last_deadline_); |
242 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", | 242 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", |
243 skip_next_begin_main_frame_to_reduce_latency_); | 243 skip_next_begin_main_frame_to_reduce_latency_); |
244 state->SetBoolean("continuous_painting", continuous_painting_); | 244 state->SetBoolean("continuous_painting", continuous_painting_); |
245 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); | 245 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); |
246 state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_); | 246 state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_); |
247 state->SetBoolean("defer_commits", defer_commits_); | 247 state->SetBoolean("defer_commits", defer_commits_); |
248 state->SetBoolean("last_commit_had_no_updates", last_commit_had_no_updates_); | 248 state->SetBoolean("last_commit_had_no_updates", last_commit_had_no_updates_); |
249 state->SetBoolean("did_request_swap_in_last_frame", | 249 state->SetBoolean("did_request_swap_in_last_frame", |
250 did_request_swap_in_last_frame_); | 250 did_request_swap_in_last_frame_); |
251 state->SetBoolean("did_perform_swap_in_last_draw", | 251 state->SetBoolean("did_perform_swap_in_last_draw", |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 if (prepare_tiles_funnel_ > 0) | 876 if (prepare_tiles_funnel_ > 0) |
877 prepare_tiles_funnel_--; | 877 prepare_tiles_funnel_--; |
878 } | 878 } |
879 } | 879 } |
880 | 880 |
881 void SchedulerStateMachine::OnBeginImplFrameIdle() { | 881 void SchedulerStateMachine::OnBeginImplFrameIdle() { |
882 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; | 882 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; |
883 | 883 |
884 skip_next_begin_main_frame_to_reduce_latency_ = false; | 884 skip_next_begin_main_frame_to_reduce_latency_ = false; |
885 | 885 |
| 886 // If a new or undrawn active tree is pending after the deadline, |
| 887 // then the main thread is in a high latency mode. |
| 888 main_thread_missed_last_deadline_ = |
| 889 CommitPending() || has_pending_tree_ || active_tree_needs_first_draw_; |
| 890 |
886 // If we're entering a state where we won't get BeginFrames set all the | 891 // If we're entering a state where we won't get BeginFrames set all the |
887 // funnels so that we don't perform any actions that we shouldn't. | 892 // funnels so that we don't perform any actions that we shouldn't. |
888 if (!BeginFrameNeeded()) | 893 if (!BeginFrameNeeded()) |
889 send_begin_main_frame_funnel_ = true; | 894 send_begin_main_frame_funnel_ = true; |
890 } | 895 } |
891 | 896 |
892 SchedulerStateMachine::BeginImplFrameDeadlineMode | 897 SchedulerStateMachine::BeginImplFrameDeadlineMode |
893 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 898 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
894 if (settings_.using_synchronous_renderer_compositor) { | 899 if (settings_.using_synchronous_renderer_compositor) { |
895 // No deadline for synchronous compositor. | 900 // No deadline for synchronous compositor. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) | 945 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) |
941 return true; | 946 return true; |
942 | 947 |
943 // Prioritize impl-thread draws in impl_latency_takes_priority_ mode. | 948 // Prioritize impl-thread draws in impl_latency_takes_priority_ mode. |
944 if (impl_latency_takes_priority_) | 949 if (impl_latency_takes_priority_) |
945 return true; | 950 return true; |
946 | 951 |
947 return false; | 952 return false; |
948 } | 953 } |
949 | 954 |
950 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const { | 955 bool SchedulerStateMachine::main_thread_missed_last_deadline() const { |
951 // If a commit is pending before the previous commit has been drawn, we | 956 return main_thread_missed_last_deadline_; |
952 // are definitely in a high latency mode. | |
953 if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_)) | |
954 return true; | |
955 | |
956 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main | |
957 // thread is in a low latency mode. | |
958 if (send_begin_main_frame_funnel_ && | |
959 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING || | |
960 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)) | |
961 return false; | |
962 | |
963 // If there's a commit in progress it must either be from the previous frame | |
964 // or it started after the impl thread's deadline. In either case the main | |
965 // thread is in high latency mode. | |
966 if (CommitPending()) | |
967 return true; | |
968 | |
969 // Similarly, if there's a pending tree the main thread is in high latency | |
970 // mode, because either | |
971 // it's from the previous frame | |
972 // or | |
973 // we're currently drawing the active tree and the pending tree will thus | |
974 // only be drawn in the next frame. | |
975 if (has_pending_tree_) | |
976 return true; | |
977 | |
978 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { | |
979 // Even if there's a new active tree to draw at the deadline or we've just | |
980 // swapped it, it may have been triggered by a previous BeginImplFrame, in | |
981 // which case the main thread is in a high latency mode. | |
982 return (active_tree_needs_first_draw_ || did_perform_swap_in_last_draw_) && | |
983 !send_begin_main_frame_funnel_; | |
984 } | |
985 | |
986 // If the active tree needs its first draw in any other state, we know the | |
987 // main thread is in a high latency mode. | |
988 return active_tree_needs_first_draw_; | |
989 } | 957 } |
990 | 958 |
991 bool SchedulerStateMachine::SwapThrottled() const { | 959 bool SchedulerStateMachine::SwapThrottled() const { |
992 return pending_swaps_ >= max_pending_swaps_; | 960 return pending_swaps_ >= max_pending_swaps_; |
993 } | 961 } |
994 | 962 |
995 void SchedulerStateMachine::SetVisible(bool visible) { | 963 void SchedulerStateMachine::SetVisible(bool visible) { |
| 964 if (visible_ == visible) |
| 965 return; |
| 966 |
996 visible_ = visible; | 967 visible_ = visible; |
| 968 |
| 969 if (visible) |
| 970 main_thread_missed_last_deadline_ = false; |
| 971 |
997 // TODO(sunnyps): Change the funnel to a bool to avoid hacks like this. | 972 // TODO(sunnyps): Change the funnel to a bool to avoid hacks like this. |
998 prepare_tiles_funnel_ = 0; | 973 prepare_tiles_funnel_ = 0; |
999 } | 974 } |
1000 | 975 |
1001 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } | 976 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } |
1002 | 977 |
1003 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } | 978 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } |
1004 | 979 |
1005 void SchedulerStateMachine::SetNeedsAnimate() { | 980 void SchedulerStateMachine::SetNeedsAnimate() { |
1006 needs_animate_ = true; | 981 needs_animate_ = true; |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; | 1125 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; |
1151 | 1126 |
1152 if (did_create_and_initialize_first_output_surface_) { | 1127 if (did_create_and_initialize_first_output_surface_) { |
1153 // TODO(boliu): See if we can remove this when impl-side painting is always | 1128 // TODO(boliu): See if we can remove this when impl-side painting is always |
1154 // on. Does anything on the main thread need to update after recreate? | 1129 // on. Does anything on the main thread need to update after recreate? |
1155 needs_commit_ = true; | 1130 needs_commit_ = true; |
1156 } | 1131 } |
1157 did_create_and_initialize_first_output_surface_ = true; | 1132 did_create_and_initialize_first_output_surface_ = true; |
1158 pending_swaps_ = 0; | 1133 pending_swaps_ = 0; |
1159 swaps_with_current_output_surface_ = 0; | 1134 swaps_with_current_output_surface_ = 0; |
| 1135 main_thread_missed_last_deadline_ = false; |
1160 } | 1136 } |
1161 | 1137 |
1162 void SchedulerStateMachine::NotifyBeginMainFrameStarted() { | 1138 void SchedulerStateMachine::NotifyBeginMainFrameStarted() { |
1163 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); | 1139 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); |
1164 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED; | 1140 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED; |
1165 } | 1141 } |
1166 | 1142 |
1167 bool SchedulerStateMachine::HasInitializedOutputSurface() const { | 1143 bool SchedulerStateMachine::HasInitializedOutputSurface() const { |
1168 switch (output_surface_state_) { | 1144 switch (output_surface_state_) { |
1169 case OUTPUT_SURFACE_LOST: | 1145 case OUTPUT_SURFACE_LOST: |
1170 case OUTPUT_SURFACE_CREATING: | 1146 case OUTPUT_SURFACE_CREATING: |
1171 return false; | 1147 return false; |
1172 | 1148 |
1173 case OUTPUT_SURFACE_ACTIVE: | 1149 case OUTPUT_SURFACE_ACTIVE: |
1174 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1150 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
1175 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1151 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
1176 return true; | 1152 return true; |
1177 } | 1153 } |
1178 NOTREACHED(); | 1154 NOTREACHED(); |
1179 return false; | 1155 return false; |
1180 } | 1156 } |
1181 | 1157 |
1182 } // namespace cc | 1158 } // namespace cc |
OLD | NEW |