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