| 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/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 scroll_handler_state_( | 53 scroll_handler_state_( |
| 54 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER), | 54 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER), |
| 55 critical_begin_main_frame_to_activate_is_fast_(true), | 55 critical_begin_main_frame_to_activate_is_fast_(true), |
| 56 main_thread_missed_last_deadline_(false), | 56 main_thread_missed_last_deadline_(false), |
| 57 skip_next_begin_main_frame_to_reduce_latency_(false), | 57 skip_next_begin_main_frame_to_reduce_latency_(false), |
| 58 defer_commits_(false), | 58 defer_commits_(false), |
| 59 video_needs_begin_frames_(false), | 59 video_needs_begin_frames_(false), |
| 60 last_commit_had_no_updates_(false), | 60 last_commit_had_no_updates_(false), |
| 61 wait_for_ready_to_draw_(false), | 61 wait_for_ready_to_draw_(false), |
| 62 did_draw_in_last_frame_(false), | 62 did_draw_in_last_frame_(false), |
| 63 did_submit_in_last_frame_(false) {} | 63 did_submit_in_last_frame_(false), |
| 64 begin_frame_allows_latency_optimizations_(true) {} |
| 64 | 65 |
| 65 const char* SchedulerStateMachine::CompositorFrameSinkStateToString( | 66 const char* SchedulerStateMachine::CompositorFrameSinkStateToString( |
| 66 CompositorFrameSinkState state) { | 67 CompositorFrameSinkState state) { |
| 67 switch (state) { | 68 switch (state) { |
| 68 case COMPOSITOR_FRAME_SINK_NONE: | 69 case COMPOSITOR_FRAME_SINK_NONE: |
| 69 return "COMPOSITOR_FRAME_SINK_NONE"; | 70 return "COMPOSITOR_FRAME_SINK_NONE"; |
| 70 case COMPOSITOR_FRAME_SINK_ACTIVE: | 71 case COMPOSITOR_FRAME_SINK_ACTIVE: |
| 71 return "COMPOSITOR_FRAME_SINK_ACTIVE"; | 72 return "COMPOSITOR_FRAME_SINK_ACTIVE"; |
| 72 case COMPOSITOR_FRAME_SINK_CREATING: | 73 case COMPOSITOR_FRAME_SINK_CREATING: |
| 73 return "COMPOSITOR_FRAME_SINK_CREATING"; | 74 return "COMPOSITOR_FRAME_SINK_CREATING"; |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 if (wait_for_ready_to_draw_) { | 368 if (wait_for_ready_to_draw_) { |
| 368 DCHECK(settings_.commit_to_active_tree); | 369 DCHECK(settings_.commit_to_active_tree); |
| 369 return false; | 370 return false; |
| 370 } | 371 } |
| 371 | 372 |
| 372 // Browser compositor commit steals any resources submitted in draw. Therefore | 373 // Browser compositor commit steals any resources submitted in draw. Therefore |
| 373 // drawing while a commit is pending is wasteful. | 374 // drawing while a commit is pending is wasteful. |
| 374 if (settings_.commit_to_active_tree && CommitPending()) | 375 if (settings_.commit_to_active_tree && CommitPending()) |
| 375 return false; | 376 return false; |
| 376 | 377 |
| 377 // Only handle forced redraws due to timeouts on the regular deadline. | 378 // Only handle forced redraws due to timeouts on the regular deadline and |
| 378 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 379 // (temporarily) for |!begin_frame_allows_latency_optimizations_|. |
| 380 if (ShouldForceDraw()) |
| 379 return true; | 381 return true; |
| 380 | 382 |
| 381 return needs_redraw_; | 383 return needs_redraw_; |
| 382 } | 384 } |
| 383 | 385 |
| 386 bool SchedulerStateMachine::ShouldForceDraw() const { |
| 387 // Browser compositor doesn't support forced draws. |
| 388 if (settings_.commit_to_active_tree) |
| 389 return false; |
| 390 |
| 391 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
| 392 return true; |
| 393 |
| 394 // |!begin_frame_allows_latency_optimizations_| is typically used with long |
| 395 // deadlines, for which we depend on a timely acknowledgment of the BeginFrame |
| 396 // in the browser. Since we currently don't have a unified acknowledgment for |
| 397 // unsuccessful draws, we force a draw and wait for surface damage in the |
| 398 // browser's DisplayScheduler. |
| 399 // TODO(eseckler): Remove once we have unified BeginFrame acknowledgments. |
| 400 if (!begin_frame_allows_latency_optimizations_) |
| 401 return true; |
| 402 |
| 403 return false; |
| 404 } |
| 405 |
| 384 bool SchedulerStateMachine::ShouldActivatePendingTree() const { | 406 bool SchedulerStateMachine::ShouldActivatePendingTree() const { |
| 385 // There is nothing to activate. | 407 // There is nothing to activate. |
| 386 if (!has_pending_tree_) | 408 if (!has_pending_tree_) |
| 387 return false; | 409 return false; |
| 388 | 410 |
| 389 // We should not activate a second tree before drawing the first one. | 411 // We should not activate a second tree before drawing the first one. |
| 390 // Even if we need to force activation of the pending tree, we should abort | 412 // Even if we need to force activation of the pending tree, we should abort |
| 391 // drawing the active tree first. | 413 // drawing the active tree first. |
| 392 if (active_tree_needs_first_draw_) | 414 if (active_tree_needs_first_draw_) |
| 393 return false; | 415 return false; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 } | 569 } |
| 548 | 570 |
| 549 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { | 571 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
| 550 if (ShouldActivatePendingTree()) | 572 if (ShouldActivatePendingTree()) |
| 551 return ACTION_ACTIVATE_SYNC_TREE; | 573 return ACTION_ACTIVATE_SYNC_TREE; |
| 552 if (ShouldCommit()) | 574 if (ShouldCommit()) |
| 553 return ACTION_COMMIT; | 575 return ACTION_COMMIT; |
| 554 if (ShouldDraw()) { | 576 if (ShouldDraw()) { |
| 555 if (PendingDrawsShouldBeAborted()) | 577 if (PendingDrawsShouldBeAborted()) |
| 556 return ACTION_DRAW_ABORT; | 578 return ACTION_DRAW_ABORT; |
| 557 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 579 else if (ShouldForceDraw()) |
| 558 return ACTION_DRAW_FORCED; | 580 return ACTION_DRAW_FORCED; |
| 559 else | 581 else |
| 560 return ACTION_DRAW_IF_POSSIBLE; | 582 return ACTION_DRAW_IF_POSSIBLE; |
| 561 } | 583 } |
| 562 if (ShouldPrepareTiles()) | 584 if (ShouldPrepareTiles()) |
| 563 return ACTION_PREPARE_TILES; | 585 return ACTION_PREPARE_TILES; |
| 564 if (ShouldSendBeginMainFrame()) | 586 if (ShouldSendBeginMainFrame()) |
| 565 return ACTION_SEND_BEGIN_MAIN_FRAME; | 587 return ACTION_SEND_BEGIN_MAIN_FRAME; |
| 566 if (ShouldInvalidateCompositorFrameSink()) | 588 if (ShouldInvalidateCompositorFrameSink()) |
| 567 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; | 589 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 | 782 |
| 761 void SchedulerStateMachine::SetVideoNeedsBeginFrames( | 783 void SchedulerStateMachine::SetVideoNeedsBeginFrames( |
| 762 bool video_needs_begin_frames) { | 784 bool video_needs_begin_frames) { |
| 763 video_needs_begin_frames_ = video_needs_begin_frames; | 785 video_needs_begin_frames_ = video_needs_begin_frames; |
| 764 } | 786 } |
| 765 | 787 |
| 766 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { | 788 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { |
| 767 defer_commits_ = defer_commits; | 789 defer_commits_ = defer_commits; |
| 768 } | 790 } |
| 769 | 791 |
| 792 void SchedulerStateMachine::SetBeginFrameAllowsLatencyOptimizations( |
| 793 bool allow_latency_optimizations) { |
| 794 // In this mode, we ensure that we don't skip the BeginFrame/BeginMainFrame |
| 795 // and that we don't prioritize impl thread latency. Thus, we first give the |
| 796 // main thread a chance to produce updates, and only if it doesn't (or doesn't |
| 797 // respond in time for the deadline), we produce an impl frame. |
| 798 |
| 799 // |!allow_latency_optimizations| is often used in combination with long or |
| 800 // infinite BeginFrame deadlines. To respond timely, we rely on triggering the |
| 801 // BeginFrame deadline immediately if the main frame has no updates or as soon |
| 802 // as it was activated (see ShouldTriggerBeginImplFrameDeadlineImmediately()). |
| 803 |
| 804 begin_frame_allows_latency_optimizations_ = allow_latency_optimizations; |
| 805 } |
| 806 |
| 770 // These are the cases where we require a BeginFrame message to make progress | 807 // These are the cases where we require a BeginFrame message to make progress |
| 771 // on requested actions. | 808 // on requested actions. |
| 772 bool SchedulerStateMachine::BeginFrameRequiredForAction() const { | 809 bool SchedulerStateMachine::BeginFrameRequiredForAction() const { |
| 773 // The forced draw respects our normal draw scheduling, so we need to | 810 // The forced draw respects our normal draw scheduling, so we need to |
| 774 // request a BeginImplFrame for it. | 811 // request a BeginImplFrame for it. |
| 775 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 812 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
| 776 return true; | 813 return true; |
| 777 | 814 |
| 778 return needs_redraw_ || needs_one_begin_impl_frame_ || | 815 return needs_redraw_ || needs_one_begin_impl_frame_ || |
| 779 (needs_begin_main_frame_ && !defer_commits_); | 816 (needs_begin_main_frame_ && !defer_commits_); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 912 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
| 876 if (settings_.using_synchronous_renderer_compositor) { | 913 if (settings_.using_synchronous_renderer_compositor) { |
| 877 // No deadline for synchronous compositor. | 914 // No deadline for synchronous compositor. |
| 878 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; | 915 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE; |
| 879 } else if (wait_for_ready_to_draw_) { | 916 } else if (wait_for_ready_to_draw_) { |
| 880 // In browser compositor, wait for active tree to be rasterized. | 917 // In browser compositor, wait for active tree to be rasterized. |
| 881 DCHECK(settings_.commit_to_active_tree); | 918 DCHECK(settings_.commit_to_active_tree); |
| 882 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; | 919 return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW; |
| 883 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { | 920 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { |
| 884 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; | 921 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; |
| 885 } else if (needs_redraw_) { | 922 } else if (needs_redraw_ && begin_frame_allows_latency_optimizations_) { |
| 886 // We have an animation or fast input path on the impl thread that wants | 923 // We have an animation or fast input path on the impl thread that wants |
| 887 // to draw, so don't wait too long for a new active tree. | 924 // to draw, so don't wait too long for a new active tree. |
| 888 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; | 925 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; |
| 889 } else { | 926 } else { |
| 890 // The impl thread doesn't have anything it wants to draw and we are just | 927 // The impl thread doesn't have anything it wants to draw and we are just |
| 891 // waiting for a new active tree. In short we are blocked. | 928 // waiting for a new active tree. In short we are blocked. |
| 892 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; | 929 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; |
| 893 } | 930 } |
| 894 } | 931 } |
| 895 | 932 |
| 896 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() | 933 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() |
| 897 const { | 934 const { |
| 898 // If we just forced activation, we should end the deadline right now. | 935 // If we just forced activation, we should end the deadline right now. |
| 899 if (PendingActivationsShouldBeForced() && !has_pending_tree_) | 936 if (PendingActivationsShouldBeForced() && !has_pending_tree_) |
| 900 return true; | 937 return true; |
| 901 | 938 |
| 902 // Throttle the deadline on CompositorFrameAck since we wont draw and submit | 939 // Throttle the deadline on CompositorFrameAck since we wont draw and submit |
| 903 // anyway. | 940 // anyway. |
| 904 if (IsDrawThrottled()) | 941 if (IsDrawThrottled()) |
| 905 return false; | 942 return false; |
| 906 | 943 |
| 907 if (active_tree_needs_first_draw_) | 944 if (active_tree_needs_first_draw_) |
| 908 return true; | 945 return true; |
| 909 | 946 |
| 947 // Immediately respond to the BeginFrame if the main frame isn't producing |
| 948 // anything, e.g., after an aborted commit. We also check that we don't have a |
| 949 // pending tree -- otherwise we should give it a chance to activate. We |
| 950 // trigger an immediate deadline even if the impl thread doesn't want to draw |
| 951 // anything either, because we don't want to stall the BeginFrame |
| 952 // acknowledgment unnecessarily. |
| 953 // TODO(skyostil): Revisit this when we have more accurate deadline estimates. |
| 954 if (!CommitPending() && !has_pending_tree_) |
| 955 return true; |
| 956 |
| 910 if (!needs_redraw_) | 957 if (!needs_redraw_) |
| 911 return false; | 958 return false; |
| 912 | 959 |
| 913 // This is used to prioritize impl-thread draws when the main thread isn't | |
| 914 // producing anything, e.g., after an aborted commit. We also check that we | |
| 915 // don't have a pending tree -- otherwise we should give it a chance to | |
| 916 // activate. | |
| 917 // TODO(skyostil): Revisit this when we have more accurate deadline estimates. | |
| 918 if (!CommitPending() && !has_pending_tree_) | |
| 919 return true; | |
| 920 | |
| 921 // Prioritize impl-thread draws in ImplLatencyTakesPriority mode. | 960 // Prioritize impl-thread draws in ImplLatencyTakesPriority mode. |
| 922 if (ImplLatencyTakesPriority()) | 961 if (ImplLatencyTakesPriority()) |
| 923 return true; | 962 return true; |
| 924 | 963 |
| 925 return false; | 964 return false; |
| 926 } | 965 } |
| 927 | 966 |
| 928 bool SchedulerStateMachine::IsDrawThrottled() const { | 967 bool SchedulerStateMachine::IsDrawThrottled() const { |
| 929 return pending_submit_frames_ >= kMaxPendingSubmitFrames; | 968 return pending_submit_frames_ >= kMaxPendingSubmitFrames; |
| 930 } | 969 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 tree_priority_ = tree_priority; | 1038 tree_priority_ = tree_priority; |
| 1000 scroll_handler_state_ = scroll_handler_state; | 1039 scroll_handler_state_ = scroll_handler_state; |
| 1001 } | 1040 } |
| 1002 | 1041 |
| 1003 void SchedulerStateMachine::SetCriticalBeginMainFrameToActivateIsFast( | 1042 void SchedulerStateMachine::SetCriticalBeginMainFrameToActivateIsFast( |
| 1004 bool is_fast) { | 1043 bool is_fast) { |
| 1005 critical_begin_main_frame_to_activate_is_fast_ = is_fast; | 1044 critical_begin_main_frame_to_activate_is_fast_ = is_fast; |
| 1006 } | 1045 } |
| 1007 | 1046 |
| 1008 bool SchedulerStateMachine::ImplLatencyTakesPriority() const { | 1047 bool SchedulerStateMachine::ImplLatencyTakesPriority() const { |
| 1048 // Wait for main frame if requested by BeginFrameArgs. |
| 1049 if (!begin_frame_allows_latency_optimizations_) |
| 1050 return false; |
| 1051 |
| 1009 // Attempt to synchronize with the main thread if it has a scroll listener | 1052 // Attempt to synchronize with the main thread if it has a scroll listener |
| 1010 // and is fast. | 1053 // and is fast. |
| 1011 if (ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER == | 1054 if (ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER == |
| 1012 scroll_handler_state_ && | 1055 scroll_handler_state_ && |
| 1013 critical_begin_main_frame_to_activate_is_fast_) | 1056 critical_begin_main_frame_to_activate_is_fast_) |
| 1014 return false; | 1057 return false; |
| 1015 | 1058 |
| 1016 // Don't wait for the main thread if we are prioritizing smoothness. | 1059 // Don't wait for the main thread if we are prioritizing smoothness. |
| 1017 if (SMOOTHNESS_TAKES_PRIORITY == tree_priority_) | 1060 if (SMOOTHNESS_TAKES_PRIORITY == tree_priority_) |
| 1018 return true; | 1061 return true; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 case COMPOSITOR_FRAME_SINK_ACTIVE: | 1155 case COMPOSITOR_FRAME_SINK_ACTIVE: |
| 1113 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: | 1156 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: |
| 1114 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: | 1157 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: |
| 1115 return true; | 1158 return true; |
| 1116 } | 1159 } |
| 1117 NOTREACHED(); | 1160 NOTREACHED(); |
| 1118 return false; | 1161 return false; |
| 1119 } | 1162 } |
| 1120 | 1163 |
| 1121 } // namespace cc | 1164 } // namespace cc |
| OLD | NEW |