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/format_macros.h" | 8 #include "base/format_macros.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 main_thread_needs_layer_textures_(false), | 34 main_thread_needs_layer_textures_(false), |
35 inside_poll_for_anticipated_draw_triggers_(false), | 35 inside_poll_for_anticipated_draw_triggers_(false), |
36 visible_(false), | 36 visible_(false), |
37 can_start_(false), | 37 can_start_(false), |
38 can_draw_(false), | 38 can_draw_(false), |
39 has_pending_tree_(false), | 39 has_pending_tree_(false), |
40 pending_tree_is_ready_for_activation_(false), | 40 pending_tree_is_ready_for_activation_(false), |
41 active_tree_needs_first_draw_(false), | 41 active_tree_needs_first_draw_(false), |
42 draw_if_possible_failed_(false), | 42 draw_if_possible_failed_(false), |
43 did_create_and_initialize_first_output_surface_(false), | 43 did_create_and_initialize_first_output_surface_(false), |
44 smoothness_takes_priority_(false) {} | 44 smoothness_takes_priority_(false), |
| 45 skip_begin_main_frame_to_reduce_latency_(false) {} |
45 | 46 |
46 const char* SchedulerStateMachine::OutputSurfaceStateToString( | 47 const char* SchedulerStateMachine::OutputSurfaceStateToString( |
47 OutputSurfaceState state) { | 48 OutputSurfaceState state) { |
48 switch (state) { | 49 switch (state) { |
49 case OUTPUT_SURFACE_ACTIVE: | 50 case OUTPUT_SURFACE_ACTIVE: |
50 return "OUTPUT_SURFACE_ACTIVE"; | 51 return "OUTPUT_SURFACE_ACTIVE"; |
51 case OUTPUT_SURFACE_LOST: | 52 case OUTPUT_SURFACE_LOST: |
52 return "OUTPUT_SURFACE_LOST"; | 53 return "OUTPUT_SURFACE_LOST"; |
53 case OUTPUT_SURFACE_CREATING: | 54 case OUTPUT_SURFACE_CREATING: |
54 return "OUTPUT_SURFACE_CREATING"; | 55 return "OUTPUT_SURFACE_CREATING"; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); | 253 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); |
253 minor_state->SetBoolean("pending_tree_is_ready_for_activation", | 254 minor_state->SetBoolean("pending_tree_is_ready_for_activation", |
254 pending_tree_is_ready_for_activation_); | 255 pending_tree_is_ready_for_activation_); |
255 minor_state->SetBoolean("active_tree_needs_first_draw", | 256 minor_state->SetBoolean("active_tree_needs_first_draw", |
256 active_tree_needs_first_draw_); | 257 active_tree_needs_first_draw_); |
257 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); | 258 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); |
258 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", | 259 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", |
259 did_create_and_initialize_first_output_surface_); | 260 did_create_and_initialize_first_output_surface_); |
260 minor_state->SetBoolean("smoothness_takes_priority", | 261 minor_state->SetBoolean("smoothness_takes_priority", |
261 smoothness_takes_priority_); | 262 smoothness_takes_priority_); |
| 263 minor_state->SetBoolean("main_thread_is_in_high_latency_mode", |
| 264 MainThreadIsInHighLatencyMode()); |
| 265 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency", |
| 266 skip_begin_main_frame_to_reduce_latency_); |
262 state->Set("minor_state", minor_state.release()); | 267 state->Set("minor_state", minor_state.release()); |
263 | 268 |
264 return state.PassAs<base::Value>(); | 269 return state.PassAs<base::Value>(); |
265 } | 270 } |
266 | 271 |
267 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { | 272 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { |
268 return current_frame_number_ == | 273 return current_frame_number_ == |
269 last_frame_number_begin_main_frame_sent_; | 274 last_frame_number_begin_main_frame_sent_; |
270 } | 275 } |
271 | 276 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 return true; | 483 return true; |
479 | 484 |
480 // After this point, we only start a commit once per frame. | 485 // After this point, we only start a commit once per frame. |
481 if (HasSentBeginMainFrameThisFrame()) | 486 if (HasSentBeginMainFrameThisFrame()) |
482 return false; | 487 return false; |
483 | 488 |
484 // We shouldn't normally accept commits if there isn't an OutputSurface. | 489 // We shouldn't normally accept commits if there isn't an OutputSurface. |
485 if (!HasInitializedOutputSurface()) | 490 if (!HasInitializedOutputSurface()) |
486 return false; | 491 return false; |
487 | 492 |
| 493 if (skip_begin_main_frame_to_reduce_latency_) |
| 494 return false; |
| 495 |
488 return true; | 496 return true; |
489 } | 497 } |
490 | 498 |
491 bool SchedulerStateMachine::ShouldCommit() const { | 499 bool SchedulerStateMachine::ShouldCommit() const { |
492 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; | 500 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; |
493 } | 501 } |
494 | 502 |
495 bool SchedulerStateMachine::ShouldManageTiles() const { | 503 bool SchedulerStateMachine::ShouldManageTiles() const { |
496 // Limiting to once per-frame is not enough, since we only want to | 504 // Limiting to once per-frame is not enough, since we only want to |
497 // manage tiles _after_ draws. Polling for draw triggers and | 505 // manage tiles _after_ draws. Polling for draw triggers and |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 void SchedulerStateMachine::UpdateStateOnManageTiles() { | 757 void SchedulerStateMachine::UpdateStateOnManageTiles() { |
750 needs_manage_tiles_ = false; | 758 needs_manage_tiles_ = false; |
751 } | 759 } |
752 | 760 |
753 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { | 761 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { |
754 DCHECK(!main_thread_needs_layer_textures_); | 762 DCHECK(!main_thread_needs_layer_textures_); |
755 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); | 763 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); |
756 main_thread_needs_layer_textures_ = true; | 764 main_thread_needs_layer_textures_ = true; |
757 } | 765 } |
758 | 766 |
| 767 void SchedulerStateMachine::SetSkipBeginMainFrameToReduceLatency(bool skip) { |
| 768 skip_begin_main_frame_to_reduce_latency_ = skip; |
| 769 } |
| 770 |
759 bool SchedulerStateMachine::BeginImplFrameNeeded() const { | 771 bool SchedulerStateMachine::BeginImplFrameNeeded() const { |
760 // Proactive BeginImplFrames are bad for the synchronous compositor because we | 772 // Proactive BeginImplFrames are bad for the synchronous compositor because we |
761 // have to draw when we get the BeginImplFrame and could end up drawing many | 773 // have to draw when we get the BeginImplFrame and could end up drawing many |
762 // duplicate frames if our new frame isn't ready in time. | 774 // duplicate frames if our new frame isn't ready in time. |
763 // To poll for state with the synchronous compositor without having to draw, | 775 // To poll for state with the synchronous compositor without having to draw, |
764 // we rely on ShouldPollForAnticipatedDrawTriggers instead. | 776 // we rely on ShouldPollForAnticipatedDrawTriggers instead. |
765 if (!SupportsProactiveBeginImplFrame()) | 777 if (!SupportsProactiveBeginImplFrame()) |
766 return BeginImplFrameNeededToDraw(); | 778 return BeginImplFrameNeededToDraw(); |
767 | 779 |
768 return BeginImplFrameNeededToDraw() || | 780 return BeginImplFrameNeededToDraw() || |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) | 924 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) |
913 return true; | 925 return true; |
914 | 926 |
915 // Prioritize impl-thread draws in smoothness mode. | 927 // Prioritize impl-thread draws in smoothness mode. |
916 if (smoothness_takes_priority_) | 928 if (smoothness_takes_priority_) |
917 return true; | 929 return true; |
918 | 930 |
919 return false; | 931 return false; |
920 } | 932 } |
921 | 933 |
| 934 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const { |
| 935 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main |
| 936 // thread is in a low latency mode. |
| 937 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ && |
| 938 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING || |
| 939 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)) |
| 940 return false; |
| 941 |
| 942 // If there's a commit in progress it must either be from the previous frame |
| 943 // or it started after the impl thread's deadline. In either case the main |
| 944 // thread is in high latency mode. |
| 945 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || |
| 946 commit_state_ == COMMIT_STATE_READY_TO_COMMIT) |
| 947 return true; |
| 948 |
| 949 // Similarly, if there's a pending tree the main thread is in high latency |
| 950 // mode, because either |
| 951 // it's from the previous frame |
| 952 // or |
| 953 // we're currently drawing the active tree and the pending tree will thus |
| 954 // only be drawn in the next frame. |
| 955 if (has_pending_tree_) |
| 956 return true; |
| 957 |
| 958 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { |
| 959 // Even if there's a new active tree to draw at the deadline or we've just |
| 960 // drawn it, it may have been triggered by a previous BeginImplFrame, in |
| 961 // which case the main thread is in a high latency mode. |
| 962 return (active_tree_needs_first_draw_ || |
| 963 last_frame_number_swap_performed_ == current_frame_number_) && |
| 964 last_frame_number_begin_main_frame_sent_ != current_frame_number_; |
| 965 } |
| 966 |
| 967 // If the active tree needs its first draw in any other state, we know the |
| 968 // main thread is in a high latency mode. |
| 969 return active_tree_needs_first_draw_; |
| 970 } |
| 971 |
922 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { | 972 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { |
923 current_frame_number_++; | 973 current_frame_number_++; |
924 inside_poll_for_anticipated_draw_triggers_ = true; | 974 inside_poll_for_anticipated_draw_triggers_ = true; |
925 } | 975 } |
926 | 976 |
927 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { | 977 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { |
928 inside_poll_for_anticipated_draw_triggers_ = false; | 978 inside_poll_for_anticipated_draw_triggers_ = false; |
929 } | 979 } |
930 | 980 |
931 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } | 981 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 case OUTPUT_SURFACE_ACTIVE: | 1103 case OUTPUT_SURFACE_ACTIVE: |
1054 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1104 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
1055 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1105 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
1056 return true; | 1106 return true; |
1057 } | 1107 } |
1058 NOTREACHED(); | 1108 NOTREACHED(); |
1059 return false; | 1109 return false; |
1060 } | 1110 } |
1061 | 1111 |
1062 } // namespace cc | 1112 } // namespace cc |
OLD | NEW |