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

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

Issue 22926024: cc: Control activation from the Scheduler (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedOutputSurface4
Patch Set: Fixes for tests 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 #include "base/values.h" 10 #include "base/values.h"
11 11
12 namespace cc { 12 namespace cc {
13 13
14 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 14 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
15 : settings_(settings), 15 : settings_(settings),
16 output_surface_state_(OUTPUT_SURFACE_LOST), 16 output_surface_state_(OUTPUT_SURFACE_LOST),
17 commit_state_(COMMIT_STATE_IDLE), 17 commit_state_(COMMIT_STATE_IDLE),
18 commit_count_(0), 18 commit_count_(0),
19 current_frame_number_(0), 19 current_frame_number_(0),
20 last_frame_number_where_begin_frame_sent_to_main_thread_(-1), 20 last_frame_number_where_begin_frame_sent_to_main_thread_(-1),
21 last_frame_number_where_draw_was_called_(-1), 21 last_frame_number_where_draw_was_called_(-1),
22 last_frame_number_where_tree_activation_attempted_(-1),
23 last_frame_number_where_update_visible_tiles_was_called_(-1), 22 last_frame_number_where_update_visible_tiles_was_called_(-1),
24 consecutive_failed_draws_(0), 23 consecutive_failed_draws_(0),
25 maximum_number_of_failed_draws_before_draw_is_forced_(3), 24 maximum_number_of_failed_draws_before_draw_is_forced_(3),
26 needs_redraw_(false), 25 needs_redraw_(false),
27 swap_used_incomplete_tile_(false), 26 swap_used_incomplete_tile_(false),
28 needs_forced_redraw_(false), 27 needs_forced_redraw_(false),
29 needs_forced_redraw_after_next_commit_(false), 28 needs_forced_redraw_after_next_commit_(false),
30 needs_commit_(false), 29 needs_commit_(false),
31 needs_forced_commit_(false), 30 needs_forced_commit_(false),
32 expect_immediate_begin_frame_for_main_thread_(false), 31 expect_immediate_begin_frame_for_main_thread_(false),
33 main_thread_needs_layer_textures_(false), 32 main_thread_needs_layer_textures_(false),
34 inside_begin_frame_(false), 33 inside_begin_frame_(false),
35 visible_(false), 34 visible_(false),
36 can_start_(false), 35 can_start_(false),
37 can_draw_(false), 36 can_draw_(false),
38 has_pending_tree_(false), 37 has_pending_tree_(false),
38 pending_tree_is_ready_for_activation_(false),
39 active_tree_has_been_drawn_(false),
39 draw_if_possible_failed_(false), 40 draw_if_possible_failed_(false),
40 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED), 41 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
41 did_create_and_initialize_first_output_surface_(false) {} 42 did_create_and_initialize_first_output_surface_(false) {}
42 43
43 const char* SchedulerStateMachine::OutputSurfaceStateToString( 44 const char* SchedulerStateMachine::OutputSurfaceStateToString(
44 OutputSurfaceState state) { 45 OutputSurfaceState state) {
45 switch (state) { 46 switch (state) {
46 case OUTPUT_SURFACE_ACTIVE: 47 case OUTPUT_SURFACE_ACTIVE:
47 return "OUTPUT_SURFACE_ACTIVE"; 48 return "OUTPUT_SURFACE_ACTIVE";
48 case OUTPUT_SURFACE_LOST: 49 case OUTPUT_SURFACE_LOST:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 const char* SchedulerStateMachine::ActionToString(Action action) { 92 const char* SchedulerStateMachine::ActionToString(Action action) {
92 switch (action) { 93 switch (action) {
93 case ACTION_NONE: 94 case ACTION_NONE:
94 return "ACTION_NONE"; 95 return "ACTION_NONE";
95 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 96 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
96 return "ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD"; 97 return "ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD";
97 case ACTION_COMMIT: 98 case ACTION_COMMIT:
98 return "ACTION_COMMIT"; 99 return "ACTION_COMMIT";
99 case ACTION_UPDATE_VISIBLE_TILES: 100 case ACTION_UPDATE_VISIBLE_TILES:
100 return "ACTION_UPDATE_VISIBLE_TILES"; 101 return "ACTION_UPDATE_VISIBLE_TILES";
101 case ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 102 case ACTION_ACTIVATE_PENDING_TREE:
102 return "ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED"; 103 return "ACTION_ACTIVATE_PENDING_TREE";
103 case ACTION_DRAW_IF_POSSIBLE: 104 case ACTION_DRAW_IF_POSSIBLE:
104 return "ACTION_DRAW_IF_POSSIBLE"; 105 return "ACTION_DRAW_IF_POSSIBLE";
105 case ACTION_DRAW_FORCED: 106 case ACTION_DRAW_FORCED:
106 return "ACTION_DRAW_FORCED"; 107 return "ACTION_DRAW_FORCED";
107 case ACTION_DRAW_AND_SWAP_ABORT: 108 case ACTION_DRAW_AND_SWAP_ABORT:
108 return "ACTION_DRAW_AND_SWAP_ABORT"; 109 return "ACTION_DRAW_AND_SWAP_ABORT";
109 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 110 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
110 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; 111 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
111 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 112 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
112 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD"; 113 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD";
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 state->Set("major_timestamps_in_ms", timestamps_state.release()); 156 state->Set("major_timestamps_in_ms", timestamps_state.release());
156 157
157 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); 158 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
158 minor_state->SetInteger("commit_count", commit_count_); 159 minor_state->SetInteger("commit_count", commit_count_);
159 minor_state->SetInteger("current_frame_number", current_frame_number_); 160 minor_state->SetInteger("current_frame_number", current_frame_number_);
160 minor_state->SetInteger( 161 minor_state->SetInteger(
161 "last_frame_number_where_begin_frame_sent_to_main_thread", 162 "last_frame_number_where_begin_frame_sent_to_main_thread",
162 last_frame_number_where_begin_frame_sent_to_main_thread_); 163 last_frame_number_where_begin_frame_sent_to_main_thread_);
163 minor_state->SetInteger("last_frame_number_where_draw_was_called", 164 minor_state->SetInteger("last_frame_number_where_draw_was_called",
164 last_frame_number_where_draw_was_called_); 165 last_frame_number_where_draw_was_called_);
165 minor_state->SetInteger("last_frame_number_where_tree_activation_attempted",
166 last_frame_number_where_tree_activation_attempted_);
167 minor_state->SetInteger( 166 minor_state->SetInteger(
168 "last_frame_number_where_update_visible_tiles_was_called", 167 "last_frame_number_where_update_visible_tiles_was_called",
169 last_frame_number_where_update_visible_tiles_was_called_); 168 last_frame_number_where_update_visible_tiles_was_called_);
170 minor_state->SetInteger("consecutive_failed_draws", 169 minor_state->SetInteger("consecutive_failed_draws",
171 consecutive_failed_draws_); 170 consecutive_failed_draws_);
172 minor_state->SetInteger( 171 minor_state->SetInteger(
173 "maximum_number_of_failed_draws_before_draw_is_forced", 172 "maximum_number_of_failed_draws_before_draw_is_forced",
174 maximum_number_of_failed_draws_before_draw_is_forced_); 173 maximum_number_of_failed_draws_before_draw_is_forced_);
175 minor_state->SetBoolean("needs_redraw", needs_redraw_); 174 minor_state->SetBoolean("needs_redraw", needs_redraw_);
176 minor_state->SetBoolean("swap_used_incomplete_tile", 175 minor_state->SetBoolean("swap_used_incomplete_tile",
177 swap_used_incomplete_tile_); 176 swap_used_incomplete_tile_);
178 minor_state->SetBoolean("needs_forced_redraw", needs_forced_redraw_); 177 minor_state->SetBoolean("needs_forced_redraw", needs_forced_redraw_);
179 minor_state->SetBoolean("needs_forced_redraw_after_next_commit", 178 minor_state->SetBoolean("needs_forced_redraw_after_next_commit",
180 needs_forced_redraw_after_next_commit_); 179 needs_forced_redraw_after_next_commit_);
181 minor_state->SetBoolean("needs_commit", needs_commit_); 180 minor_state->SetBoolean("needs_commit", needs_commit_);
182 minor_state->SetBoolean("needs_forced_commit", needs_forced_commit_); 181 minor_state->SetBoolean("needs_forced_commit", needs_forced_commit_);
183 minor_state->SetBoolean("expect_immediate_begin_frame_for_main_thread", 182 minor_state->SetBoolean("expect_immediate_begin_frame_for_main_thread",
184 expect_immediate_begin_frame_for_main_thread_); 183 expect_immediate_begin_frame_for_main_thread_);
185 minor_state->SetBoolean("main_thread_needs_layer_textures", 184 minor_state->SetBoolean("main_thread_needs_layer_textures",
186 main_thread_needs_layer_textures_); 185 main_thread_needs_layer_textures_);
187 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_); 186 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_);
188 minor_state->SetBoolean("visible", visible_); 187 minor_state->SetBoolean("visible", visible_);
189 minor_state->SetBoolean("can_start", can_start_); 188 minor_state->SetBoolean("can_start", can_start_);
190 minor_state->SetBoolean("can_draw", can_draw_); 189 minor_state->SetBoolean("can_draw", can_draw_);
191 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); 190 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
191 minor_state->SetBoolean("pending_tree_is_ready_for_activation_",
192 pending_tree_is_ready_for_activation_);
193 minor_state->SetBoolean("active_tree_has_been_drawn_",
194 active_tree_has_been_drawn_);
192 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); 195 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
193 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", 196 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
194 did_create_and_initialize_first_output_surface_); 197 did_create_and_initialize_first_output_surface_);
195 state->Set("minor_state", minor_state.release()); 198 state->Set("minor_state", minor_state.release());
196 199
197 return state.PassAs<base::Value>(); 200 return state.PassAs<base::Value>();
198 } 201 }
199 202
200 bool SchedulerStateMachine::HasDrawnThisFrame() const { 203 bool SchedulerStateMachine::HasDrawnThisFrame() const {
201 return current_frame_number_ == last_frame_number_where_draw_was_called_; 204 return current_frame_number_ == last_frame_number_where_draw_was_called_;
202 } 205 }
203 206
204 bool SchedulerStateMachine::HasAttemptedTreeActivationThisFrame() const {
205 return current_frame_number_ ==
206 last_frame_number_where_tree_activation_attempted_;
207 }
208
209 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 207 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
210 return current_frame_number_ == 208 return current_frame_number_ ==
211 last_frame_number_where_update_visible_tiles_was_called_; 209 last_frame_number_where_update_visible_tiles_was_called_;
212 } 210 }
213 211
214 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const { 212 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
215 return current_frame_number_ == 213 return current_frame_number_ ==
216 last_frame_number_where_begin_frame_sent_to_main_thread_; 214 last_frame_number_where_begin_frame_sent_to_main_thread_;
217 } 215 }
218 216
219 void SchedulerStateMachine::HandleCommitInternal(bool commit_was_aborted) {
220 commit_count_++;
221
222 // If we are impl-side-painting but the commit was aborted, then we behave
223 // mostly as if we are not impl-side-painting since there is no pending tree.
224 bool commit_results_in_pending_tree =
225 settings_.impl_side_painting && !commit_was_aborted;
226
227 // Update the commit state.
228 if (expect_immediate_begin_frame_for_main_thread_)
229 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
230 else if (!commit_was_aborted)
231 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
232 else
233 commit_state_ = COMMIT_STATE_IDLE;
234
235 // Update the output surface state.
236 DCHECK_NE(output_surface_state_,
237 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
238 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
239 if (commit_results_in_pending_tree) {
240 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
241 } else {
242 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
243 needs_redraw_ = true;
244 }
245 }
246
247 // if we don't have to wait for activation, update needs_redraw now.
248 if (!commit_results_in_pending_tree) {
249 if (!commit_was_aborted)
250 needs_redraw_ = true;
251 if (expect_immediate_begin_frame_for_main_thread_)
252 needs_redraw_ = true;
253 }
254
255 // This post-commit work is common to both completed and aborted commits.
256 if (draw_if_possible_failed_)
257 last_frame_number_where_draw_was_called_ = -1;
258
259 if (needs_forced_redraw_after_next_commit_) {
260 needs_forced_redraw_after_next_commit_ = false;
261 needs_forced_redraw_ = true;
262 }
263
264 // If we are planing to draw with the new commit, lock the layer textures for
265 // use on the impl thread. Otherwise, leave them unlocked.
266 if (commit_results_in_pending_tree || needs_redraw_ || needs_forced_redraw_)
267 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
268 else
269 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
270 }
271
272 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 217 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
273 // These are all the cases where, if we do not abort draws to make 218 // These are all the cases where, if we do not abort draws to make
274 // forward progress, we might deadlock with the main thread. 219 // forward progress, we might deadlock with the main thread.
220 // This should be a superset of PendingActivationsShouldBeForced().
221 if (PendingActivationsShouldBeForced())
222 return true;
223
224 // Additional states where we should abort draws.
225 // Note: We don't force activation in these cases because doing so would
226 // result in checkerboarding on resize, becoming visible, etc.
275 if (!can_draw_) 227 if (!can_draw_)
276 return true; 228 return true;
277 if (!visible_) 229 if (!visible_)
278 return true; 230 return true;
279 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 231 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
280 return true; 232 return true;
233 return false;
234 }
235
236 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
237 // These are all the cases where, if we do not force activations to make
238 // forward progress, we might deadlock with the main thread.
239 // This should be a subset PendingDrawsShouldBeAborted().
281 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) 240 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
282 return true; 241 return true;
242 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
243 output_surface_state_ == OUTPUT_SURFACE_CREATING ||
244 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
245 return true;
283 return false; 246 return false;
284 } 247 }
285 248
286 bool SchedulerStateMachine::ShouldDraw() const { 249 bool SchedulerStateMachine::ShouldDraw() const {
250 // We should not draw or abort draws while we are waiting for the
251 // first activation. Doing so will cause us to transition to
252 // COMMIT_STATE_IDLE and start the 2nd commit before the 1st commit
253 // has been drawn. It will also cause us to fail readbacks when we could
254 // have succeeded by waiting a little longer.
255 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
256 return false;
257
287 // Always handle forced draws ASAP. 258 // Always handle forced draws ASAP.
288 if (needs_forced_redraw_) 259 if (needs_forced_redraw_)
289 return true; 260 return true;
290 261
262 // When we are waiting for a forced draw, only draw when
263 // needs_forced_redraw_ is true.
264 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW)
265 return needs_forced_redraw_;
266
291 // If we are going to abort draws, we should do so ASAP. 267 // If we are going to abort draws, we should do so ASAP.
292 if (PendingDrawsShouldBeAborted()) { 268 if (PendingDrawsShouldBeAborted())
293 // TODO(brianderson): Remove the !has_pending_tree_ condition once 269 return commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
294 // the Scheduler controls activation. It's dangerous for us to rely on
295 // an eventual activation if we've lost the output surface.
296 return commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW &&
297 !has_pending_tree_;
298 }
299 270
300 // After this line, we only want to draw once per frame. 271 // After this line, we only want to draw once per frame.
301 if (HasDrawnThisFrame()) 272 if (HasDrawnThisFrame())
302 return false; 273 return false;
303 274
304 // We currently only draw within the BeginFrame. 275 // We currently only draw within the BeginFrame.
305 if (!inside_begin_frame_) 276 if (!inside_begin_frame_)
306 return false; 277 return false;
307 278
308 return needs_redraw_; 279 return needs_redraw_;
309 } 280 }
310 281
311 bool SchedulerStateMachine::ShouldAttemptTreeActivation() const { 282 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
312 return has_pending_tree_ && inside_begin_frame_ && 283 // There is nothing to activate.
313 !HasAttemptedTreeActivationThisFrame(); 284 if (!has_pending_tree_)
285 return false;
286
287 // We don't want to activate a second tree before drawing the first one.
288 // Note: It is possible that there is no active tree to draw when
289 // output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
290 // so we don't block activation on draw in that case.
291 if (!active_tree_has_been_drawn_ &&
292 output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
293 return false;
294
295 // If we want to force activation, do so ASAP.
296 if (PendingActivationsShouldBeForced())
297 return true;
298
299 // At this point, only activate if we are ready to activate.
300 return pending_tree_is_ready_for_activation_;
314 } 301 }
315 302
316 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 303 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
317 if (!settings_.impl_side_painting) 304 if (!settings_.impl_side_painting)
318 return false; 305 return false;
319 if (HasUpdatedVisibleTilesThisFrame()) 306 if (HasUpdatedVisibleTilesThisFrame())
320 return false; 307 return false;
321 308
322 return ShouldAttemptTreeActivation() || ShouldDraw() || 309 return ShouldActivatePendingTree() || ShouldDraw() ||
323 swap_used_incomplete_tile_; 310 swap_used_incomplete_tile_;
324 } 311 }
325 312
326 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const { 313 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
327 if (!needs_commit_) 314 if (!needs_commit_)
328 return false; 315 return false;
329 316
330 // Only send BeginFrame to the main thread when idle. 317 // Only send BeginFrame to the main thread when idle.
331 if (commit_state_ != COMMIT_STATE_IDLE) 318 if (commit_state_ != COMMIT_STATE_IDLE)
332 return false; 319 return false;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); 354 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
368 return false; 355 return false;
369 } 356 }
370 357
371 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 358 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
372 if (ShouldAcquireLayerTexturesForMainThread()) 359 if (ShouldAcquireLayerTexturesForMainThread())
373 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 360 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
374 361
375 switch (commit_state_) { 362 switch (commit_state_) {
376 case COMMIT_STATE_IDLE: { 363 case COMMIT_STATE_IDLE: {
377 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
378 needs_forced_redraw_)
379 return ACTION_DRAW_FORCED;
380 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
381 needs_forced_commit_)
382 // TODO(enne): Should probably drop the active tree on force commit.
383 return has_pending_tree_ ? ACTION_NONE
384 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
385 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_) 364 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_)
386 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 365 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
387 if (output_surface_state_ == OUTPUT_SURFACE_CREATING) 366 if (output_surface_state_ == OUTPUT_SURFACE_CREATING)
388 return ACTION_NONE; 367 return ACTION_NONE;
389 if (ShouldUpdateVisibleTiles()) 368 if (ShouldUpdateVisibleTiles())
390 return ACTION_UPDATE_VISIBLE_TILES; 369 return ACTION_UPDATE_VISIBLE_TILES;
391 if (ShouldAttemptTreeActivation()) 370 if (ShouldActivatePendingTree())
392 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 371 return ACTION_ACTIVATE_PENDING_TREE;
393 if (ShouldDraw()) { 372 if (ShouldDraw()) {
394 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 373 return needs_forced_redraw_ ? ACTION_DRAW_FORCED
395 : ACTION_DRAW_IF_POSSIBLE; 374 : ACTION_DRAW_IF_POSSIBLE;
396 } 375 }
397 if (ShouldSendBeginFrameToMainThread()) 376 if (ShouldSendBeginFrameToMainThread())
398 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD; 377 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
399 return ACTION_NONE; 378 return ACTION_NONE;
400 } 379 }
401 case COMMIT_STATE_FRAME_IN_PROGRESS: 380 case COMMIT_STATE_FRAME_IN_PROGRESS:
402 if (ShouldUpdateVisibleTiles()) 381 if (ShouldUpdateVisibleTiles())
403 return ACTION_UPDATE_VISIBLE_TILES; 382 return ACTION_UPDATE_VISIBLE_TILES;
404 if (ShouldAttemptTreeActivation()) 383 if (ShouldActivatePendingTree())
405 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 384 return ACTION_ACTIVATE_PENDING_TREE;
406 if (ShouldDraw()) { 385 if (ShouldDraw()) {
407 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 386 return needs_forced_redraw_ ? ACTION_DRAW_FORCED
408 : ACTION_DRAW_IF_POSSIBLE; 387 : ACTION_DRAW_IF_POSSIBLE;
409 } 388 }
410 return ACTION_NONE; 389 return ACTION_NONE;
411 390
412 case COMMIT_STATE_READY_TO_COMMIT: 391 case COMMIT_STATE_READY_TO_COMMIT:
413 return ACTION_COMMIT; 392 return ACTION_COMMIT;
414 393
415 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: { 394 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: {
416 if (ShouldUpdateVisibleTiles()) 395 if (ShouldUpdateVisibleTiles())
417 return ACTION_UPDATE_VISIBLE_TILES; 396 return ACTION_UPDATE_VISIBLE_TILES;
418 if (ShouldAttemptTreeActivation()) 397 if (ShouldActivatePendingTree())
419 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 398 return ACTION_ACTIVATE_PENDING_TREE;
420 if (ShouldDraw()) { 399 if (ShouldDraw()) {
421 if (needs_forced_redraw_) 400 if (needs_forced_redraw_)
422 return ACTION_DRAW_FORCED; 401 return ACTION_DRAW_FORCED;
423 else if (PendingDrawsShouldBeAborted()) 402 else if (PendingDrawsShouldBeAborted())
424 return ACTION_DRAW_AND_SWAP_ABORT; 403 return ACTION_DRAW_AND_SWAP_ABORT;
425 else 404 else
426 return ACTION_DRAW_IF_POSSIBLE; 405 return ACTION_DRAW_IF_POSSIBLE;
427 } 406 }
428 return ACTION_NONE; 407 return ACTION_NONE;
429 } 408 }
430 409
431 case COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW: 410 case COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW:
432 if (ShouldUpdateVisibleTiles()) 411 if (ShouldUpdateVisibleTiles())
433 return ACTION_UPDATE_VISIBLE_TILES; 412 return ACTION_UPDATE_VISIBLE_TILES;
434 if (ShouldAttemptTreeActivation()) 413 if (ShouldActivatePendingTree())
435 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 414 return ACTION_ACTIVATE_PENDING_TREE;
436 if (needs_forced_redraw_) 415 if (ShouldDraw())
437 return ACTION_DRAW_FORCED; 416 return ACTION_DRAW_FORCED;
438 return ACTION_NONE; 417 return ACTION_NONE;
439 } 418 }
440 NOTREACHED(); 419 NOTREACHED();
441 return ACTION_NONE; 420 return ACTION_NONE;
442 } 421 }
443 422
444 void SchedulerStateMachine::UpdateState(Action action) { 423 void SchedulerStateMachine::UpdateState(Action action) {
445 switch (action) { 424 switch (action) {
446 case ACTION_NONE: 425 case ACTION_NONE:
447 return; 426 return;
448 427
449 case ACTION_UPDATE_VISIBLE_TILES: 428 case ACTION_UPDATE_VISIBLE_TILES:
450 last_frame_number_where_update_visible_tiles_was_called_ = 429 last_frame_number_where_update_visible_tiles_was_called_ =
451 current_frame_number_; 430 current_frame_number_;
452 return; 431 return;
453 432
454 case ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 433 case ACTION_ACTIVATE_PENDING_TREE:
455 last_frame_number_where_tree_activation_attempted_ = 434 UpdateStateOnActivation();
456 current_frame_number_;
457 return; 435 return;
458 436
459 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 437 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
460 DCHECK(!has_pending_tree_); 438 DCHECK(!has_pending_tree_);
461 if (!needs_forced_commit_ && 439 if (!needs_forced_commit_ &&
462 output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) { 440 output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
463 DCHECK(visible_); 441 DCHECK(visible_);
464 DCHECK_GT(current_frame_number_, 442 DCHECK_GT(current_frame_number_,
465 last_frame_number_where_begin_frame_sent_to_main_thread_); 443 last_frame_number_where_begin_frame_sent_to_main_thread_);
466 } 444 }
467 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 445 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
468 needs_commit_ = false; 446 needs_commit_ = false;
469 needs_forced_commit_ = false; 447 needs_forced_commit_ = false;
470 last_frame_number_where_begin_frame_sent_to_main_thread_ = 448 last_frame_number_where_begin_frame_sent_to_main_thread_ =
471 current_frame_number_; 449 current_frame_number_;
472 return; 450 return;
473 451
474 case ACTION_COMMIT: { 452 case ACTION_COMMIT: {
475 bool commit_was_aborted = false; 453 bool commit_was_aborted = false;
476 HandleCommitInternal(commit_was_aborted); 454 UpdateStateOnCommit(commit_was_aborted);
477 return; 455 return;
478 } 456 }
479 457
480 case ACTION_DRAW_FORCED: 458 case ACTION_DRAW_FORCED:
481 case ACTION_DRAW_IF_POSSIBLE: { 459 case ACTION_DRAW_IF_POSSIBLE: {
482 bool did_swap = true; 460 bool did_swap = true;
483 UpdateStateOnDraw(did_swap); 461 UpdateStateOnDraw(did_swap);
484 return; 462 return;
485 } 463 }
486 464
487 case ACTION_DRAW_AND_SWAP_ABORT: { 465 case ACTION_DRAW_AND_SWAP_ABORT: {
488 bool did_swap = false; 466 bool did_swap = false;
489 UpdateStateOnDraw(did_swap); 467 UpdateStateOnDraw(did_swap);
490 return; 468 return;
491 } 469 }
492 470
493 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 471 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
494 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); 472 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
495 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 473 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
496 output_surface_state_ = OUTPUT_SURFACE_CREATING; 474 output_surface_state_ = OUTPUT_SURFACE_CREATING;
497 return; 475 return;
498 476
499 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 477 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
500 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; 478 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
501 main_thread_needs_layer_textures_ = false; 479 main_thread_needs_layer_textures_ = false;
502 return; 480 return;
503 } 481 }
504 } 482 }
505 483
484 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
485 commit_count_++;
486
487 // If we are impl-side-painting but the commit was aborted, then we behave
488 // mostly as if we are not impl-side-painting since there is no pending tree.
489 has_pending_tree_ =
490 settings_.impl_side_painting && !commit_was_aborted;
491
492 // Update the commit state.
493 if (expect_immediate_begin_frame_for_main_thread_)
494 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
495 else if (!commit_was_aborted)
496 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
497 else
498 commit_state_ = COMMIT_STATE_IDLE;
499
500 // Update the output surface state.
501 DCHECK_NE(output_surface_state_,
502 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
503 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
504 if (has_pending_tree_) {
505 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
506 } else {
507 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
508 needs_redraw_ = true;
509 }
510 }
511
512 // Update state if we have a new active tree to draw.
513 if (!has_pending_tree_ &&
514 (!commit_was_aborted || expect_immediate_begin_frame_for_main_thread_)) {
515 needs_redraw_ = true;
516 active_tree_has_been_drawn_ = false;
517 }
518
519 // This post-commit work is common to both completed and aborted commits.
520 pending_tree_is_ready_for_activation_ = false;
521
522 if (draw_if_possible_failed_)
523 last_frame_number_where_draw_was_called_ = -1;
524
525 if (needs_forced_redraw_after_next_commit_) {
526 needs_forced_redraw_after_next_commit_ = false;
527 needs_forced_redraw_ = true;
528 }
529
530 // If we are planing to draw with the new commit, lock the layer textures for
531 // use on the impl thread. Otherwise, leave them unlocked.
532 if (has_pending_tree_ || needs_redraw_ || needs_forced_redraw_)
533 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
534 else
535 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
536 }
537
538 void SchedulerStateMachine::UpdateStateOnActivation() {
539 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
540 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
541
542 has_pending_tree_ = false;
543 pending_tree_is_ready_for_activation_ = false;
544 active_tree_has_been_drawn_ = false;
545 needs_redraw_ = true;
546 }
547
506 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) { 548 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
enne (OOO) 2013/08/26 21:55:13 All of these UpdateStateOnFoo functions make the c
507 if (inside_begin_frame_) 549 if (inside_begin_frame_)
508 last_frame_number_where_draw_was_called_ = current_frame_number_; 550 last_frame_number_where_draw_was_called_ = current_frame_number_;
509 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) { 551 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) {
510 DCHECK(expect_immediate_begin_frame_for_main_thread_); 552 DCHECK(expect_immediate_begin_frame_for_main_thread_);
511 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 553 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
512 expect_immediate_begin_frame_for_main_thread_ = false; 554 expect_immediate_begin_frame_for_main_thread_ = false;
513 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) { 555 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
514 commit_state_ = COMMIT_STATE_IDLE; 556 commit_state_ = COMMIT_STATE_IDLE;
515 } 557 }
516 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) 558 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
517 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 559 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
518 560
519 needs_redraw_ = false; 561 needs_redraw_ = false;
520 needs_forced_redraw_ = false; 562 needs_forced_redraw_ = false;
521 draw_if_possible_failed_ = false; 563 draw_if_possible_failed_ = false;
564 active_tree_has_been_drawn_ = true;
522 565
523 if (did_swap) 566 if (did_swap)
524 swap_used_incomplete_tile_ = false; 567 swap_used_incomplete_tile_ = false;
525 } 568 }
526 569
527 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 570 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
528 DCHECK(!main_thread_needs_layer_textures_); 571 DCHECK(!main_thread_needs_layer_textures_);
529 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 572 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
530 main_thread_needs_layer_textures_ = true; 573 main_thread_needs_layer_textures_ = true;
531 } 574 }
532 575
533 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 576 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
534 // TODO(brianderson): Remove this hack once the Scheduler controls activation,
535 // otherwise we can get stuck in OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION.
536 // It lies that we actually need to draw, but we won't actually draw
537 // if we can't. This will cause WebView to potentially have corruption
538 // in the first few frames, but this workaround is being removed soon.
539 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
540 return true;
541
542 // If we can't draw, don't tick until we are notified that we can draw again. 577 // If we can't draw, don't tick until we are notified that we can draw again.
543 if (!can_draw_) 578 if (!can_draw_)
544 return false; 579 return false;
545 580
546 if (needs_forced_redraw_) 581 if (needs_forced_redraw_)
547 return true; 582 return true;
548 583
549 if (visible_ && swap_used_incomplete_tile_) 584 if (visible_ && swap_used_incomplete_tile_)
550 return true; 585 return true;
551 586
552 return needs_redraw_ && visible_ && HasInitializedOutputSurface(); 587 return needs_redraw_ && visible_ && HasInitializedOutputSurface();
553 } 588 }
554 589
555 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 590 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
556 // Do not be proactive when invisible. 591 // Do not be proactive when invisible.
557 if (!visible_ || output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 592 if (!visible_ || !HasInitializedOutputSurface())
558 return false; 593 return false;
559 594
560 // We should proactively request a BeginFrame if a commit or a tree activation 595 // We should proactively request a BeginFrame if a commit or a tree activation
561 // is pending. 596 // is pending.
562 return (needs_commit_ || needs_forced_commit_ || 597 return (needs_commit_ || needs_forced_commit_ ||
563 commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_); 598 commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_);
564 } 599 }
565 600
566 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 601 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) {
567 current_frame_number_++; 602 current_frame_number_++;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 (expect_immediate_begin_frame_for_main_thread_ && 651 (expect_immediate_begin_frame_for_main_thread_ &&
617 commit_state_ != COMMIT_STATE_IDLE)) 652 commit_state_ != COMMIT_STATE_IDLE))
618 << *AsValue(); 653 << *AsValue();
619 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; 654 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
620 } 655 }
621 656
622 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) { 657 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
623 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS); 658 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
624 if (did_handle) { 659 if (did_handle) {
625 bool commit_was_aborted = true; 660 bool commit_was_aborted = true;
626 HandleCommitInternal(commit_was_aborted); 661 UpdateStateOnCommit(commit_was_aborted);
627 } else if (expect_immediate_begin_frame_for_main_thread_) { 662 } else if (expect_immediate_begin_frame_for_main_thread_) {
628 expect_immediate_begin_frame_for_main_thread_ = false; 663 expect_immediate_begin_frame_for_main_thread_ = false;
629 } else { 664 } else {
630 commit_state_ = COMMIT_STATE_IDLE; 665 commit_state_ = COMMIT_STATE_IDLE;
631 SetNeedsCommit(); 666 SetNeedsCommit();
632 } 667 }
633 } 668 }
634 669
635 void SchedulerStateMachine::DidLoseOutputSurface() { 670 void SchedulerStateMachine::DidLoseOutputSurface() {
636 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 671 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
637 output_surface_state_ == OUTPUT_SURFACE_CREATING) 672 output_surface_state_ == OUTPUT_SURFACE_CREATING)
638 return; 673 return;
639 output_surface_state_ = OUTPUT_SURFACE_LOST; 674 output_surface_state_ = OUTPUT_SURFACE_LOST;
640 needs_redraw_ = false; 675 needs_redraw_ = false;
641 } 676 }
642 677
643 void SchedulerStateMachine::SetHasPendingTree(bool has_pending_tree) { 678 void SchedulerStateMachine::NotifyReadyToActivate() {
644 if (has_pending_tree_ && !has_pending_tree) { 679 if (has_pending_tree_)
645 // There is a new active tree. 680 pending_tree_is_ready_for_activation_ = true;
646 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
647 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
648
649 needs_redraw_ = true;
650 }
651 has_pending_tree_ = has_pending_tree;
652 } 681 }
653 682
654 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; } 683 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; }
655 684
656 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 685 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
657 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 686 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
658 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; 687 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
659 688
660 if (did_create_and_initialize_first_output_surface_) { 689 if (did_create_and_initialize_first_output_surface_) {
661 // TODO(boliu): See if we can remove this when impl-side painting is always 690 // TODO(boliu): See if we can remove this when impl-side painting is always
(...skipping 17 matching lines...) Expand all
679 NOTREACHED(); 708 NOTREACHED();
680 return false; 709 return false;
681 } 710 }
682 711
683 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced( 712 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(
684 int num_draws) { 713 int num_draws) {
685 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws; 714 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws;
686 } 715 }
687 716
688 } // namespace cc 717 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698