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/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "base/debug/trace_event_argument.h" |
8 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
11 #include "base/values.h" | 12 #include "base/values.h" |
12 #include "ui/gfx/frame_time.h" | 13 #include "ui/gfx/frame_time.h" |
13 | 14 |
14 namespace cc { | 15 namespace cc { |
15 | 16 |
16 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) | 17 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) |
17 : settings_(settings), | 18 : settings_(settings), |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 return "ACTION_DRAW_AND_SWAP_ABORT"; | 141 return "ACTION_DRAW_AND_SWAP_ABORT"; |
141 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 142 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
142 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; | 143 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; |
143 case ACTION_MANAGE_TILES: | 144 case ACTION_MANAGE_TILES: |
144 return "ACTION_MANAGE_TILES"; | 145 return "ACTION_MANAGE_TILES"; |
145 } | 146 } |
146 NOTREACHED(); | 147 NOTREACHED(); |
147 return "???"; | 148 return "???"; |
148 } | 149 } |
149 | 150 |
150 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { | 151 scoped_refptr<base::debug::ConvertableToTraceFormat> |
151 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | 152 SchedulerStateMachine::AsValue() const { |
| 153 scoped_refptr<base::debug::TracedValue> state = |
| 154 new base::debug::TracedValue(); |
| 155 AsValueInto(state); |
| 156 return state; |
| 157 } |
152 | 158 |
153 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue); | 159 void SchedulerStateMachine::AsValueInto(base::debug::TracedValue* state) const { |
154 major_state->SetString("next_action", ActionToString(NextAction())); | 160 state->BeginDictionary("major_state"); |
155 major_state->SetString("begin_impl_frame_state", | 161 state->SetString("next_action", ActionToString(NextAction())); |
156 BeginImplFrameStateToString(begin_impl_frame_state_)); | 162 state->SetString("begin_impl_frame_state", |
157 major_state->SetString("commit_state", CommitStateToString(commit_state_)); | 163 BeginImplFrameStateToString(begin_impl_frame_state_)); |
158 major_state->SetString("output_surface_state_", | 164 state->SetString("commit_state", CommitStateToString(commit_state_)); |
159 OutputSurfaceStateToString(output_surface_state_)); | 165 state->SetString("output_surface_state_", |
160 major_state->SetString( | 166 OutputSurfaceStateToString(output_surface_state_)); |
161 "forced_redraw_state", | 167 state->SetString("forced_redraw_state", |
162 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); | 168 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); |
163 state->Set("major_state", major_state.release()); | 169 state->EndDictionary(); |
164 | 170 |
165 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); | 171 state->BeginDictionary("major_timestamps_in_ms"); |
166 base::TimeTicks now = gfx::FrameTime::Now(); | 172 base::TimeTicks now = gfx::FrameTime::Now(); |
167 timestamps_state->SetDouble( | 173 state->SetDouble("0_interval", |
168 "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); | 174 begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); |
169 timestamps_state->SetDouble( | 175 state->SetDouble( |
170 "1_now_to_deadline", | 176 "1_now_to_deadline", |
171 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); | 177 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); |
172 timestamps_state->SetDouble( | 178 state->SetDouble( |
173 "2_frame_time_to_now", | 179 "2_frame_time_to_now", |
174 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L); | 180 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L); |
175 timestamps_state->SetDouble( | 181 state->SetDouble("3_frame_time_to_deadline", |
176 "3_frame_time_to_deadline", | 182 (begin_impl_frame_args_.deadline - |
177 (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time) | 183 begin_impl_frame_args_.frame_time).InMicroseconds() / |
178 .InMicroseconds() / | 184 1000.0L); |
179 1000.0L); | 185 state->SetDouble("4_now", |
180 timestamps_state->SetDouble( | 186 (now - base::TimeTicks()).InMicroseconds() / 1000.0L); |
181 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); | 187 state->SetDouble( |
182 timestamps_state->SetDouble( | |
183 "5_frame_time", | 188 "5_frame_time", |
184 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / | 189 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / |
185 1000.0L); | 190 1000.0L); |
186 timestamps_state->SetDouble( | 191 state->SetDouble( |
187 "6_deadline", | 192 "6_deadline", |
188 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / | 193 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / |
189 1000.0L); | 194 1000.0L); |
190 state->Set("major_timestamps_in_ms", timestamps_state.release()); | 195 state->EndDictionary(); |
191 | 196 |
192 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); | 197 state->BeginDictionary("minor_state"); |
193 minor_state->SetInteger("commit_count", commit_count_); | 198 state->SetInteger("commit_count", commit_count_); |
194 minor_state->SetInteger("current_frame_number", current_frame_number_); | 199 state->SetInteger("current_frame_number", current_frame_number_); |
195 | 200 |
196 minor_state->SetInteger("last_frame_number_animate_performed", | 201 state->SetInteger("last_frame_number_animate_performed", |
197 last_frame_number_animate_performed_); | 202 last_frame_number_animate_performed_); |
198 minor_state->SetInteger("last_frame_number_swap_performed", | 203 state->SetInteger("last_frame_number_swap_performed", |
199 last_frame_number_swap_performed_); | 204 last_frame_number_swap_performed_); |
200 minor_state->SetInteger("last_frame_number_swap_requested", | 205 state->SetInteger("last_frame_number_swap_requested", |
201 last_frame_number_swap_requested_); | 206 last_frame_number_swap_requested_); |
202 minor_state->SetInteger( | 207 state->SetInteger("last_frame_number_begin_main_frame_sent", |
203 "last_frame_number_begin_main_frame_sent", | 208 last_frame_number_begin_main_frame_sent_); |
204 last_frame_number_begin_main_frame_sent_); | 209 state->SetInteger("last_frame_number_update_visible_tiles_was_called", |
205 minor_state->SetInteger( | 210 last_frame_number_update_visible_tiles_was_called_); |
206 "last_frame_number_update_visible_tiles_was_called", | |
207 last_frame_number_update_visible_tiles_was_called_); | |
208 | 211 |
209 minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_); | 212 state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_); |
210 minor_state->SetInteger("consecutive_checkerboard_animations", | 213 state->SetInteger("consecutive_checkerboard_animations", |
211 consecutive_checkerboard_animations_); | 214 consecutive_checkerboard_animations_); |
212 minor_state->SetInteger("max_pending_swaps_", max_pending_swaps_); | 215 state->SetInteger("max_pending_swaps_", max_pending_swaps_); |
213 minor_state->SetInteger("pending_swaps_", pending_swaps_); | 216 state->SetInteger("pending_swaps_", pending_swaps_); |
214 minor_state->SetBoolean("needs_redraw", needs_redraw_); | 217 state->SetBoolean("needs_redraw", needs_redraw_); |
215 minor_state->SetBoolean("needs_animate_", needs_animate_); | 218 state->SetBoolean("needs_animate_", needs_animate_); |
216 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_); | 219 state->SetBoolean("needs_manage_tiles", needs_manage_tiles_); |
217 minor_state->SetBoolean("swap_used_incomplete_tile", | 220 state->SetBoolean("swap_used_incomplete_tile", swap_used_incomplete_tile_); |
218 swap_used_incomplete_tile_); | 221 state->SetBoolean("needs_commit", needs_commit_); |
219 minor_state->SetBoolean("needs_commit", needs_commit_); | 222 state->SetBoolean("visible", visible_); |
220 minor_state->SetBoolean("visible", visible_); | 223 state->SetBoolean("can_start", can_start_); |
221 minor_state->SetBoolean("can_start", can_start_); | 224 state->SetBoolean("can_draw", can_draw_); |
222 minor_state->SetBoolean("can_draw", can_draw_); | 225 state->SetBoolean("has_pending_tree", has_pending_tree_); |
223 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); | 226 state->SetBoolean("pending_tree_is_ready_for_activation", |
224 minor_state->SetBoolean("pending_tree_is_ready_for_activation", | 227 pending_tree_is_ready_for_activation_); |
225 pending_tree_is_ready_for_activation_); | 228 state->SetBoolean("active_tree_needs_first_draw", |
226 minor_state->SetBoolean("active_tree_needs_first_draw", | 229 active_tree_needs_first_draw_); |
227 active_tree_needs_first_draw_); | 230 state->SetBoolean("did_create_and_initialize_first_output_surface", |
228 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", | 231 did_create_and_initialize_first_output_surface_); |
229 did_create_and_initialize_first_output_surface_); | 232 state->SetBoolean("smoothness_takes_priority", smoothness_takes_priority_); |
230 minor_state->SetBoolean("smoothness_takes_priority", | 233 state->SetBoolean("main_thread_is_in_high_latency_mode", |
231 smoothness_takes_priority_); | 234 MainThreadIsInHighLatencyMode()); |
232 minor_state->SetBoolean("main_thread_is_in_high_latency_mode", | 235 state->SetBoolean("skip_begin_main_frame_to_reduce_latency", |
233 MainThreadIsInHighLatencyMode()); | 236 skip_begin_main_frame_to_reduce_latency_); |
234 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency", | 237 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", |
235 skip_begin_main_frame_to_reduce_latency_); | 238 skip_next_begin_main_frame_to_reduce_latency_); |
236 minor_state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", | 239 state->SetBoolean("continuous_painting", continuous_painting_); |
237 skip_next_begin_main_frame_to_reduce_latency_); | 240 state->EndDictionary(); |
238 minor_state->SetBoolean("continuous_painting", continuous_painting_); | |
239 state->Set("minor_state", minor_state.release()); | |
240 | |
241 return state.PassAs<base::Value>(); | |
242 } | 241 } |
243 | 242 |
244 void SchedulerStateMachine::AdvanceCurrentFrameNumber() { | 243 void SchedulerStateMachine::AdvanceCurrentFrameNumber() { |
245 current_frame_number_++; | 244 current_frame_number_++; |
246 | 245 |
247 // "Drain" the ManageTiles funnel. | 246 // "Drain" the ManageTiles funnel. |
248 if (manage_tiles_funnel_ > 0) | 247 if (manage_tiles_funnel_ > 0) |
249 manage_tiles_funnel_--; | 248 manage_tiles_funnel_--; |
250 | 249 |
251 skip_begin_main_frame_to_reduce_latency_ = | 250 skip_begin_main_frame_to_reduce_latency_ = |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 // BeginImplFrame. | 802 // BeginImplFrame. |
804 if (HasRequestedSwapThisFrame()) | 803 if (HasRequestedSwapThisFrame()) |
805 return true; | 804 return true; |
806 | 805 |
807 return false; | 806 return false; |
808 } | 807 } |
809 | 808 |
810 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { | 809 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { |
811 AdvanceCurrentFrameNumber(); | 810 AdvanceCurrentFrameNumber(); |
812 begin_impl_frame_args_ = args; | 811 begin_impl_frame_args_ = args; |
813 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); | 812 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) |
| 813 << AsValue()->ToString(); |
814 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; | 814 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; |
815 } | 815 } |
816 | 816 |
817 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 817 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
818 DCHECK_EQ(begin_impl_frame_state_, | 818 DCHECK_EQ(begin_impl_frame_state_, |
819 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) | 819 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) |
820 << *AsValue(); | 820 << AsValue()->ToString(); |
821 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 821 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
822 } | 822 } |
823 | 823 |
824 void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 824 void SchedulerStateMachine::OnBeginImplFrameDeadline() { |
825 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 825 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
826 << *AsValue(); | 826 << AsValue()->ToString(); |
827 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 827 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
828 } | 828 } |
829 | 829 |
830 void SchedulerStateMachine::OnBeginImplFrameIdle() { | 830 void SchedulerStateMachine::OnBeginImplFrameIdle() { |
831 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 831 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
832 << *AsValue(); | 832 << AsValue()->ToString(); |
833 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; | 833 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; |
834 } | 834 } |
835 | 835 |
836 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const { | 836 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const { |
837 // TODO(brianderson): This should take into account multiple commit sources. | 837 // TODO(brianderson): This should take into account multiple commit sources. |
838 | 838 |
839 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 839 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
840 return false; | 840 return false; |
841 | 841 |
842 // If we've lost the output surface, end the current BeginImplFrame ASAP | 842 // If we've lost the output surface, end the current BeginImplFrame ASAP |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 // removing textures (which might not). To be safe, request a commit | 1002 // removing textures (which might not). To be safe, request a commit |
1003 // anyway. | 1003 // anyway. |
1004 needs_commit_ = true; | 1004 needs_commit_ = true; |
1005 break; | 1005 break; |
1006 } | 1006 } |
1007 } | 1007 } |
1008 | 1008 |
1009 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } | 1009 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } |
1010 | 1010 |
1011 void SchedulerStateMachine::NotifyReadyToCommit() { | 1011 void SchedulerStateMachine::NotifyReadyToCommit() { |
1012 DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue(); | 1012 DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) |
| 1013 << AsValue()->ToString(); |
1013 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; | 1014 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; |
1014 } | 1015 } |
1015 | 1016 |
1016 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) { | 1017 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) { |
1017 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); | 1018 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); |
1018 if (did_handle) { | 1019 if (did_handle) { |
1019 bool commit_was_aborted = true; | 1020 bool commit_was_aborted = true; |
1020 UpdateStateOnCommit(commit_was_aborted); | 1021 UpdateStateOnCommit(commit_was_aborted); |
1021 } else { | 1022 } else { |
1022 commit_state_ = COMMIT_STATE_IDLE; | 1023 commit_state_ = COMMIT_STATE_IDLE; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 case OUTPUT_SURFACE_ACTIVE: | 1071 case OUTPUT_SURFACE_ACTIVE: |
1071 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1072 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
1072 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1073 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
1073 return true; | 1074 return true; |
1074 } | 1075 } |
1075 NOTREACHED(); | 1076 NOTREACHED(); |
1076 return false; | 1077 return false; |
1077 } | 1078 } |
1078 | 1079 |
1079 } // namespace cc | 1080 } // namespace cc |
OLD | NEW |