| 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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 major_state->SetString( | 179 major_state->SetString( |
| 180 "forced_redraw_state", | 180 "forced_redraw_state", |
| 181 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); | 181 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); |
| 182 major_state->SetString("readback_state", | 182 major_state->SetString("readback_state", |
| 183 SynchronousReadbackStateToString(readback_state_)); | 183 SynchronousReadbackStateToString(readback_state_)); |
| 184 state->Set("major_state", major_state.release()); | 184 state->Set("major_state", major_state.release()); |
| 185 | 185 |
| 186 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); | 186 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); |
| 187 base::TimeTicks now = gfx::FrameTime::Now(); | 187 base::TimeTicks now = gfx::FrameTime::Now(); |
| 188 timestamps_state->SetDouble( | 188 timestamps_state->SetDouble( |
| 189 "0_interval", | 189 "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); |
| 190 last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); | |
| 191 timestamps_state->SetDouble( | 190 timestamps_state->SetDouble( |
| 192 "1_now_to_deadline", | 191 "1_now_to_deadline", |
| 193 (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); | 192 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); |
| 194 timestamps_state->SetDouble( | 193 timestamps_state->SetDouble( |
| 195 "2_frame_time_to_now", | 194 "2_frame_time_to_now", |
| 196 (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() / | 195 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L); |
| 197 1000.0L); | |
| 198 timestamps_state->SetDouble( | 196 timestamps_state->SetDouble( |
| 199 "3_frame_time_to_deadline", | 197 "3_frame_time_to_deadline", |
| 200 (last_begin_impl_frame_args_.deadline - | 198 (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time) |
| 201 last_begin_impl_frame_args_.frame_time).InMicroseconds() / | 199 .InMicroseconds() / |
| 202 1000.0L); | 200 1000.0L); |
| 203 timestamps_state->SetDouble( | 201 timestamps_state->SetDouble( |
| 204 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); | 202 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 205 timestamps_state->SetDouble( | 203 timestamps_state->SetDouble( |
| 206 "5_frame_time", | 204 "5_frame_time", |
| 207 (last_begin_impl_frame_args_.frame_time - base::TimeTicks()) | 205 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / |
| 208 .InMicroseconds() / | |
| 209 1000.0L); | 206 1000.0L); |
| 210 timestamps_state->SetDouble( | 207 timestamps_state->SetDouble( |
| 211 "6_deadline", | 208 "6_deadline", |
| 212 (last_begin_impl_frame_args_.deadline - base::TimeTicks()) | 209 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / |
| 213 .InMicroseconds() / | |
| 214 1000.0L); | 210 1000.0L); |
| 215 state->Set("major_timestamps_in_ms", timestamps_state.release()); | 211 state->Set("major_timestamps_in_ms", timestamps_state.release()); |
| 216 | 212 |
| 217 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); | 213 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); |
| 218 minor_state->SetInteger("commit_count", commit_count_); | 214 minor_state->SetInteger("commit_count", commit_count_); |
| 219 minor_state->SetInteger("current_frame_number", current_frame_number_); | 215 minor_state->SetInteger("current_frame_number", current_frame_number_); |
| 220 | 216 |
| 221 minor_state->SetInteger("last_frame_number_swap_performed", | 217 minor_state->SetInteger("last_frame_number_swap_performed", |
| 222 last_frame_number_swap_performed_); | 218 last_frame_number_swap_performed_); |
| 223 minor_state->SetInteger( | 219 minor_state->SetInteger( |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // We want to start the first commit after we get a new output surface ASAP. | 449 // We want to start the first commit after we get a new output surface ASAP. |
| 454 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) | 450 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) |
| 455 return true; | 451 return true; |
| 456 | 452 |
| 457 // We should not send BeginMainFrame while we are in | 453 // We should not send BeginMainFrame while we are in |
| 458 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new | 454 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new |
| 459 // user input arriving soon. | 455 // user input arriving soon. |
| 460 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main | 456 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main |
| 461 // thread isn't consuming user input. | 457 // thread isn't consuming user input. |
| 462 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && | 458 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && |
| 463 BeginImplFrameNeeded()) | 459 BeginFrameNeeded()) |
| 464 return false; | 460 return false; |
| 465 | 461 |
| 466 // We need a new commit for the forced redraw. This honors the | 462 // We need a new commit for the forced redraw. This honors the |
| 467 // single commit per interval because the result will be swapped to screen. | 463 // single commit per interval because the result will be swapped to screen. |
| 468 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) | 464 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) |
| 469 return true; | 465 return true; |
| 470 | 466 |
| 471 // After this point, we only start a commit once per frame. | 467 // After this point, we only start a commit once per frame. |
| 472 if (HasSentBeginMainFrameThisFrame()) | 468 if (HasSentBeginMainFrameThisFrame()) |
| 473 return false; | 469 return false; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 756 } |
| 761 | 757 |
| 762 void SchedulerStateMachine::UpdateStateOnManageTiles() { | 758 void SchedulerStateMachine::UpdateStateOnManageTiles() { |
| 763 needs_manage_tiles_ = false; | 759 needs_manage_tiles_ = false; |
| 764 } | 760 } |
| 765 | 761 |
| 766 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() { | 762 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() { |
| 767 skip_next_begin_main_frame_to_reduce_latency_ = true; | 763 skip_next_begin_main_frame_to_reduce_latency_ = true; |
| 768 } | 764 } |
| 769 | 765 |
| 770 bool SchedulerStateMachine::BeginImplFrameNeeded() const { | 766 bool SchedulerStateMachine::BeginFrameNeeded() const { |
| 771 // Proactive BeginImplFrames are bad for the synchronous compositor because we | 767 // Proactive BeginFrames are bad for the synchronous compositor because we |
| 772 // have to draw when we get the BeginImplFrame and could end up drawing many | 768 // have to draw when we get the BeginFrame and could end up drawing many |
| 773 // duplicate frames if our new frame isn't ready in time. | 769 // duplicate frames if our new frame isn't ready in time. |
| 774 // To poll for state with the synchronous compositor without having to draw, | 770 // To poll for state with the synchronous compositor without having to draw, |
| 775 // we rely on ShouldPollForAnticipatedDrawTriggers instead. | 771 // we rely on ShouldPollForAnticipatedDrawTriggers instead. |
| 776 if (!SupportsProactiveBeginImplFrame()) | 772 if (!SupportsProactiveBeginFrame()) |
| 777 return BeginImplFrameNeededToDraw(); | 773 return BeginFrameNeededToDraw(); |
| 778 | 774 |
| 779 return BeginImplFrameNeededToDraw() || | 775 return BeginFrameNeededToDraw() || ProactiveBeginFrameWanted(); |
| 780 ProactiveBeginImplFrameWanted(); | |
| 781 } | 776 } |
| 782 | 777 |
| 783 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { | 778 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { |
| 784 // ShouldPollForAnticipatedDrawTriggers is what we use in place of | 779 // ShouldPollForAnticipatedDrawTriggers is what we use in place of |
| 785 // ProactiveBeginImplFrameWanted when we are using the synchronous | 780 // ProactiveBeginFrameWanted when we are using the synchronous |
| 786 // compositor. | 781 // compositor. |
| 787 if (!SupportsProactiveBeginImplFrame()) { | 782 if (!SupportsProactiveBeginFrame()) { |
| 788 return !BeginImplFrameNeededToDraw() && | 783 return !BeginFrameNeededToDraw() && ProactiveBeginFrameWanted(); |
| 789 ProactiveBeginImplFrameWanted(); | |
| 790 } | 784 } |
| 791 | 785 |
| 792 // Non synchronous compositors should rely on | 786 // Non synchronous compositors should rely on |
| 793 // ProactiveBeginImplFrameWanted to poll for state instead. | 787 // ProactiveBeginFrameWanted to poll for state instead. |
| 794 return false; | 788 return false; |
| 795 } | 789 } |
| 796 | 790 |
| 797 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const { | 791 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const { |
| 798 // Both the synchronous compositor and disabled vsync settings | 792 // Both the synchronous compositor and disabled vsync settings |
| 799 // make it undesirable to proactively request BeginImplFrames. | 793 // make it undesirable to proactively request BeginImplFrames. |
| 800 // If this is true, the scheduler should poll. | 794 // If this is true, the scheduler should poll. |
| 801 return !settings_.using_synchronous_renderer_compositor && | 795 return !settings_.using_synchronous_renderer_compositor && |
| 802 settings_.throttle_frame_production; | 796 settings_.throttle_frame_production; |
| 803 } | 797 } |
| 804 | 798 |
| 805 // These are the cases where we definitely (or almost definitely) have a | 799 // These are the cases where we definitely (or almost definitely) have a |
| 806 // new frame to draw and can draw. | 800 // new frame to draw and can draw. |
| 807 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const { | 801 bool SchedulerStateMachine::BeginFrameNeededToDraw() const { |
| 808 // The output surface is the provider of BeginImplFrames, so we are not going | 802 // The output surface is the provider of BeginImplFrames, so we are not going |
| 809 // to get them even if we ask for them. | 803 // to get them even if we ask for them. |
| 810 if (!HasInitializedOutputSurface()) | 804 if (!HasInitializedOutputSurface()) |
| 811 return false; | 805 return false; |
| 812 | 806 |
| 813 // If we can't draw, don't tick until we are notified that we can draw again. | 807 // If we can't draw, don't tick until we are notified that we can draw again. |
| 814 if (!can_draw_) | 808 if (!can_draw_) |
| 815 return false; | 809 return false; |
| 816 | 810 |
| 817 // The forced draw respects our normal draw scheduling, so we need to | 811 // The forced draw respects our normal draw scheduling, so we need to |
| (...skipping 10 matching lines...) Expand all Loading... |
| 828 // additional visible tiles. | 822 // additional visible tiles. |
| 829 if (swap_used_incomplete_tile_) | 823 if (swap_used_incomplete_tile_) |
| 830 return true; | 824 return true; |
| 831 | 825 |
| 832 return needs_redraw_; | 826 return needs_redraw_; |
| 833 } | 827 } |
| 834 | 828 |
| 835 // These are cases where we are very likely to draw soon, but might not | 829 // These are cases where we are very likely to draw soon, but might not |
| 836 // actually have a new frame to draw when we receive the next BeginImplFrame. | 830 // actually have a new frame to draw when we receive the next BeginImplFrame. |
| 837 // Proactively requesting the BeginImplFrame helps hide the round trip latency | 831 // Proactively requesting the BeginImplFrame helps hide the round trip latency |
| 838 // of the SetNeedsBeginImplFrame request that has to go to the Browser. | 832 // of the SetNeedsBeginFrame request that has to go to the Browser. |
| 839 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const { | 833 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const { |
| 840 // The output surface is the provider of BeginImplFrames, | 834 // The output surface is the provider of BeginImplFrames, |
| 841 // so we are not going to get them even if we ask for them. | 835 // so we are not going to get them even if we ask for them. |
| 842 if (!HasInitializedOutputSurface()) | 836 if (!HasInitializedOutputSurface()) |
| 843 return false; | 837 return false; |
| 844 | 838 |
| 845 // Do not be proactive when invisible. | 839 // Do not be proactive when invisible. |
| 846 if (!visible_) | 840 if (!visible_) |
| 847 return false; | 841 return false; |
| 848 | 842 |
| 849 // We should proactively request a BeginImplFrame if a commit is pending | 843 // We should proactively request a BeginImplFrame if a commit is pending |
| 850 // because we will want to draw if the commit completes quickly. | 844 // because we will want to draw if the commit completes quickly. |
| 851 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) | 845 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) |
| 852 return true; | 846 return true; |
| 853 | 847 |
| 854 // If the pending tree activates quickly, we'll want a BeginImplFrame soon | 848 // If the pending tree activates quickly, we'll want a BeginImplFrame soon |
| 855 // to draw the new active tree. | 849 // to draw the new active tree. |
| 856 if (has_pending_tree_) | 850 if (has_pending_tree_) |
| 857 return true; | 851 return true; |
| 858 | 852 |
| 859 // Changing priorities may allow us to activate (given the new priorities), | 853 // Changing priorities may allow us to activate (given the new priorities), |
| 860 // which may result in a new frame. | 854 // which may result in a new frame. |
| 861 if (needs_manage_tiles_) | 855 if (needs_manage_tiles_) |
| 862 return true; | 856 return true; |
| 863 | 857 |
| 864 // If we just swapped, it's likely that we are going to produce another | 858 // If we just swapped, it's likely that we are going to produce another |
| 865 // frame soon. This helps avoid negative glitches in our | 859 // frame soon. This helps avoid negative glitches in our |
| 866 // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame | 860 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame |
| 867 // provider and get sampled at an inopportune time, delaying the next | 861 // provider and get sampled at an inopportune time, delaying the next |
| 868 // BeginImplFrame. | 862 // BeginImplFrame. |
| 869 if (last_frame_number_swap_performed_ == current_frame_number_) | 863 if (last_frame_number_swap_performed_ == current_frame_number_) |
| 870 return true; | 864 return true; |
| 871 | 865 |
| 872 return false; | 866 return false; |
| 873 } | 867 } |
| 874 | 868 |
| 875 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { | 869 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { |
| 876 AdvanceCurrentFrameNumber(); | 870 AdvanceCurrentFrameNumber(); |
| 877 last_begin_impl_frame_args_ = args; | 871 begin_impl_frame_args_ = args; |
| 878 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); | 872 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); |
| 879 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; | 873 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; |
| 880 } | 874 } |
| 881 | 875 |
| 882 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 876 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
| 883 DCHECK_EQ(begin_impl_frame_state_, | 877 DCHECK_EQ(begin_impl_frame_state_, |
| 884 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) | 878 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) |
| 885 << *AsValue(); | 879 << *AsValue(); |
| 886 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 880 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
| 887 } | 881 } |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 case OUTPUT_SURFACE_ACTIVE: | 1153 case OUTPUT_SURFACE_ACTIVE: |
| 1160 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: | 1154 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: |
| 1161 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: | 1155 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: |
| 1162 return true; | 1156 return true; |
| 1163 } | 1157 } |
| 1164 NOTREACHED(); | 1158 NOTREACHED(); |
| 1165 return false; | 1159 return false; |
| 1166 } | 1160 } |
| 1167 | 1161 |
| 1168 } // namespace cc | 1162 } // namespace cc |
| OLD | NEW |