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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 major_state->SetString( | 198 major_state->SetString( |
199 "forced_redraw_state", | 199 "forced_redraw_state", |
200 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); | 200 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); |
201 major_state->SetString("readback_state", | 201 major_state->SetString("readback_state", |
202 SynchronousReadbackStateToString(readback_state_)); | 202 SynchronousReadbackStateToString(readback_state_)); |
203 state->Set("major_state", major_state.release()); | 203 state->Set("major_state", major_state.release()); |
204 | 204 |
205 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); | 205 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); |
206 base::TimeTicks now = gfx::FrameTime::Now(); | 206 base::TimeTicks now = gfx::FrameTime::Now(); |
207 timestamps_state->SetDouble( | 207 timestamps_state->SetDouble( |
208 "0_interval", | 208 "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); |
209 last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); | |
210 timestamps_state->SetDouble( | 209 timestamps_state->SetDouble( |
211 "1_now_to_deadline", | 210 "1_now_to_deadline", |
212 (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); | 211 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); |
213 timestamps_state->SetDouble( | 212 timestamps_state->SetDouble( |
214 "2_frame_time_to_now", | 213 "2_frame_time_to_now", |
215 (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() / | 214 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L); |
216 1000.0L); | |
217 timestamps_state->SetDouble( | 215 timestamps_state->SetDouble( |
218 "3_frame_time_to_deadline", | 216 "3_frame_time_to_deadline", |
219 (last_begin_impl_frame_args_.deadline - | 217 (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time) |
220 last_begin_impl_frame_args_.frame_time).InMicroseconds() / | 218 .InMicroseconds() / |
221 1000.0L); | 219 1000.0L); |
222 timestamps_state->SetDouble( | 220 timestamps_state->SetDouble( |
223 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); | 221 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); |
224 timestamps_state->SetDouble( | 222 timestamps_state->SetDouble( |
225 "5_frame_time", | 223 "5_frame_time", |
226 (last_begin_impl_frame_args_.frame_time - base::TimeTicks()) | 224 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / |
227 .InMicroseconds() / | |
228 1000.0L); | 225 1000.0L); |
229 timestamps_state->SetDouble( | 226 timestamps_state->SetDouble( |
230 "6_deadline", | 227 "6_deadline", |
231 (last_begin_impl_frame_args_.deadline - base::TimeTicks()) | 228 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / |
232 .InMicroseconds() / | |
233 1000.0L); | 229 1000.0L); |
234 state->Set("major_timestamps_in_ms", timestamps_state.release()); | 230 state->Set("major_timestamps_in_ms", timestamps_state.release()); |
235 | 231 |
236 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); | 232 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); |
237 minor_state->SetInteger("commit_count", commit_count_); | 233 minor_state->SetInteger("commit_count", commit_count_); |
238 minor_state->SetInteger("current_frame_number", current_frame_number_); | 234 minor_state->SetInteger("current_frame_number", current_frame_number_); |
239 | 235 |
240 minor_state->SetInteger("last_frame_number_swap_performed", | 236 minor_state->SetInteger("last_frame_number_swap_performed", |
241 last_frame_number_swap_performed_); | 237 last_frame_number_swap_performed_); |
242 minor_state->SetInteger( | 238 minor_state->SetInteger( |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 // We want to start the first commit after we get a new output surface ASAP. | 484 // We want to start the first commit after we get a new output surface ASAP. |
489 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) | 485 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) |
490 return true; | 486 return true; |
491 | 487 |
492 // We should not send BeginMainFrame while we are in | 488 // We should not send BeginMainFrame while we are in |
493 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new | 489 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new |
494 // user input arriving soon. | 490 // user input arriving soon. |
495 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main | 491 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main |
496 // thread isn't consuming user input. | 492 // thread isn't consuming user input. |
497 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && | 493 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && |
498 BeginImplFrameNeeded()) | 494 BeginFrameNeeded()) |
499 return false; | 495 return false; |
500 | 496 |
501 // We need a new commit for the forced redraw. This honors the | 497 // We need a new commit for the forced redraw. This honors the |
502 // single commit per interval because the result will be swapped to screen. | 498 // single commit per interval because the result will be swapped to screen. |
503 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) | 499 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) |
504 return true; | 500 return true; |
505 | 501 |
506 // After this point, we only start a commit once per frame. | 502 // After this point, we only start a commit once per frame. |
507 if (HasSentBeginMainFrameThisFrame()) | 503 if (HasSentBeginMainFrameThisFrame()) |
508 return false; | 504 return false; |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { | 819 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { |
824 DCHECK(!main_thread_needs_layer_textures_); | 820 DCHECK(!main_thread_needs_layer_textures_); |
825 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); | 821 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); |
826 main_thread_needs_layer_textures_ = true; | 822 main_thread_needs_layer_textures_ = true; |
827 } | 823 } |
828 | 824 |
829 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() { | 825 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() { |
830 skip_next_begin_main_frame_to_reduce_latency_ = true; | 826 skip_next_begin_main_frame_to_reduce_latency_ = true; |
831 } | 827 } |
832 | 828 |
833 bool SchedulerStateMachine::BeginImplFrameNeeded() const { | 829 bool SchedulerStateMachine::BeginFrameNeeded() const { |
834 // Proactive BeginImplFrames are bad for the synchronous compositor because we | 830 // Proactive BeginFrames are bad for the synchronous compositor because we |
835 // have to draw when we get the BeginImplFrame and could end up drawing many | 831 // have to draw when we get the BeginFrame and could end up drawing many |
836 // duplicate frames if our new frame isn't ready in time. | 832 // duplicate frames if our new frame isn't ready in time. |
837 // To poll for state with the synchronous compositor without having to draw, | 833 // To poll for state with the synchronous compositor without having to draw, |
838 // we rely on ShouldPollForAnticipatedDrawTriggers instead. | 834 // we rely on ShouldPollForAnticipatedDrawTriggers instead. |
839 if (!SupportsProactiveBeginImplFrame()) | 835 if (!SupportsProactiveBeginFrame()) |
840 return BeginImplFrameNeededToDraw(); | 836 return BeginFrameNeededToDraw(); |
841 | 837 |
842 return BeginImplFrameNeededToDraw() || | 838 return BeginFrameNeededToDraw() || ProactiveBeginFrameWanted(); |
843 ProactiveBeginImplFrameWanted(); | |
844 } | 839 } |
845 | 840 |
846 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { | 841 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { |
847 // ShouldPollForAnticipatedDrawTriggers is what we use in place of | 842 // ShouldPollForAnticipatedDrawTriggers is what we use in place of |
848 // ProactiveBeginImplFrameWanted when we are using the synchronous | 843 // ProactiveBeginFrameWanted when we are using the synchronous |
849 // compositor. | 844 // compositor. |
850 if (!SupportsProactiveBeginImplFrame()) { | 845 if (!SupportsProactiveBeginFrame()) { |
851 return !BeginImplFrameNeededToDraw() && | 846 return !BeginFrameNeededToDraw() && ProactiveBeginFrameWanted(); |
852 ProactiveBeginImplFrameWanted(); | |
853 } | 847 } |
854 | 848 |
855 // Non synchronous compositors should rely on | 849 // Non synchronous compositors should rely on |
856 // ProactiveBeginImplFrameWanted to poll for state instead. | 850 // ProactiveBeginFrameWanted to poll for state instead. |
857 return false; | 851 return false; |
858 } | 852 } |
859 | 853 |
860 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const { | 854 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const { |
861 // Both the synchronous compositor and disabled vsync settings | 855 // Both the synchronous compositor and disabled vsync settings |
862 // make it undesirable to proactively request BeginImplFrames. | 856 // make it undesirable to proactively request BeginImplFrames. |
863 // If this is true, the scheduler should poll. | 857 // If this is true, the scheduler should poll. |
864 return !settings_.using_synchronous_renderer_compositor && | 858 return !settings_.using_synchronous_renderer_compositor && |
865 settings_.throttle_frame_production; | 859 settings_.throttle_frame_production; |
866 } | 860 } |
867 | 861 |
868 // These are the cases where we definitely (or almost definitely) have a | 862 // These are the cases where we definitely (or almost definitely) have a |
869 // new frame to draw and can draw. | 863 // new frame to draw and can draw. |
870 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const { | 864 bool SchedulerStateMachine::BeginFrameNeededToDraw() const { |
871 // The output surface is the provider of BeginImplFrames, so we are not going | 865 // The output surface is the provider of BeginImplFrames, so we are not going |
872 // to get them even if we ask for them. | 866 // to get them even if we ask for them. |
873 if (!HasInitializedOutputSurface()) | 867 if (!HasInitializedOutputSurface()) |
874 return false; | 868 return false; |
875 | 869 |
876 // If we can't draw, don't tick until we are notified that we can draw again. | 870 // If we can't draw, don't tick until we are notified that we can draw again. |
877 if (!can_draw_) | 871 if (!can_draw_) |
878 return false; | 872 return false; |
879 | 873 |
880 // The forced draw respects our normal draw scheduling, so we need to | 874 // The forced draw respects our normal draw scheduling, so we need to |
(...skipping 10 matching lines...) Expand all Loading... |
891 // additional visible tiles. | 885 // additional visible tiles. |
892 if (swap_used_incomplete_tile_) | 886 if (swap_used_incomplete_tile_) |
893 return true; | 887 return true; |
894 | 888 |
895 return needs_redraw_; | 889 return needs_redraw_; |
896 } | 890 } |
897 | 891 |
898 // These are cases where we are very likely to draw soon, but might not | 892 // These are cases where we are very likely to draw soon, but might not |
899 // actually have a new frame to draw when we receive the next BeginImplFrame. | 893 // actually have a new frame to draw when we receive the next BeginImplFrame. |
900 // Proactively requesting the BeginImplFrame helps hide the round trip latency | 894 // Proactively requesting the BeginImplFrame helps hide the round trip latency |
901 // of the SetNeedsBeginImplFrame request that has to go to the Browser. | 895 // of the SetNeedsBeginFrame request that has to go to the Browser. |
902 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const { | 896 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const { |
903 // The output surface is the provider of BeginImplFrames, | 897 // The output surface is the provider of BeginImplFrames, |
904 // so we are not going to get them even if we ask for them. | 898 // so we are not going to get them even if we ask for them. |
905 if (!HasInitializedOutputSurface()) | 899 if (!HasInitializedOutputSurface()) |
906 return false; | 900 return false; |
907 | 901 |
908 // Do not be proactive when invisible. | 902 // Do not be proactive when invisible. |
909 if (!visible_) | 903 if (!visible_) |
910 return false; | 904 return false; |
911 | 905 |
912 // We should proactively request a BeginImplFrame if a commit is pending | 906 // We should proactively request a BeginImplFrame if a commit is pending |
913 // because we will want to draw if the commit completes quickly. | 907 // because we will want to draw if the commit completes quickly. |
914 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) | 908 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) |
915 return true; | 909 return true; |
916 | 910 |
917 // If the pending tree activates quickly, we'll want a BeginImplFrame soon | 911 // If the pending tree activates quickly, we'll want a BeginImplFrame soon |
918 // to draw the new active tree. | 912 // to draw the new active tree. |
919 if (has_pending_tree_) | 913 if (has_pending_tree_) |
920 return true; | 914 return true; |
921 | 915 |
922 // Changing priorities may allow us to activate (given the new priorities), | 916 // Changing priorities may allow us to activate (given the new priorities), |
923 // which may result in a new frame. | 917 // which may result in a new frame. |
924 if (needs_manage_tiles_) | 918 if (needs_manage_tiles_) |
925 return true; | 919 return true; |
926 | 920 |
927 // If we just swapped, it's likely that we are going to produce another | 921 // If we just swapped, it's likely that we are going to produce another |
928 // frame soon. This helps avoid negative glitches in our | 922 // frame soon. This helps avoid negative glitches in our |
929 // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame | 923 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame |
930 // provider and get sampled at an inopportune time, delaying the next | 924 // provider and get sampled at an inopportune time, delaying the next |
931 // BeginImplFrame. | 925 // BeginImplFrame. |
932 if (last_frame_number_swap_performed_ == current_frame_number_) | 926 if (last_frame_number_swap_performed_ == current_frame_number_) |
933 return true; | 927 return true; |
934 | 928 |
935 return false; | 929 return false; |
936 } | 930 } |
937 | 931 |
938 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { | 932 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { |
939 AdvanceCurrentFrameNumber(); | 933 AdvanceCurrentFrameNumber(); |
940 last_begin_impl_frame_args_ = args; | 934 begin_impl_frame_args_ = args; |
941 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); | 935 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); |
942 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; | 936 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; |
943 } | 937 } |
944 | 938 |
945 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 939 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
946 DCHECK_EQ(begin_impl_frame_state_, | 940 DCHECK_EQ(begin_impl_frame_state_, |
947 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) | 941 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) |
948 << *AsValue(); | 942 << *AsValue(); |
949 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 943 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
950 } | 944 } |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 case OUTPUT_SURFACE_ACTIVE: | 1216 case OUTPUT_SURFACE_ACTIVE: |
1223 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1217 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
1224 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1218 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
1225 return true; | 1219 return true; |
1226 } | 1220 } |
1227 NOTREACHED(); | 1221 NOTREACHED(); |
1228 return false; | 1222 return false; |
1229 } | 1223 } |
1230 | 1224 |
1231 } // namespace cc | 1225 } // namespace cc |
OLD | NEW |