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