Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(502)

Side by Side Diff: cc/scheduler/scheduler_state_machine.cc

Issue 16871016: cc: Use BeginFrameArgs (Closed) Base URL: http://git.chromium.org/chromium/src.git@bfargs2
Patch Set: Rebase; Avoid double activate; Fix OutputSurface init and page scroll delta; Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 10
11 namespace cc { 11 namespace cc {
12 12
13 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 13 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
14 : settings_(settings), 14 : settings_(settings),
15 output_surface_state_(OUTPUT_SURFACE_LOST),
16 begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
15 commit_state_(COMMIT_STATE_IDLE), 17 commit_state_(COMMIT_STATE_IDLE),
18 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
19 readback_state_(READBACK_STATE_IDLE),
20 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
16 commit_count_(0), 21 commit_count_(0),
17 current_frame_number_(0), 22 begin_frame_count_(0),
18 last_frame_number_where_begin_frame_sent_to_main_thread_(-1), 23 draw_attempt_count_(0),
19 last_frame_number_where_draw_was_called_(-1), 24 last_begin_frame_count_draw_was_called_(-1),
20 last_frame_number_where_tree_activation_attempted_(-1), 25 last_draw_attempt_count_draw_was_called_(-1),
21 last_frame_number_where_update_visible_tiles_was_called_(-1), 26 last_begin_frame_count_begin_frame_sent_to_main_thread_(-1),
27 last_draw_attempt_count_tree_activation_attempted_(-1),
28 last_draw_attempt_count_update_visible_tiles_was_called_(-1),
22 consecutive_failed_draws_(0), 29 consecutive_failed_draws_(0),
23 maximum_number_of_failed_draws_before_draw_is_forced_(3), 30 maximum_number_of_failed_draws_before_draw_is_forced_(3),
24 needs_redraw_(false), 31 needs_redraw_(false),
25 swap_used_incomplete_tile_(false), 32 swap_used_incomplete_tile_(false),
26 needs_forced_redraw_(false),
27 needs_forced_redraw_after_next_commit_(false),
28 needs_redraw_after_next_commit_(false),
29 needs_commit_(false), 33 needs_commit_(false),
30 needs_forced_commit_(false),
31 expect_immediate_begin_frame_for_main_thread_(false),
32 main_thread_needs_layer_textures_(false), 34 main_thread_needs_layer_textures_(false),
33 inside_begin_frame_(false), 35 active_tree_has_been_drawn_(false),
36 active_tree_is_null_(true),
34 visible_(false), 37 visible_(false),
35 can_start_(false), 38 can_start_(false),
36 can_draw_(false), 39 can_draw_(false),
37 has_pending_tree_(false), 40 has_pending_tree_(false),
41 pending_tree_is_ready_for_activation_(false),
38 draw_if_possible_failed_(false), 42 draw_if_possible_failed_(false),
39 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
40 output_surface_state_(OUTPUT_SURFACE_LOST),
41 did_create_and_initialize_first_output_surface_(false) {} 43 did_create_and_initialize_first_output_surface_(false) {}
42 44
43 std::string SchedulerStateMachine::ToString() { 45 std::string SchedulerStateMachine::ToString() {
44 std::string str; 46 std::string str;
47 base::StringAppendF(&str, "settings_.impl_side_painting = %d; ",
48 settings_.impl_side_painting);
49 base::StringAppendF(&str, "output_surface_state_ = %d; ",
50 output_surface_state_);
51 base::StringAppendF(&str, "begin_frame_state_ = %d; ", begin_frame_state_);
52 base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_);
53 base::StringAppendF(&str, "texture_state_ = %d; ", texture_state_);
54 base::StringAppendF(&str, "readback_state_ = %d; ", readback_state_);
55 base::StringAppendF(&str, "forced_redraw_state_ = %d; ",
56 forced_redraw_state_);
57 base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_);
58 base::StringAppendF(&str, "begin_frame_count_ = %d; ", begin_frame_count_);
59 base::StringAppendF(&str, "draw_attempt_count_ = %d; ", draw_attempt_count_);
60 base::StringAppendF(&str, "last_begin_frame_count_draw_was_called_ = %d; ",
61 last_begin_frame_count_draw_was_called_);
62 base::StringAppendF(&str, "last_draw_attempt_count_draw_was_called_ = %d; ",
63 last_draw_attempt_count_draw_was_called_);
45 base::StringAppendF(&str, 64 base::StringAppendF(&str,
46 "settings_.impl_side_painting = %d; ", 65 "last_begin_frame_count_begin_frame_sent_to_main_thread_ = %d; ",
47 settings_.impl_side_painting); 66 last_begin_frame_count_begin_frame_sent_to_main_thread_);
48 base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_);
49 base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_);
50 base::StringAppendF(
51 &str, "current_frame_number_ = %d; ", current_frame_number_);
52 base::StringAppendF(&str, 67 base::StringAppendF(&str,
53 "last_frame_number_where_draw_was_called_ = %d; ", 68 "last_draw_attempt_count_tree_activation_attempted_ = %d; ",
54 last_frame_number_where_draw_was_called_); 69 last_draw_attempt_count_tree_activation_attempted_);
55 base::StringAppendF( 70 base::StringAppendF(&str,
56 &str, 71 "last_draw_attempt_count_update_visible_tiles_was_called_ = %d; ",
57 "last_frame_number_where_tree_activation_attempted_ = %d; ", 72 last_draw_attempt_count_update_visible_tiles_was_called_);
58 last_frame_number_where_tree_activation_attempted_);
59 base::StringAppendF(
60 &str,
61 "last_frame_number_where_update_visible_tiles_was_called_ = %d; ",
62 last_frame_number_where_update_visible_tiles_was_called_);
63 base::StringAppendF( 73 base::StringAppendF(
64 &str, "consecutive_failed_draws_ = %d; ", consecutive_failed_draws_); 74 &str, "consecutive_failed_draws_ = %d; ", consecutive_failed_draws_);
65 base::StringAppendF( 75 base::StringAppendF(
66 &str, 76 &str,
67 "maximum_number_of_failed_draws_before_draw_is_forced_ = %d; ", 77 "maximum_number_of_failed_draws_before_draw_is_forced_ = %d; ",
68 maximum_number_of_failed_draws_before_draw_is_forced_); 78 maximum_number_of_failed_draws_before_draw_is_forced_);
69 base::StringAppendF(&str, "needs_redraw_ = %d; ", needs_redraw_); 79 base::StringAppendF(&str, "needs_redraw_ = %d; ", needs_redraw_);
70 base::StringAppendF( 80 base::StringAppendF(
71 &str, "swap_used_incomplete_tile_ = %d; ", swap_used_incomplete_tile_); 81 &str, "swap_used_incomplete_tile_ = %d; ", swap_used_incomplete_tile_);
72 base::StringAppendF(
73 &str, "needs_forced_redraw_ = %d; ", needs_forced_redraw_);
74 base::StringAppendF(&str,
75 "needs_forced_redraw_after_next_commit_ = %d; ",
76 needs_forced_redraw_after_next_commit_);
77 base::StringAppendF(&str, "needs_commit_ = %d; ", needs_commit_); 82 base::StringAppendF(&str, "needs_commit_ = %d; ", needs_commit_);
78 base::StringAppendF(
79 &str, "needs_forced_commit_ = %d; ", needs_forced_commit_);
80 base::StringAppendF(&str,
81 "expect_immediate_begin_frame_for_main_thread_ = %d; ",
82 expect_immediate_begin_frame_for_main_thread_);
83 base::StringAppendF(&str, 83 base::StringAppendF(&str,
84 "main_thread_needs_layer_textures_ = %d; ", 84 "main_thread_needs_layer_textures_ = %d; ",
85 main_thread_needs_layer_textures_); 85 main_thread_needs_layer_textures_);
86 base::StringAppendF(&str, "inside_begin_frame_ = %d; ",
87 inside_begin_frame_);
88 base::StringAppendF(&str, "last_frame_time_ = %" PRId64 "; ", 86 base::StringAppendF(&str, "last_frame_time_ = %" PRId64 "; ",
89 (last_begin_frame_args_.frame_time - base::TimeTicks()) 87 (last_begin_frame_args_.frame_time - base::TimeTicks())
90 .InMilliseconds()); 88 .InMilliseconds());
91 base::StringAppendF(&str, "last_deadline_ = %" PRId64 "; ", 89 base::StringAppendF(&str, "last_deadline_ = %" PRId64 "; ",
92 (last_begin_frame_args_.deadline - base::TimeTicks()).InMilliseconds()); 90 (last_begin_frame_args_.deadline - base::TimeTicks()).InMilliseconds());
93 base::StringAppendF(&str, "last_interval_ = %" PRId64 "; ", 91 base::StringAppendF(&str, "last_interval_ = %" PRId64 "; ",
94 last_begin_frame_args_.interval.InMilliseconds()); 92 last_begin_frame_args_.interval.InMilliseconds());
95 base::StringAppendF(&str, "visible_ = %d; ", visible_); 93 base::StringAppendF(&str, "visible_ = %d; ", visible_);
96 base::StringAppendF(&str, "can_start_ = %d; ", can_start_); 94 base::StringAppendF(&str, "can_start_ = %d; ", can_start_);
97 base::StringAppendF(&str, "can_draw_ = %d; ", can_draw_); 95 base::StringAppendF(&str, "can_draw_ = %d; ", can_draw_);
98 base::StringAppendF( 96 base::StringAppendF(
99 &str, "draw_if_possible_failed_ = %d; ", draw_if_possible_failed_); 97 &str, "draw_if_possible_failed_ = %d; ", draw_if_possible_failed_);
100 base::StringAppendF(&str, "has_pending_tree_ = %d; ", has_pending_tree_); 98 base::StringAppendF(&str, "has_pending_tree_ = %d; ", has_pending_tree_);
101 base::StringAppendF(&str, "texture_state_ = %d; ", texture_state_); 99 base::StringAppendF(&str,
102 base::StringAppendF( 100 "pending_tree_is_ready_for_activation_ = %d; ",
103 &str, "output_surface_state_ = %d; ", output_surface_state_); 101 pending_tree_is_ready_for_activation_);
102 base::StringAppendF(&str, "active_tree_has_been_drawn_ = %d; ",
103 active_tree_has_been_drawn_);
104 base::StringAppendF(&str, "active_tree_is_null_ = %d; ",
105 active_tree_is_null_);
104 return str; 106 return str;
105 } 107 }
106 108
107 bool SchedulerStateMachine::HasDrawnThisFrame() const { 109 bool SchedulerStateMachine::HasDrawnThisFrame() const {
108 return current_frame_number_ == last_frame_number_where_draw_was_called_; 110 return begin_frame_count_ == last_begin_frame_count_draw_was_called_;
109 } 111 }
110 112
111 bool SchedulerStateMachine::HasAttemptedTreeActivationThisFrame() const { 113 bool SchedulerStateMachine::HasDrawnThisDrawAttempt() const {
112 return current_frame_number_ == 114 return draw_attempt_count_ == last_draw_attempt_count_draw_was_called_;
113 last_frame_number_where_tree_activation_attempted_;
114 } 115 }
115 116
116 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 117 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
117 return current_frame_number_ == 118 return begin_frame_count_ ==
118 last_frame_number_where_update_visible_tiles_was_called_; 119 last_begin_frame_count_begin_frame_sent_to_main_thread_;
119 } 120 }
120 121
121 void SchedulerStateMachine::SetPostCommitFlags() { 122 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisDrawAttempt() const {
122 // This post-commit work is common to both completed and aborted commits. 123 return draw_attempt_count_ ==
123 if (needs_forced_redraw_after_next_commit_) { 124 last_draw_attempt_count_update_visible_tiles_was_called_;
124 needs_forced_redraw_after_next_commit_ = false; 125 }
125 needs_forced_redraw_ = true; 126
127 bool SchedulerStateMachine::HasActivatedPendingTreeThisDrawAttempt() const {
128 return draw_attempt_count_ ==
129 last_draw_attempt_count_tree_activation_attempted_;
130 }
131
132 void SchedulerStateMachine::HandleCommitInternal(bool commit_was_aborted) {
133 commit_count_++;
134 draw_attempt_count_++;
135
136 // If we are impl-side-painting but the commit was aborted, then we behave
137 // as if we are not impl-side-painting since there is no pending tree.
138 if (settings_.impl_side_painting && !commit_was_aborted) {
139 commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
140
141 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
142 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
143
144 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
145 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION;
146 else if (readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
147 readback_state_ = READBACK_STATE_WAITING_FOR_ACTIVATION;
148 else if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING)
149 readback_state_ = READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING;
150
151 } else {
152 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
153 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
154 needs_redraw_ = true;
155 }
156
157 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
158 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
159 else if (readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
160 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
161 else if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING)
162 readback_state_ = READBACK_STATE_IDLE;
163
164 if (draw_if_possible_failed_) {
165 last_begin_frame_count_draw_was_called_ = -1;
166 last_draw_attempt_count_draw_was_called_ = -1;
167 }
168
169 if (commit_was_aborted) {
170 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW ||
171 readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
172 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
173 else
174 commit_state_ = COMMIT_STATE_IDLE;
175 } else {
176 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
177 active_tree_has_been_drawn_ = false;
178 needs_redraw_ = true;
179 }
126 } 180 }
127 if (needs_redraw_after_next_commit_) { 181
128 needs_redraw_after_next_commit_ = false;
129 needs_redraw_ = true;
130 }
131 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; 182 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
132 } 183 }
133 184
134 bool SchedulerStateMachine::DrawSuspendedUntilCommit() const { 185 bool SchedulerStateMachine::DrawSuspendedUntilCommit() const {
135 if (!can_draw_) 186 if (!can_draw_)
136 return true; 187 return true;
137 if (!visible_) 188 if (!visible_)
138 return true; 189 return true;
139 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) 190 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
140 return true; 191 return true;
141 return false; 192 return false;
142 } 193 }
143 194
144 bool SchedulerStateMachine::ScheduledToDraw() const { 195 bool SchedulerStateMachine::ScheduledToDraw() const {
145 if (!needs_redraw_) 196 if (!needs_redraw_)
146 return false; 197 return false;
147 if (DrawSuspendedUntilCommit()) 198 if (DrawSuspendedUntilCommit())
148 return false; 199 return false;
149 return true; 200 return true;
150 } 201 }
151 202
152 bool SchedulerStateMachine::ShouldDraw() const { 203 bool SchedulerStateMachine::ShouldDraw() const {
153 if (needs_forced_redraw_) 204 if (HasDrawnThisDrawAttempt())
205 return false;
206
207 // After a readback, make sure not to draw again until we've replaced the
208 // readback commit with a real one.
209 if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING ||
210 readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING)
211 return false;
212
213 // Draw outside of the BeginFrame deadline for readbacks.
214 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
215 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
154 return true; 216 return true;
217 }
218
219 // If we've lost the output surface or draw is suspended, we want to be able
220 // to abort a draw and make forward progress to unblock the main thread.
221 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
222 DrawSuspendedUntilCommit()) {
223 return !active_tree_has_been_drawn_ &&
224 (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW ||
225 commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION ||
226 (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
227 !active_tree_is_null_));
228 }
229
230 // Except for the cases above, do not draw outside of the BeginFrame deadline.
231 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
232 return false;
233
234 // Only handle forced redraws due to timeouts on the regular deadline.
235 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
236 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
237 return true;
238 }
155 239
156 if (!ScheduledToDraw()) 240 if (!ScheduledToDraw())
157 return false; 241 return false;
158 if (!inside_begin_frame_)
159 return false;
160 if (HasDrawnThisFrame()) 242 if (HasDrawnThisFrame())
161 return false; 243 return false;
162 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 244 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE)
163 return false; 245 return false;
164 return true; 246 return true;
165 } 247 }
166 248
167 bool SchedulerStateMachine::ShouldAttemptTreeActivation() const { 249 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
168 return has_pending_tree_ && inside_begin_frame_ && 250 // Some quick early outs.
169 !HasAttemptedTreeActivationThisFrame(); 251 if (!has_pending_tree_)
252 return false;
253 if (HasActivatedPendingTreeThisDrawAttempt())
254 return false;
255
256 // If this is our first activation, we don't want to activate early.
257 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
258 return pending_tree_is_ready_for_activation_;
259
260 // In these cases, we want to activate even if the pending tree isn't ready
enne (OOO) 2013/08/02 19:41:25 This looks really good. This is what I was trying
261 // because we aren't going to draw the pending tree or need to make
262 // forward progress to unblock the main thread.
263 if (!visible_ ||
264 output_surface_state_ == OUTPUT_SURFACE_LOST ||
265 output_surface_state_ == OUTPUT_SURFACE_CREATING ||
266 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
267 return true;
268
269 // After this line, we only want to activate if we are ready to activate.
270 if (!pending_tree_is_ready_for_activation_)
271 return false;
272
enne (OOO) 2013/08/02 19:41:25 This comment doesn't really add much, and I don't
brianderson 2013/08/02 23:04:31 Good catch! This needlessly delays activation. I p
273 // Do not activate in BEGIN_FRAME_STATE_IDLE
274 if (begin_frame_state_ == BEGIN_FRAME_STATE_IDLE)
275 return false;
276
277 // We do not want to activate a second tree before drawing the first one.
enne (OOO) 2013/08/02 19:41:25 How is that possible? Maybe I'm misreading other p
brianderson 2013/08/02 23:04:31 In this patch, the draw no longer has to occur bef
278 return active_tree_has_been_drawn_ || active_tree_is_null_;
enne (OOO) 2013/08/02 19:41:25 There are other reasons that the active tree might
brianderson 2013/08/02 23:04:31 In cases where can_draw_ is false, ACTION_DRAW_AND
enne (OOO) 2013/08/05 19:37:43 In that case, shouldn't that logic to set active_t
brianderson 2013/08/05 21:56:19 As it is currently coded, ShouldDraw() will not re
170 } 279 }
171 280
172 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 281 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
173 if (!settings_.impl_side_painting) 282 if (!settings_.impl_side_painting)
174 return false; 283 return false;
175 if (HasUpdatedVisibleTilesThisFrame()) 284 if (HasUpdatedVisibleTilesThisDrawAttempt())
176 return false; 285 return false;
177 286
178 return ShouldAttemptTreeActivation() || ShouldDraw() || 287 return ShouldActivatePendingTree() || ShouldDraw() ||
179 swap_used_incomplete_tile_; 288 swap_used_incomplete_tile_;
180 } 289 }
181 290
182 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const { 291 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
183 if (!main_thread_needs_layer_textures_) 292 if (!main_thread_needs_layer_textures_)
184 return false; 293 return false;
185 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED) 294 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
186 return true; 295 return true;
187 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); 296 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
188 // Transfer the lock from impl thread to main thread immediately if the 297 // Transfer the lock from impl thread to main thread immediately if the
189 // impl thread is not even scheduled to draw. Guards against deadlocking. 298 // impl thread is not even scheduled to draw. Guards against deadlocking.
190 if (!ScheduledToDraw()) 299 if (!ScheduledToDraw())
191 return true; 300 return true;
192 if (!BeginFrameNeededToDrawByImplThread()) 301 if (!BeginFrameNeededToDrawByImplThread())
193 return true; 302 return true;
194 return false; 303 return false;
195 } 304 }
196 305
306 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
307 if (HasSentBeginFrameToMainThreadThisFrame())
308 return false;
309
310 // Only send BeginFrame to the main thread when idle.
311 if (commit_state_ != COMMIT_STATE_IDLE)
312 return false;
313
314 // We can't accept a commit if we have a pending tree.
315 if (has_pending_tree_)
316 return false;
317
318 // We want to handle readback commits ASAP.
319 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED)
320 return !CommitPending();
321
322 // We want to start the first commit after we get a new output surface
323 // immediately.
324 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT
325 && needs_commit_)
326 return true;
327
328 // We usually want to slave the main thread's BeginFrame to the impl thread's
329 // BeginFrame. However, if we aren't expecting a BeginFrame on the impl
330 // thread, we should send a BeginFrame to the main thread anyway to make
331 // progress.
332 // TODO(brianderson): Also allow sending BeginFrame to main thread while idle
333 // when the main thread isn't consuming user input.
334 if (begin_frame_state_ == BEGIN_FRAME_STATE_IDLE &&
335 BeginFrameNeededByImplThread())
336 return false;
337
338 // Do not send begin frame to main thread in the deadline until we have drawn.
339 // We have a train to catch!
340 if (begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_DEADLINE &&
341 !HasDrawnThisFrame())
342 return false;
343
344 // If not impl-side-painting, do not send a BeginFrame to the main thread if
345 // we haven't drawn the active tree. Otherwise, the commit overwrite the
346 // active tree before we have a chance to draw it.
347 if (!settings_.impl_side_painting &&
348 !active_tree_has_been_drawn_ &&
349 !active_tree_is_null_)
350 return false;
351
352 bool can_commit = needs_commit_ &&
353 (visible_ ||
354 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
355 return can_commit &&
356 (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT ||
357 HasInitializedOutputSurface());
358 }
359
197 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 360 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
198 if (ShouldAcquireLayerTexturesForMainThread()) 361 if (ShouldAcquireLayerTexturesForMainThread())
199 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 362 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
200 363
201 switch (commit_state_) { 364 switch (commit_state_) {
202 case COMMIT_STATE_IDLE: { 365 case COMMIT_STATE_IDLE:
203 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE && 366 if (ShouldSendBeginFrameToMainThread())
204 needs_forced_redraw_) 367 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
205 return ACTION_DRAW_FORCED;
206 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
207 needs_forced_commit_)
208 // TODO(enne): Should probably drop the active tree on force commit.
209 return has_pending_tree_ ? ACTION_NONE
210 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
211 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_) 368 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_)
212 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 369 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
213 if (output_surface_state_ == OUTPUT_SURFACE_CREATING) 370 if (output_surface_state_ == OUTPUT_SURFACE_CREATING)
214 return ACTION_NONE; 371 return ACTION_NONE;
215 if (ShouldUpdateVisibleTiles()) 372 if (ShouldUpdateVisibleTiles())
216 return ACTION_UPDATE_VISIBLE_TILES; 373 return ACTION_UPDATE_VISIBLE_TILES;
217 if (ShouldAttemptTreeActivation()) 374 if (ShouldActivatePendingTree())
218 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 375 return ACTION_ACTIVATE_PENDING_TREE;
219 if (ShouldDraw()) { 376 if (ShouldDraw()) {
220 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 377 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
221 : ACTION_DRAW_IF_POSSIBLE; 378 DrawSuspendedUntilCommit())
379 return ACTION_DRAW_AND_SWAP_ABORT;
380 else
381 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
222 } 382 }
223 bool can_commit_this_frame =
224 visible_ &&
225 current_frame_number_ >
226 last_frame_number_where_begin_frame_sent_to_main_thread_;
227 if (needs_commit_ && ((can_commit_this_frame &&
228 output_surface_state_ == OUTPUT_SURFACE_ACTIVE) ||
229 needs_forced_commit_))
230 // TODO(enne): Should probably drop the active tree on force commit.
231 return has_pending_tree_ ? ACTION_NONE
232 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
233 return ACTION_NONE; 383 return ACTION_NONE;
234 } 384
235 case COMMIT_STATE_FRAME_IN_PROGRESS: 385 case COMMIT_STATE_FRAME_IN_PROGRESS:
236 if (ShouldUpdateVisibleTiles()) 386 if (ShouldUpdateVisibleTiles())
237 return ACTION_UPDATE_VISIBLE_TILES; 387 return ACTION_UPDATE_VISIBLE_TILES;
238 if (ShouldAttemptTreeActivation()) 388 if (ShouldActivatePendingTree())
239 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 389 return ACTION_ACTIVATE_PENDING_TREE;
240 if (ShouldDraw()) { 390 if (ShouldDraw()) {
241 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 391 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
242 : ACTION_DRAW_IF_POSSIBLE; 392 DrawSuspendedUntilCommit())
393 return ACTION_DRAW_AND_SWAP_ABORT;
394 else
395 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
243 } 396 }
244 return ACTION_NONE; 397 return ACTION_NONE;
245 398
246 case COMMIT_STATE_READY_TO_COMMIT: 399 case COMMIT_STATE_READY_TO_COMMIT:
247 return ACTION_COMMIT; 400 return ACTION_COMMIT;
248 401
402 case COMMIT_STATE_WAITING_FOR_ACTIVATION: {
403 if (ShouldUpdateVisibleTiles())
404 return ACTION_UPDATE_VISIBLE_TILES;
405 if (ShouldActivatePendingTree())
406 return ACTION_ACTIVATE_PENDING_TREE;
407 if (ShouldDraw()) {
408 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
409 DrawSuspendedUntilCommit())
410 return ACTION_DRAW_AND_SWAP_ABORT;
411 else
412 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
413 }
414 return ACTION_NONE;
415 }
416
249 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: { 417 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: {
250 if (ShouldUpdateVisibleTiles()) 418 if (ShouldUpdateVisibleTiles())
251 return ACTION_UPDATE_VISIBLE_TILES; 419 return ACTION_UPDATE_VISIBLE_TILES;
252 if (ShouldAttemptTreeActivation()) 420 if (ShouldActivatePendingTree())
253 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 421 return ACTION_ACTIVATE_PENDING_TREE;
254 if (ShouldDraw() || output_surface_state_ == OUTPUT_SURFACE_LOST) { 422 if (ShouldDraw()) {
255 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 423 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
256 : ACTION_DRAW_IF_POSSIBLE; 424 return ACTION_DRAW_AND_SWAP_FORCED;
425 else if (readback_state_ ==
426 READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
427 return ACTION_DRAW_AND_READBACK;
428 else if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
429 DrawSuspendedUntilCommit())
430 return ACTION_DRAW_AND_SWAP_ABORT;
431 else
432 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
257 } 433 }
258 // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If
259 // can_draw_ is false or textures are not available, proceed to the next
260 // step (similar as in COMMIT_STATE_IDLE).
261 bool can_commit =
262 needs_forced_commit_ ||
263 (visible_ &&
264 current_frame_number_ >
265 last_frame_number_where_begin_frame_sent_to_main_thread_);
266 if (needs_commit_ && can_commit && DrawSuspendedUntilCommit())
267 return has_pending_tree_ ? ACTION_NONE
268 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
269 return ACTION_NONE; 434 return ACTION_NONE;
270 } 435 }
271
272 case COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW:
273 if (ShouldUpdateVisibleTiles())
274 return ACTION_UPDATE_VISIBLE_TILES;
275 if (ShouldAttemptTreeActivation())
276 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED;
277 if (needs_forced_redraw_)
278 return ACTION_DRAW_FORCED;
279 return ACTION_NONE;
280 } 436 }
281 NOTREACHED(); 437 NOTREACHED();
282 return ACTION_NONE; 438 return ACTION_NONE;
283 } 439 }
284 440
285 void SchedulerStateMachine::UpdateState(Action action) { 441 void SchedulerStateMachine::UpdateState(Action action) {
286 switch (action) { 442 switch (action) {
287 case ACTION_NONE: 443 case ACTION_NONE:
288 return; 444 return;
289 445
290 case ACTION_UPDATE_VISIBLE_TILES: 446 case ACTION_UPDATE_VISIBLE_TILES:
291 last_frame_number_where_update_visible_tiles_was_called_ = 447 last_draw_attempt_count_update_visible_tiles_was_called_ =
292 current_frame_number_; 448 draw_attempt_count_;
293 return; 449 return;
294 450
295 case ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 451 case ACTION_ACTIVATE_PENDING_TREE:
296 last_frame_number_where_tree_activation_attempted_ = 452 last_draw_attempt_count_tree_activation_attempted_ =
297 current_frame_number_; 453 draw_attempt_count_;
298 return; 454 return;
299 455
300 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 456 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
301 DCHECK(!has_pending_tree_); 457 DCHECK(!has_pending_tree_);
302 if (!needs_forced_commit_) { 458 DCHECK(visible_ ||
303 DCHECK(visible_); 459 readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED ||
304 DCHECK_GT(current_frame_number_, 460 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT ||
305 last_frame_number_where_begin_frame_sent_to_main_thread_); 461 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
306 }
307 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 462 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
308 needs_commit_ = false; 463 needs_commit_ = false;
309 needs_forced_commit_ = false; 464 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED)
310 last_frame_number_where_begin_frame_sent_to_main_thread_ = 465 readback_state_ = READBACK_STATE_FORCED_COMMIT_PENDING;
311 current_frame_number_; 466 last_begin_frame_count_begin_frame_sent_to_main_thread_ =
467 begin_frame_count_;
312 return; 468 return;
313 469
314 case ACTION_COMMIT: 470 case ACTION_COMMIT:
315 commit_count_++; 471 HandleCommitInternal(false);
316 if (expect_immediate_begin_frame_for_main_thread_)
317 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
318 else
319 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
320 // When impl-side painting, we draw on activation instead of on commit.
321 if (!settings_.impl_side_painting)
322 needs_redraw_ = true;
323 if (draw_if_possible_failed_)
324 last_frame_number_where_draw_was_called_ = -1;
325 SetPostCommitFlags();
326 return; 472 return;
327 473
328 case ACTION_DRAW_FORCED: 474 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
329 case ACTION_DRAW_IF_POSSIBLE: 475 case ACTION_DRAW_AND_SWAP_FORCED:
330 needs_redraw_ = false; 476 case ACTION_DRAW_AND_READBACK:
331 needs_forced_redraw_ = false; 477 case ACTION_DRAW_AND_SWAP_ABORT:
332 draw_if_possible_failed_ = false; 478 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
333 swap_used_incomplete_tile_ = false; 479 commit_state_ = COMMIT_STATE_IDLE;
334 if (inside_begin_frame_) 480 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
335 last_frame_number_where_draw_was_called_ = current_frame_number_; 481 } else if (readback_state_ ==
336 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) { 482 READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
337 DCHECK(expect_immediate_begin_frame_for_main_thread_); 483 DCHECK(!has_pending_tree_);
338 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 484 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
339 expect_immediate_begin_frame_for_main_thread_ = false; 485 readback_state_ = READBACK_STATE_REPLACEMENT_COMMIT_PENDING;
340 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) { 486 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
341 commit_state_ = COMMIT_STATE_IDLE; 487 commit_state_ = COMMIT_STATE_IDLE;
342 } 488 }
489 needs_redraw_ = false;
490 draw_if_possible_failed_ = false;
491 swap_used_incomplete_tile_ = false;
492 last_begin_frame_count_draw_was_called_ = begin_frame_count_;
493 last_draw_attempt_count_draw_was_called_ = draw_attempt_count_;
343 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) 494 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
344 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 495 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
496 active_tree_has_been_drawn_ = true;
345 return; 497 return;
346 498
347 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 499 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
348 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); 500 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
349 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 501 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
350 output_surface_state_ = OUTPUT_SURFACE_CREATING; 502 output_surface_state_ = OUTPUT_SURFACE_CREATING;
351 return; 503 return;
352 504
353 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 505 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
354 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; 506 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
355 main_thread_needs_layer_textures_ = false; 507 main_thread_needs_layer_textures_ = false;
356 return; 508 return;
357 } 509 }
358 } 510 }
359 511
512 void SchedulerStateMachine::AdvanceBeginFrameStateWhenNoActionsRemain() {
513 switch (begin_frame_state_) {
514 case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
515 begin_frame_state_ = BEGIN_FRAME_STATE_DEADLINE_PENDING;
516 break;
517 case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
518 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
519 break;
520 case BEGIN_FRAME_STATE_IDLE:
521 case BEGIN_FRAME_STATE_DEADLINE_PENDING:
522 break;
523 }
524 }
525
360 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 526 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
361 DCHECK(!main_thread_needs_layer_textures_); 527 DCHECK(!main_thread_needs_layer_textures_);
362 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 528 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
363 main_thread_needs_layer_textures_ = true; 529 main_thread_needs_layer_textures_ = true;
364 } 530 }
365 531
532 bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
533 return BeginFrameNeededToDrawByImplThread() ||
534 BeginFrameProactivelyNeededByImplThread();
535 }
536
366 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 537 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
367 // If we can't draw, don't tick until we are notified that we can draw again. 538 // If we can't draw, don't tick until we are notified that we can draw again.
368 if (!can_draw_) 539 if (!can_draw_)
369 return false; 540 return false;
370 541
371 if (needs_forced_redraw_) 542 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
372 return true; 543 return true;
373 544
374 if (visible_ && swap_used_incomplete_tile_) 545 if (visible_ && swap_used_incomplete_tile_)
375 return true; 546 return true;
376 547
377 return needs_redraw_ && visible_ && 548 return needs_redraw_ && visible_ && HasInitializedOutputSurface();
378 output_surface_state_ == OUTPUT_SURFACE_ACTIVE;
379 } 549 }
380 550
381 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 551 bool SchedulerStateMachine::BeginFrameProactivelyNeededByImplThread() const {
382 // Do not be proactive when invisible. 552 if (settings_.using_synchronous_renderer_compositor)
383 if (!visible_ || output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 553 return false;
554
555 if (!settings_.throttle_frame_production)
556 return false;
557
558 if (!visible_ || !HasInitializedOutputSurface())
384 return false; 559 return false;
385 560
386 // We should proactively request a BeginFrame if a commit or a tree activation 561 // We should proactively request a BeginFrame if a commit or a tree activation
387 // is pending. 562 // is pending.
388 return (needs_commit_ || needs_forced_commit_ || 563 return (needs_commit_ ||
389 commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_); 564 commit_state_ != COMMIT_STATE_IDLE ||
565 has_pending_tree_);
390 } 566 }
391 567
392 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 568 void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
393 current_frame_number_++; 569 begin_frame_count_++;
394 inside_begin_frame_ = true; 570 draw_attempt_count_++;
395 last_begin_frame_args_ = args; 571 last_begin_frame_args_ = args;
572 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
396 } 573 }
397 574
398 void SchedulerStateMachine::DidLeaveBeginFrame() { 575 bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
399 inside_begin_frame_ = false; 576 // TODO(brianderson): This should take into account multiple commit sources.
577 return begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING &&
578 !active_tree_has_been_drawn_;
400 } 579 }
401 580
402 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 581 bool SchedulerStateMachine::InsideBeginFrame() const {
582 return begin_frame_state_ != BEGIN_FRAME_STATE_IDLE;
583 }
584
585 void SchedulerStateMachine::OnBeginFrameDeadline() {
586 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_DEADLINE_PENDING);
587 draw_attempt_count_++;
588 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
589 }
590
591 void SchedulerStateMachine::SetVisible(bool visible) {
592 visible_ = visible;
593 }
403 594
404 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 595 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
405 596
406 void SchedulerStateMachine::DidSwapUseIncompleteTile() { 597 void SchedulerStateMachine::DidSwapUseIncompleteTile() {
407 swap_used_incomplete_tile_ = true; 598 swap_used_incomplete_tile_ = true;
408 } 599 }
409 600
410 void SchedulerStateMachine::SetNeedsForcedRedraw() {
411 needs_forced_redraw_ = true;
412 }
413
414 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { 601 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
415 draw_if_possible_failed_ = !success; 602 draw_if_possible_failed_ = !success;
416 if (draw_if_possible_failed_) { 603 if (draw_if_possible_failed_) {
417 needs_redraw_ = true; 604 needs_redraw_ = true;
418 needs_commit_ = true; 605 needs_commit_ = true;
419 consecutive_failed_draws_++; 606 consecutive_failed_draws_++;
420 if (settings_.timeout_and_draw_when_animation_checkerboards && 607 if (settings_.timeout_and_draw_when_animation_checkerboards &&
421 consecutive_failed_draws_ >= 608 consecutive_failed_draws_ >=
422 maximum_number_of_failed_draws_before_draw_is_forced_) { 609 maximum_number_of_failed_draws_before_draw_is_forced_) {
423 consecutive_failed_draws_ = 0; 610 consecutive_failed_draws_ = 0;
424 // We need to force a draw, but it doesn't make sense to do this until 611 // We need to force a draw, but it doesn't make sense to do this until
425 // we've committed and have new textures. 612 // we've committed and have new textures.
426 needs_forced_redraw_after_next_commit_ = true; 613 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
427 } 614 }
428 } else { 615 } else {
429 consecutive_failed_draws_ = 0; 616 consecutive_failed_draws_ = 0;
430 } 617 }
431 } 618 }
432 619
433 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } 620 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
434 621
435 void SchedulerStateMachine::SetNeedsForcedCommit() { 622 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
436 needs_forced_commit_ = true; 623 DCHECK_EQ(readback_state_, READBACK_STATE_IDLE);
437 expect_immediate_begin_frame_for_main_thread_ = true; 624 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
625 readback_state_ = READBACK_STATE_FORCED_COMMIT_PENDING;
626 else
627 readback_state_ = READBACK_STATE_FORCED_COMMIT_REQUESTED;
438 } 628 }
439 629
440 void SchedulerStateMachine::FinishCommit() { 630 void SchedulerStateMachine::FinishCommit() {
441 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || 631 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
442 (expect_immediate_begin_frame_for_main_thread_ && 632 readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
443 commit_state_ != COMMIT_STATE_IDLE))
444 << ToString(); 633 << ToString();
445 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; 634 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
446 } 635 }
447 636
448 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) { 637 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
449 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS); 638 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
450 if (expect_immediate_begin_frame_for_main_thread_) { 639 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED) {
451 expect_immediate_begin_frame_for_main_thread_ = false; 640 readback_state_ = READBACK_STATE_IDLE;
452 } else if (did_handle) { 641 } else if (did_handle) {
453 commit_state_ = COMMIT_STATE_IDLE; 642 HandleCommitInternal(true);
454 SetPostCommitFlags();
455 } else { 643 } else {
456 commit_state_ = COMMIT_STATE_IDLE; 644 commit_state_ = COMMIT_STATE_IDLE;
457 SetNeedsCommit(); 645 SetNeedsCommit();
458 } 646 }
459 } 647 }
460 648
461 void SchedulerStateMachine::DidLoseOutputSurface() { 649 void SchedulerStateMachine::DidLoseOutputSurface() {
462 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 650 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
463 output_surface_state_ == OUTPUT_SURFACE_CREATING) 651 output_surface_state_ == OUTPUT_SURFACE_CREATING)
464 return; 652 return;
465 output_surface_state_ = OUTPUT_SURFACE_LOST; 653 output_surface_state_ = OUTPUT_SURFACE_LOST;
654 needs_redraw_ = false;
466 } 655 }
467 656
468 void SchedulerStateMachine::SetHasPendingTree(bool has_pending_tree) { 657 void SchedulerStateMachine::NotifyReadyToActivate() {
658 if (has_pending_tree_)
659 pending_tree_is_ready_for_activation_ = true;
660 }
661
662 void SchedulerStateMachine::SetHasTrees(bool has_pending_tree,
663 bool active_tree_is_null) {
664 active_tree_is_null_ = active_tree_is_null;
665 if (has_pending_tree_ && !has_pending_tree) {
666 // There is a new active tree.
667 draw_attempt_count_++;
668 pending_tree_is_ready_for_activation_ = false;
669 active_tree_has_been_drawn_ = false;
670 needs_redraw_ = true;
671
672 if (draw_if_possible_failed_) {
673 last_begin_frame_count_draw_was_called_ = -1;
674 last_draw_attempt_count_draw_was_called_ = -1;
675 }
676
677 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
678 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
679
680 DCHECK_EQ(COMMIT_STATE_WAITING_FOR_ACTIVATION, commit_state_);
681 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION) {
682 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
683 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
684 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) {
685 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
686 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
687 } else {
688 commit_state_ = COMMIT_STATE_IDLE;
689 if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING)
690 readback_state_ = READBACK_STATE_IDLE;
691 }
692 } else if (!has_pending_tree_ && has_pending_tree) {
693 // There is a new pending tree.
694 pending_tree_is_ready_for_activation_ = false;
695 }
696
469 has_pending_tree_ = has_pending_tree; 697 has_pending_tree_ = has_pending_tree;
470 } 698 }
471 699
472 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; } 700 void SchedulerStateMachine::SetCanDraw(bool can_draw) {
701 can_draw_ = can_draw;
702 }
473 703
474 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 704 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
475 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 705 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
476 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 706 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
477 707 if (did_create_and_initialize_first_output_surface_)
478 if (did_create_and_initialize_first_output_surface_) {
479 // TODO(boliu): See if we can remove this when impl-side painting is always
480 // on. Does anything on the main thread need to update after recreate?
481 needs_commit_ = true; 708 needs_commit_ = true;
482 // If anything has requested a redraw, we don't want to actually draw
483 // when the output surface is restored until things have a chance to
484 // sort themselves out with a commit.
485 needs_redraw_ = false;
486 }
487 needs_redraw_after_next_commit_ = true;
488 did_create_and_initialize_first_output_surface_ = true; 709 did_create_and_initialize_first_output_surface_ = true;
489 } 710 }
490 711
491 bool SchedulerStateMachine::HasInitializedOutputSurface() const { 712 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
492 return output_surface_state_ == OUTPUT_SURFACE_ACTIVE; 713 return output_surface_state_ != OUTPUT_SURFACE_LOST &&
714 output_surface_state_ != OUTPUT_SURFACE_CREATING;
493 } 715 }
494 716
495 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced( 717 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(
496 int num_draws) { 718 int num_draws) {
497 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws; 719 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws;
498 } 720 }
499 721
500 } // namespace cc 722 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698