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