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