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 |