| 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 |