Chromium Code Reviews| 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 30 matching lines...) Expand all Loading... | |
| 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 skip_next_begin_main_frame_to_reduce_latency_(false), | 50 skip_next_begin_main_frame_to_reduce_latency_(false), |
| 51 skip_begin_main_frame_to_reduce_latency_(false), | |
| 52 continuous_painting_(false), | 51 continuous_painting_(false), |
| 53 children_need_begin_frames_(false), | 52 children_need_begin_frames_(false), |
| 54 defer_commits_(false), | 53 defer_commits_(false), |
| 55 video_needs_begin_frames_(false), | 54 video_needs_begin_frames_(false), |
| 56 last_commit_had_no_updates_(false), | 55 last_commit_had_no_updates_(false), |
| 57 wait_for_active_tree_ready_to_draw_(false), | 56 wait_for_active_tree_ready_to_draw_(false), |
| 58 did_request_swap_in_last_frame_(false), | 57 did_request_swap_in_last_frame_(false), |
| 59 did_perform_swap_in_last_draw_(false) { | 58 did_perform_swap_in_last_draw_(false) { |
| 60 } | 59 } |
| 61 | 60 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 state->SetBoolean("active_tree_needs_first_draw", | 232 state->SetBoolean("active_tree_needs_first_draw", |
| 234 active_tree_needs_first_draw_); | 233 active_tree_needs_first_draw_); |
| 235 state->SetBoolean("wait_for_active_tree_ready_to_draw", | 234 state->SetBoolean("wait_for_active_tree_ready_to_draw", |
| 236 wait_for_active_tree_ready_to_draw_); | 235 wait_for_active_tree_ready_to_draw_); |
| 237 state->SetBoolean("did_create_and_initialize_first_output_surface", | 236 state->SetBoolean("did_create_and_initialize_first_output_surface", |
| 238 did_create_and_initialize_first_output_surface_); | 237 did_create_and_initialize_first_output_surface_); |
| 239 state->SetBoolean("impl_latency_takes_priority", | 238 state->SetBoolean("impl_latency_takes_priority", |
| 240 impl_latency_takes_priority_); | 239 impl_latency_takes_priority_); |
| 241 state->SetBoolean("main_thread_is_in_high_latency_mode", | 240 state->SetBoolean("main_thread_is_in_high_latency_mode", |
| 242 MainThreadIsInHighLatencyMode()); | 241 MainThreadIsInHighLatencyMode()); |
| 243 state->SetBoolean("skip_begin_main_frame_to_reduce_latency", | |
| 244 skip_begin_main_frame_to_reduce_latency_); | |
| 245 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", | 242 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", |
| 246 skip_next_begin_main_frame_to_reduce_latency_); | 243 skip_next_begin_main_frame_to_reduce_latency_); |
| 247 state->SetBoolean("continuous_painting", continuous_painting_); | 244 state->SetBoolean("continuous_painting", continuous_painting_); |
| 248 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); | 245 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); |
| 249 state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_); | 246 state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_); |
| 250 state->SetBoolean("defer_commits", defer_commits_); | 247 state->SetBoolean("defer_commits", defer_commits_); |
| 251 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_); |
| 252 state->SetBoolean("did_request_swap_in_last_frame", | 249 state->SetBoolean("did_request_swap_in_last_frame", |
| 253 did_request_swap_in_last_frame_); | 250 did_request_swap_in_last_frame_); |
| 254 state->SetBoolean("did_perform_swap_in_last_draw", | 251 state->SetBoolean("did_perform_swap_in_last_draw", |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 // this before checking for aborted draws because aborted draws do not request | 329 // this before checking for aborted draws because aborted draws do not request |
| 333 // a swap. | 330 // a swap. |
| 334 if (request_swap_funnel_) | 331 if (request_swap_funnel_) |
| 335 return false; | 332 return false; |
| 336 | 333 |
| 337 // Don't draw if we are waiting on the first commit after a surface. | 334 // Don't draw if we are waiting on the first commit after a surface. |
| 338 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) | 335 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) |
| 339 return false; | 336 return false; |
| 340 | 337 |
| 341 // Do not queue too many swaps. | 338 // Do not queue too many swaps. |
| 342 if (pending_swaps_ >= max_pending_swaps_) | 339 if (SwapThrottled()) |
| 343 return false; | 340 return false; |
| 344 | 341 |
| 345 // Except for the cases above, do not draw outside of the BeginImplFrame | 342 // Except for the cases above, do not draw outside of the BeginImplFrame |
| 346 // deadline. | 343 // deadline. |
| 347 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 344 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 348 return false; | 345 return false; |
| 349 | 346 |
| 350 // Only handle forced redraws due to timeouts on the regular deadline. | 347 // Only handle forced redraws due to timeouts on the regular deadline. |
| 351 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 348 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
| 352 return true; | 349 return true; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 | 403 |
| 407 bool SchedulerStateMachine::SendingBeginMainFrameMightCauseDeadlock() const { | 404 bool SchedulerStateMachine::SendingBeginMainFrameMightCauseDeadlock() const { |
| 408 // NPAPI is the only case where the UI thread makes synchronous calls to the | 405 // NPAPI is the only case where the UI thread makes synchronous calls to the |
| 409 // Renderer main thread. During that synchronous call, we may not get a | 406 // Renderer main thread. During that synchronous call, we may not get a |
| 410 // SwapAck for the UI thread, which may prevent BeginMainFrame's from | 407 // SwapAck for the UI thread, which may prevent BeginMainFrame's from |
| 411 // completing if there's enough back pressure. If the BeginMainFrame can't | 408 // completing if there's enough back pressure. If the BeginMainFrame can't |
| 412 // make progress, the Renderer can't service the UI thread's synchronous call | 409 // make progress, the Renderer can't service the UI thread's synchronous call |
| 413 // and we have deadlock. | 410 // and we have deadlock. |
| 414 // This returns true if there's too much backpressure to finish a commit | 411 // This returns true if there's too much backpressure to finish a commit |
| 415 // if we were to initiate a BeginMainFrame. | 412 // if we were to initiate a BeginMainFrame. |
| 416 return has_pending_tree_ && active_tree_needs_first_draw_ && | 413 return has_pending_tree_ && active_tree_needs_first_draw_ && SwapThrottled(); |
| 417 pending_swaps_ >= max_pending_swaps_; | |
| 418 } | 414 } |
| 419 | 415 |
| 420 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { | 416 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { |
| 421 if (!CouldSendBeginMainFrame()) | 417 if (!CouldSendBeginMainFrame()) |
| 422 return false; | 418 return false; |
| 423 | 419 |
| 424 // Do not send begin main frame too many times in a single frame. | 420 // Do not send begin main frame too many times in a single frame. |
| 425 if (send_begin_main_frame_funnel_) | 421 if (send_begin_main_frame_funnel_) |
| 426 return false; | 422 return false; |
| 427 | 423 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 return false; | 461 return false; |
| 466 | 462 |
| 467 if (!settings_.main_frame_while_swap_throttled_enabled) { | 463 if (!settings_.main_frame_while_swap_throttled_enabled) { |
| 468 // SwapAck throttle the BeginMainFrames unless we just swapped to | 464 // SwapAck throttle the BeginMainFrames unless we just swapped to |
| 469 // potentially improve impl-thread latency over main-thread throughput. | 465 // potentially improve impl-thread latency over main-thread throughput. |
| 470 // TODO(brianderson): Remove this restriction to improve throughput or | 466 // TODO(brianderson): Remove this restriction to improve throughput or |
| 471 // make it conditional on impl_latency_takes_priority_. | 467 // make it conditional on impl_latency_takes_priority_. |
| 472 bool just_swapped_in_deadline = | 468 bool just_swapped_in_deadline = |
| 473 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && | 469 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && |
| 474 did_perform_swap_in_last_draw_; | 470 did_perform_swap_in_last_draw_; |
| 475 if (pending_swaps_ >= max_pending_swaps_ && !just_swapped_in_deadline) | 471 if (SwapThrottled() && !just_swapped_in_deadline) |
| 476 return false; | 472 return false; |
| 477 } | 473 } |
| 478 | 474 |
| 479 if (skip_begin_main_frame_to_reduce_latency_) | 475 if (skip_next_begin_main_frame_to_reduce_latency_) |
| 480 return false; | 476 return false; |
| 481 | 477 |
| 482 return true; | 478 return true; |
| 483 } | 479 } |
| 484 | 480 |
| 485 bool SchedulerStateMachine::ShouldCommit() const { | 481 bool SchedulerStateMachine::ShouldCommit() const { |
| 486 if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT) | 482 if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT) |
| 487 return false; | 483 return false; |
| 488 | 484 |
| 489 // We must not finish the commit until the pending tree is free. | 485 // We must not finish the commit until the pending tree is free. |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 did_request_swap_in_last_frame_ = false; | 847 did_request_swap_in_last_frame_ = false; |
| 852 | 848 |
| 853 // Clear funnels for any actions we perform during the frame. | 849 // Clear funnels for any actions we perform during the frame. |
| 854 animate_funnel_ = false; | 850 animate_funnel_ = false; |
| 855 send_begin_main_frame_funnel_ = false; | 851 send_begin_main_frame_funnel_ = false; |
| 856 invalidate_output_surface_funnel_ = false; | 852 invalidate_output_surface_funnel_ = false; |
| 857 | 853 |
| 858 // "Drain" the PrepareTiles funnel. | 854 // "Drain" the PrepareTiles funnel. |
| 859 if (prepare_tiles_funnel_ > 0) | 855 if (prepare_tiles_funnel_ > 0) |
| 860 prepare_tiles_funnel_--; | 856 prepare_tiles_funnel_--; |
| 861 | |
| 862 skip_begin_main_frame_to_reduce_latency_ = | |
| 863 skip_next_begin_main_frame_to_reduce_latency_; | |
| 864 skip_next_begin_main_frame_to_reduce_latency_ = false; | |
| 865 } | 857 } |
| 866 | 858 |
| 867 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 859 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
| 868 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 860 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
| 869 } | 861 } |
| 870 | 862 |
| 871 void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 863 void SchedulerStateMachine::OnBeginImplFrameDeadline() { |
| 872 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 864 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
| 873 | 865 |
| 874 did_perform_swap_in_last_draw_ = false; | 866 did_perform_swap_in_last_draw_ = false; |
| 875 | 867 |
| 876 // Clear funnels for any actions we perform during the deadline. | 868 // Clear funnels for any actions we perform during the deadline. |
| 877 request_swap_funnel_ = false; | 869 request_swap_funnel_ = false; |
| 878 | 870 |
| 879 // Allow one PrepareTiles per draw for synchronous compositor. | 871 // Allow one PrepareTiles per draw for synchronous compositor. |
| 880 if (settings_.using_synchronous_renderer_compositor) { | 872 if (settings_.using_synchronous_renderer_compositor) { |
| 881 if (prepare_tiles_funnel_ > 0) | 873 if (prepare_tiles_funnel_ > 0) |
| 882 prepare_tiles_funnel_--; | 874 prepare_tiles_funnel_--; |
| 883 } | 875 } |
| 884 } | 876 } |
| 885 | 877 |
| 886 void SchedulerStateMachine::OnBeginImplFrameIdle() { | 878 void SchedulerStateMachine::OnBeginImplFrameIdle() { |
| 887 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; | 879 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; |
| 880 | |
| 881 skip_next_begin_main_frame_to_reduce_latency_ = false; | |
|
sunnyps
2015/07/08 22:37:12
Why was this moved here?
brianderson
2015/07/09 01:28:11
Resetting it here allowed me to get rid of the ski
| |
| 888 } | 882 } |
| 889 | 883 |
| 890 SchedulerStateMachine::BeginImplFrameDeadlineMode | 884 SchedulerStateMachine::BeginImplFrameDeadlineMode |
| 891 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 885 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
| 892 if (settings_.using_synchronous_renderer_compositor) { | 886 if (settings_.using_synchronous_renderer_compositor) { |
| 893 // No deadline for synchronous compositor. | 887 // No deadline for synchronous compositor. |
| 894 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; | 888 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; |
| 895 } else if (wait_for_active_tree_ready_to_draw_) { | 889 } else if (wait_for_active_tree_ready_to_draw_) { |
| 896 // When we are waiting for ready to draw signal, we do not wait to post a | 890 // When we are waiting for ready to draw signal, we do not wait to post a |
| 897 // deadline yet. | 891 // deadline yet. |
| 898 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; | 892 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; |
| 899 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { | 893 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { |
| 900 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; | 894 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; |
| 901 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { | 895 } else if (needs_redraw_ && !SwapThrottled()) { |
| 902 // We have an animation or fast input path on the impl thread that wants | 896 // We have an animation or fast input path on the impl thread that wants |
| 903 // to draw, so don't wait too long for a new active tree. | 897 // to draw, so don't wait too long for a new active tree. |
| 904 // If we are swap throttled we should wait until we are unblocked. | 898 // If we are swap throttled we should wait until we are unblocked. |
| 905 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; | 899 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; |
| 906 } else { | 900 } else { |
| 907 // The impl thread doesn't have anything it wants to draw and we are just | 901 // The impl thread doesn't have anything it wants to draw and we are just |
| 908 // waiting for a new active tree or we are swap throttled. In short we are | 902 // waiting for a new active tree or we are swap throttled. In short we are |
| 909 // blocked. | 903 // blocked. |
| 910 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; | 904 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; |
| 911 } | 905 } |
| 912 } | 906 } |
| 913 | 907 |
| 914 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() | 908 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() |
| 915 const { | 909 const { |
| 916 // TODO(brianderson): This should take into account multiple commit sources. | |
| 917 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 910 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
| 918 return false; | 911 return false; |
| 919 | 912 |
| 920 // If we just forced activation, we should end the deadline right now. | 913 // If we just forced activation, we should end the deadline right now. |
| 921 if (PendingActivationsShouldBeForced() && !has_pending_tree_) | 914 if (PendingActivationsShouldBeForced() && !has_pending_tree_) |
| 922 return true; | 915 return true; |
| 923 | 916 |
| 924 // SwapAck throttle the deadline since we wont draw and swap anyway. | 917 // SwapAck throttle the deadline since we wont draw and swap anyway. |
| 925 if (pending_swaps_ >= max_pending_swaps_) | 918 if (SwapThrottled()) |
| 926 return false; | 919 return false; |
| 927 | 920 |
| 928 if (active_tree_needs_first_draw_) | 921 if (active_tree_needs_first_draw_) |
| 929 return true; | 922 return true; |
| 930 | 923 |
| 931 if (!needs_redraw_) | 924 if (!needs_redraw_) |
| 932 return false; | 925 return false; |
| 933 | 926 |
| 934 // This is used to prioritize impl-thread draws when the main thread isn't | 927 // This is used to prioritize impl-thread draws when the main thread isn't |
| 935 // producing anything, e.g., after an aborted commit. We also check that we | 928 // producing anything, e.g., after an aborted commit. We also check that we |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1157 case OUTPUT_SURFACE_ACTIVE: | 1150 case OUTPUT_SURFACE_ACTIVE: |
| 1158 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1151 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
| 1159 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1152 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
| 1160 return true; | 1153 return true; |
| 1161 } | 1154 } |
| 1162 NOTREACHED(); | 1155 NOTREACHED(); |
| 1163 return false; | 1156 return false; |
| 1164 } | 1157 } |
| 1165 | 1158 |
| 1166 } // namespace cc | 1159 } // namespace cc |
| OLD | NEW |