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

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

Issue 23796002: cc: Implement deadine scheduling disabled by default (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedReadback4
Patch Set: address enne's comments Created 7 years, 3 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 begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
17 commit_state_(COMMIT_STATE_IDLE), 18 commit_state_(COMMIT_STATE_IDLE),
18 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED), 19 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
19 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), 20 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
20 readback_state_(READBACK_STATE_IDLE), 21 readback_state_(READBACK_STATE_IDLE),
21 commit_count_(0), 22 commit_count_(0),
22 current_frame_number_(0), 23 current_frame_number_(0),
23 last_frame_number_where_begin_frame_sent_to_main_thread_(-1),
24 last_frame_number_swap_performed_(-1), 24 last_frame_number_swap_performed_(-1),
25 last_frame_number_where_update_visible_tiles_was_called_(-1), 25 last_frame_number_begin_frame_sent_to_main_thread_(-1),
26 last_frame_number_update_visible_tiles_was_called_(-1),
26 consecutive_failed_draws_(0), 27 consecutive_failed_draws_(0),
27 needs_redraw_(false), 28 needs_redraw_(false),
28 swap_used_incomplete_tile_(false), 29 swap_used_incomplete_tile_(false),
29 needs_commit_(false), 30 needs_commit_(false),
30 main_thread_needs_layer_textures_(false), 31 main_thread_needs_layer_textures_(false),
31 inside_begin_frame_(false),
32 visible_(false), 32 visible_(false),
33 can_start_(false), 33 can_start_(false),
34 can_draw_(false), 34 can_draw_(false),
35 has_pending_tree_(false), 35 has_pending_tree_(false),
36 pending_tree_is_ready_for_activation_(false), 36 pending_tree_is_ready_for_activation_(false),
37 active_tree_needs_first_draw_(false), 37 active_tree_needs_first_draw_(false),
38 draw_if_possible_failed_(false), 38 draw_if_possible_failed_(false),
39 did_create_and_initialize_first_output_surface_(false) {} 39 did_create_and_initialize_first_output_surface_(false) {}
40 40
41 const char* SchedulerStateMachine::OutputSurfaceStateToString( 41 const char* SchedulerStateMachine::OutputSurfaceStateToString(
42 OutputSurfaceState state) { 42 OutputSurfaceState state) {
43 switch (state) { 43 switch (state) {
44 case OUTPUT_SURFACE_ACTIVE: 44 case OUTPUT_SURFACE_ACTIVE:
45 return "OUTPUT_SURFACE_ACTIVE"; 45 return "OUTPUT_SURFACE_ACTIVE";
46 case OUTPUT_SURFACE_LOST: 46 case OUTPUT_SURFACE_LOST:
47 return "OUTPUT_SURFACE_LOST"; 47 return "OUTPUT_SURFACE_LOST";
48 case OUTPUT_SURFACE_CREATING: 48 case OUTPUT_SURFACE_CREATING:
49 return "OUTPUT_SURFACE_CREATING"; 49 return "OUTPUT_SURFACE_CREATING";
50 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 50 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
51 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT"; 51 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
52 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 52 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
53 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION"; 53 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
54 } 54 }
55 NOTREACHED(); 55 NOTREACHED();
56 return "???"; 56 return "???";
57 } 57 }
58 58
59 const char* SchedulerStateMachine::BeginFrameStateToString(
60 BeginFrameState state) {
61 switch (state) {
62 case BEGIN_FRAME_STATE_IDLE:
63 return "BEGIN_FRAME_STATE_IDLE";
64 case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
65 return "BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME";
66 case BEGIN_FRAME_STATE_DEADLINE_PENDING:
67 return "BEGIN_FRAME_STATE_DEADLINE_PENDING";
68 case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
69 return "BEGIN_FRAME_STATE_INSIDE_DEADLINE";
70 }
71 NOTREACHED();
72 return "???";
73 }
74
59 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { 75 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
60 switch (state) { 76 switch (state) {
61 case COMMIT_STATE_IDLE: 77 case COMMIT_STATE_IDLE:
62 return "COMMIT_STATE_IDLE"; 78 return "COMMIT_STATE_IDLE";
63 case COMMIT_STATE_FRAME_IN_PROGRESS: 79 case COMMIT_STATE_FRAME_IN_PROGRESS:
64 return "COMMIT_STATE_FRAME_IN_PROGRESS"; 80 return "COMMIT_STATE_FRAME_IN_PROGRESS";
65 case COMMIT_STATE_READY_TO_COMMIT: 81 case COMMIT_STATE_READY_TO_COMMIT:
66 return "COMMIT_STATE_READY_TO_COMMIT"; 82 return "COMMIT_STATE_READY_TO_COMMIT";
67 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: 83 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
68 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW"; 84 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 165 }
150 NOTREACHED(); 166 NOTREACHED();
151 return "???"; 167 return "???";
152 } 168 }
153 169
154 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { 170 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
155 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 171 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
156 172
157 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue); 173 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
158 major_state->SetString("next_action", ActionToString(NextAction())); 174 major_state->SetString("next_action", ActionToString(NextAction()));
175 major_state->SetString("begin_frame_state",
176 BeginFrameStateToString(begin_frame_state_));
159 major_state->SetString("commit_state", CommitStateToString(commit_state_)); 177 major_state->SetString("commit_state", CommitStateToString(commit_state_));
160 major_state->SetString("texture_state_", 178 major_state->SetString("texture_state_",
161 TextureStateToString(texture_state_)); 179 TextureStateToString(texture_state_));
162 major_state->SetString("output_surface_state_", 180 major_state->SetString("output_surface_state_",
163 OutputSurfaceStateToString(output_surface_state_)); 181 OutputSurfaceStateToString(output_surface_state_));
164 major_state->SetString( 182 major_state->SetString(
165 "forced_redraw_state", 183 "forced_redraw_state",
166 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); 184 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
167 major_state->SetString("readback_state", 185 major_state->SetString("readback_state",
168 SynchronousReadbackStateToString(readback_state_)); 186 SynchronousReadbackStateToString(readback_state_));
(...skipping 21 matching lines...) Expand all
190 (last_begin_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / 208 (last_begin_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
191 1000.0L); 209 1000.0L);
192 timestamps_state->SetDouble( 210 timestamps_state->SetDouble(
193 "6_deadline", 211 "6_deadline",
194 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / 212 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
195 1000.0L); 213 1000.0L);
196 state->Set("major_timestamps_in_ms", timestamps_state.release()); 214 state->Set("major_timestamps_in_ms", timestamps_state.release());
197 215
198 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); 216 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
199 minor_state->SetInteger("commit_count", commit_count_); 217 minor_state->SetInteger("commit_count", commit_count_);
200 minor_state->SetInteger("current_frame_number", current_frame_number_); 218 minor_state->SetInteger("current_frame_number_", current_frame_number_);
201 minor_state->SetInteger( 219
202 "last_frame_number_where_begin_frame_sent_to_main_thread",
203 last_frame_number_where_begin_frame_sent_to_main_thread_);
204 minor_state->SetInteger("last_frame_number_swap_performed_", 220 minor_state->SetInteger("last_frame_number_swap_performed_",
205 last_frame_number_swap_performed_); 221 last_frame_number_swap_performed_);
206 minor_state->SetInteger( 222 minor_state->SetInteger(
207 "last_frame_number_where_update_visible_tiles_was_called", 223 "last_frame_number_begin_frame_sent_to_main_thread_",
208 last_frame_number_where_update_visible_tiles_was_called_); 224 last_frame_number_begin_frame_sent_to_main_thread_);
209 minor_state->SetInteger("consecutive_failed_draws", 225 minor_state->SetInteger(
226 "last_frame_number_update_visible_tiles_was_called_",
227 last_frame_number_update_visible_tiles_was_called_);
228
229 minor_state->SetInteger("consecutive_failed_draws_",
enne (OOO) 2013/09/12 21:56:22 This is trivial, but this whole section seems to h
210 consecutive_failed_draws_); 230 consecutive_failed_draws_);
211 minor_state->SetBoolean("needs_redraw", needs_redraw_); 231 minor_state->SetBoolean("needs_redraw", needs_redraw_);
212 minor_state->SetBoolean("swap_used_incomplete_tile", 232 minor_state->SetBoolean("swap_used_incomplete_tile",
213 swap_used_incomplete_tile_); 233 swap_used_incomplete_tile_);
214 minor_state->SetBoolean("needs_commit", needs_commit_); 234 minor_state->SetBoolean("needs_commit", needs_commit_);
215 minor_state->SetBoolean("main_thread_needs_layer_textures", 235 minor_state->SetBoolean("main_thread_needs_layer_textures",
216 main_thread_needs_layer_textures_); 236 main_thread_needs_layer_textures_);
217 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_);
218 minor_state->SetBoolean("visible", visible_); 237 minor_state->SetBoolean("visible", visible_);
219 minor_state->SetBoolean("can_start", can_start_); 238 minor_state->SetBoolean("can_start", can_start_);
220 minor_state->SetBoolean("can_draw", can_draw_); 239 minor_state->SetBoolean("can_draw", can_draw_);
221 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); 240 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
222 minor_state->SetBoolean("pending_tree_is_ready_for_activation_", 241 minor_state->SetBoolean("pending_tree_is_ready_for_activation_",
223 pending_tree_is_ready_for_activation_); 242 pending_tree_is_ready_for_activation_);
224 minor_state->SetBoolean("active_tree_needs_first_draw_", 243 minor_state->SetBoolean("active_tree_needs_first_draw_",
225 active_tree_needs_first_draw_); 244 active_tree_needs_first_draw_);
226 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); 245 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
227 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", 246 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
228 did_create_and_initialize_first_output_surface_); 247 did_create_and_initialize_first_output_surface_);
229 state->Set("minor_state", minor_state.release()); 248 state->Set("minor_state", minor_state.release());
230 249
231 return state.PassAs<base::Value>(); 250 return state.PassAs<base::Value>();
232 } 251 }
233 252
234 bool SchedulerStateMachine::HasDrawnAndSwappedThisFrame() const { 253 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
235 return current_frame_number_ == last_frame_number_swap_performed_; 254 return current_frame_number_ ==
255 last_frame_number_begin_frame_sent_to_main_thread_;
236 } 256 }
237 257
238 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 258 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
239 return current_frame_number_ == 259 return current_frame_number_ ==
240 last_frame_number_where_update_visible_tiles_was_called_; 260 last_frame_number_update_visible_tiles_was_called_;
241 } 261 }
242 262
243 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const { 263 bool SchedulerStateMachine::HasSwappedThisFrame() const {
244 return current_frame_number_ == 264 return current_frame_number_ == last_frame_number_swap_performed_;
245 last_frame_number_where_begin_frame_sent_to_main_thread_;
246 } 265 }
247 266
248 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 267 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
249 // These are all the cases where we normally cannot or do not want to draw 268 // These are all the cases where we normally cannot or do not want to draw
250 // but, if needs_redraw_ is true and we do not draw to make forward progress, 269 // but, if needs_redraw_ is true and we do not draw to make forward progress,
251 // we might deadlock with the main thread. 270 // we might deadlock with the main thread.
252 // This should be a superset of PendingActivationsShouldBeForced() since 271 // This should be a superset of PendingActivationsShouldBeForced() since
253 // activation of the pending tree is blocked by drawing of the active tree and 272 // activation of the pending tree is blocked by drawing of the active tree and
254 // the main thread might be blocked on activation of the most recent commit. 273 // the main thread might be blocked on activation of the most recent commit.
255 if (PendingActivationsShouldBeForced()) 274 if (PendingActivationsShouldBeForced())
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 337 }
319 338
320 // If we need to abort draws, we should do so ASAP since the draw could 339 // If we need to abort draws, we should do so ASAP since the draw could
321 // be blocking other important actions (like output surface initialization), 340 // be blocking other important actions (like output surface initialization),
322 // from occuring. If we are waiting for the first draw, then perfom the 341 // from occuring. If we are waiting for the first draw, then perfom the
323 // aborted draw to keep things moving. If we are not waiting for the first 342 // aborted draw to keep things moving. If we are not waiting for the first
324 // draw however, we don't want to abort for no reason. 343 // draw however, we don't want to abort for no reason.
325 if (PendingDrawsShouldBeAborted()) 344 if (PendingDrawsShouldBeAborted())
326 return active_tree_needs_first_draw_; 345 return active_tree_needs_first_draw_;
327 346
328 // After this line, we only want to draw once per frame. 347 // After this line, we only want to swap once per frame.
329 if (HasDrawnAndSwappedThisFrame()) 348 if (HasSwappedThisFrame())
330 return false; 349 return false;
331 350
332 // We currently only draw within the BeginFrame. 351 // Except for the cases above, do not draw outside of the BeginFrame deadline.
333 if (!inside_begin_frame_) 352 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
334 return false; 353 return false;
335 354
336 // Only handle forced redraws due to timeouts on the regular deadline. 355 // Only handle forced redraws due to timeouts on the regular deadline.
337 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { 356 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
338 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 357 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
339 return true; 358 return true;
340 } 359 }
341 360
342 return needs_redraw_; 361 return needs_redraw_;
343 } 362 }
(...skipping 29 matching lines...) Expand all
373 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 392 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
374 if (!settings_.impl_side_painting) 393 if (!settings_.impl_side_painting)
375 return false; 394 return false;
376 if (HasUpdatedVisibleTilesThisFrame()) 395 if (HasUpdatedVisibleTilesThisFrame())
377 return false; 396 return false;
378 397
379 // There's no reason to check for tiles if we don't have an output surface. 398 // There's no reason to check for tiles if we don't have an output surface.
380 if (!HasInitializedOutputSurface()) 399 if (!HasInitializedOutputSurface())
381 return false; 400 return false;
382 401
383 // We always want to update the most recent visible tiles before drawing 402 // We should not check for visible tiles until we've entered the deadline so
384 // so we draw with fewer missing tiles. 403 // we check as late possible and give the tiles more time to initialize.
385 if (ShouldDraw()) 404 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
386 return true; 405 return false;
387 406
388 // If the last swap drew with checkerboard or missing tiles, we should 407 // If the last swap drew with checkerboard or missing tiles, we should
389 // poll for any new visible tiles so we can be notified to draw again 408 // poll for any new visible tiles so we can be notified to draw again
390 // when there are. 409 // when there are.
391 if (swap_used_incomplete_tile_) 410 if (swap_used_incomplete_tile_)
392 return true; 411 return true;
393 412
394 return false; 413 return false;
395 } 414 }
396 415
397 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const { 416 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
398 if (!needs_commit_) 417 if (!needs_commit_)
399 return false; 418 return false;
400 419
401 // Only send BeginFrame to the main thread when idle. 420 // Only send BeginFrame to the main thread when there isn't another commit
421 // pending already.
402 if (commit_state_ != COMMIT_STATE_IDLE) 422 if (commit_state_ != COMMIT_STATE_IDLE)
403 return false; 423 return false;
404 424
405 // We can't accept a commit if we have a pending tree. 425 // We can't accept a commit if we have a pending tree.
406 if (has_pending_tree_) 426 if (has_pending_tree_)
407 return false; 427 return false;
408 428
409 // We want to handle readback commits immediately to unblock the main thread. 429 // We want to handle readback commits immediately to unblock the main thread.
410 // Note: This BeginFrame will correspond to the replacement commit that comes 430 // Note: This BeginFrame will correspond to the replacement commit that comes
411 // after the readback commit itself, so we only send the BeginFrame if a 431 // after the readback commit itself, so we only send the BeginFrame if a
412 // commit isn't already pending behind the readback. 432 // commit isn't already pending behind the readback.
413 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME) 433 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
414 return !CommitPending(); 434 return !CommitPending();
415 435
416 // We do not need commits if we are not visible, unless there's a 436 // We do not need commits if we are not visible, unless there's a
417 // request for a forced commit. 437 // request for a readback.
418 if (!visible_) 438 if (!visible_)
419 return false; 439 return false;
420 440
441 // We shouldn't normally accept commits if there isn't an OutputSurface.
442 if (!HasInitializedOutputSurface())
443 return false;
444
421 // We want to start the first commit after we get a new output surface ASAP. 445 // We want to start the first commit after we get a new output surface ASAP.
422 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) 446 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
423 return true; 447 return true;
424 448
449 // We should not send the BeginFrame to the main thread while we are in
450 // BEGIN_FRAME_STATE_IDLE since we might have new user input coming in soon.
451 // However, if we are not expecting a BeginFrame to take us out of idle,
452 // we should not early out here to avoid blocking commits forever.
453 // TODO(brianderson): Also allow sending BeginFrame to main thread while idle
454 // when the main thread isn't consuming user input.
455 if (begin_frame_state_ == BEGIN_FRAME_STATE_IDLE &&
456 BeginFrameNeededByImplThread())
457 return false;
458
425 // We need a new commit for the forced redraw. This honors the 459 // We need a new commit for the forced redraw. This honors the
426 // single commit per interval because the result will be swapped to screen. 460 // single commit per interval because the result will be swapped to screen.
427 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) 461 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
428 return true; 462 return true;
429 463
430 // After this point, we only start a commit once per frame. 464 // After this point, we only start a commit once per frame.
431 if (HasSentBeginFrameToMainThreadThisFrame()) 465 if (HasSentBeginFrameToMainThreadThisFrame())
432 return false; 466 return false;
433 467
434 // We shouldn't normally accept commits if there isn't an OutputSurface.
435 if (!HasInitializedOutputSurface())
436 return false;
437
438 return true; 468 return true;
439 } 469 }
440 470
441 bool SchedulerStateMachine::ShouldCommit() const { 471 bool SchedulerStateMachine::ShouldCommit() const {
442 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; 472 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
443 } 473 }
444 474
445 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 475 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
446 if (ShouldAcquireLayerTexturesForMainThread()) 476 if (ShouldAcquireLayerTexturesForMainThread())
447 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 477 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
(...skipping 26 matching lines...) Expand all
474 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW && 504 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
475 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)); 505 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
476 } 506 }
477 507
478 void SchedulerStateMachine::UpdateState(Action action) { 508 void SchedulerStateMachine::UpdateState(Action action) {
479 switch (action) { 509 switch (action) {
480 case ACTION_NONE: 510 case ACTION_NONE:
481 return; 511 return;
482 512
483 case ACTION_UPDATE_VISIBLE_TILES: 513 case ACTION_UPDATE_VISIBLE_TILES:
484 last_frame_number_where_update_visible_tiles_was_called_ = 514 last_frame_number_update_visible_tiles_was_called_ =
485 current_frame_number_; 515 current_frame_number_;
486 return; 516 return;
487 517
488 case ACTION_ACTIVATE_PENDING_TREE: 518 case ACTION_ACTIVATE_PENDING_TREE:
489 UpdateStateOnActivation(); 519 UpdateStateOnActivation();
490 return; 520 return;
491 521
492 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 522 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
493 DCHECK(!has_pending_tree_); 523 DCHECK(!has_pending_tree_);
494 DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME); 524 DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME);
495 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 525 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
496 needs_commit_ = false; 526 needs_commit_ = false;
497 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME) 527 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
498 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT; 528 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
499 last_frame_number_where_begin_frame_sent_to_main_thread_ = 529 last_frame_number_begin_frame_sent_to_main_thread_ =
500 current_frame_number_; 530 current_frame_number_;
501 return; 531 return;
502 532
503 case ACTION_COMMIT: { 533 case ACTION_COMMIT: {
504 bool commit_was_aborted = false; 534 bool commit_was_aborted = false;
505 UpdateStateOnCommit(commit_was_aborted); 535 UpdateStateOnCommit(commit_was_aborted);
506 return; 536 return;
507 } 537 }
508 538
509 case ACTION_DRAW_AND_SWAP_FORCED: 539 case ACTION_DRAW_AND_SWAP_FORCED:
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 if (did_swap) 706 if (did_swap)
677 last_frame_number_swap_performed_ = current_frame_number_; 707 last_frame_number_swap_performed_ = current_frame_number_;
678 } 708 }
679 709
680 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 710 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
681 DCHECK(!main_thread_needs_layer_textures_); 711 DCHECK(!main_thread_needs_layer_textures_);
682 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 712 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
683 main_thread_needs_layer_textures_ = true; 713 main_thread_needs_layer_textures_ = true;
684 } 714 }
685 715
716 bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
717 // Proactive BeginFrames are bad for the synchronous compositor because we
718 // have to draw when we get the BeginFrame and could end up drawing many
719 // duplicate frames if our new frame isn't ready in time.
720 if (settings_.using_synchronous_renderer_compositor)
721 return BeginFrameNeededToDrawByImplThread();
722
723 return BeginFrameNeededToDrawByImplThread() ||
724 ProactiveBeginFrameWantedByImplThread();
725 }
726
727 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
728 return !BeginFrameNeededByImplThread() &&
729 ProactiveBeginFrameWantedByImplThread();
730 }
731
686 // These are the cases where we definitely (or almost definitely) have a 732 // These are the cases where we definitely (or almost definitely) have a
687 // new frame to draw and can draw. 733 // new frame to draw and can draw.
688 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 734 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
689 // The output surface is the provider of BeginFrames for the impl thread, 735 // The output surface is the provider of BeginFrames for the impl thread,
690 // so we are not going to get them even if we ask for them. 736 // so we are not going to get them even if we ask for them.
691 if (!HasInitializedOutputSurface()) 737 if (!HasInitializedOutputSurface())
692 return false; 738 return false;
693 739
694 // If we can't draw, don't tick until we are notified that we can draw again. 740 // If we can't draw, don't tick until we are notified that we can draw again.
695 if (!can_draw_) 741 if (!can_draw_)
(...skipping 14 matching lines...) Expand all
710 if (swap_used_incomplete_tile_) 756 if (swap_used_incomplete_tile_)
711 return true; 757 return true;
712 758
713 return needs_redraw_; 759 return needs_redraw_;
714 } 760 }
715 761
716 // These are cases where we are very likely to draw soon, but might not 762 // These are cases where we are very likely to draw soon, but might not
717 // actually have a new frame to draw when we receive the next BeginFrame. 763 // actually have a new frame to draw when we receive the next BeginFrame.
718 // Proactively requesting the BeginFrame helps hide the round trip latency of 764 // Proactively requesting the BeginFrame helps hide the round trip latency of
719 // the SetNeedsBeginFrame request that has to go to the Browser. 765 // the SetNeedsBeginFrame request that has to go to the Browser.
720 // However, this is bad for the synchronous compositor because we have to
721 // draw when we get the BeginFrame and could end up drawing many duplicate
722 // frames.
723 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 766 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
724 // The output surface is the provider of BeginFrames for the impl thread, 767 // The output surface is the provider of BeginFrames for the impl thread,
725 // so we are not going to get them even if we ask for them. 768 // so we are not going to get them even if we ask for them.
726 if (!HasInitializedOutputSurface()) 769 if (!HasInitializedOutputSurface())
727 return false; 770 return false;
728 771
772 // Do not be proactive if vsync is off.
773 if (!settings_.throttle_frame_production)
774 return false;
775
729 // Do not be proactive when invisible. 776 // Do not be proactive when invisible.
730 if (!visible_) 777 if (!visible_)
731 return false; 778 return false;
732 779
733 // We should proactively request a BeginFrame if a commit is pending 780 // We should proactively request a BeginFrame if a commit is pending
734 // because we will want to draw if the commit completes quickly. 781 // because we will want to draw if the commit completes quickly.
735 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) 782 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
736 return true; 783 return true;
737 784
738 // If the pending tree activates quickly, we'll want a BeginFrame soon 785 // If the pending tree activates quickly, we'll want a BeginFrame soon
739 // to draw the new active tree. 786 // to draw the new active tree.
740 if (has_pending_tree_) 787 if (has_pending_tree_)
741 return true; 788 return true;
742 789
743 return false; 790 return false;
744 } 791 }
745 792
746 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 793 void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
747 current_frame_number_++; 794 current_frame_number_++;
748 inside_begin_frame_ = true;
749 last_begin_frame_args_ = args; 795 last_begin_frame_args_ = args;
796 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_IDLE)
797 << *AsValue();
798 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
750 } 799 }
751 800
752 void SchedulerStateMachine::DidLeaveBeginFrame() { 801 void SchedulerStateMachine::OnBeginFrameDeadlinePending() {
753 inside_begin_frame_ = false; 802 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
803 << *AsValue();
804 begin_frame_state_ = BEGIN_FRAME_STATE_DEADLINE_PENDING;
805 }
806
807 void SchedulerStateMachine::OnBeginFrameDeadline() {
808 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_DEADLINE_PENDING)
809 << *AsValue();
810 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
811 }
812
813 void SchedulerStateMachine::OnBeginFrameIdle() {
814 if (HasInitializedOutputSurface()) {
815 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_DEADLINE)
816 << *AsValue();
817 }
818 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
819 }
820
821 bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
822 // TODO(brianderson): This should take into account multiple commit sources.
823 return begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING &&
824 active_tree_needs_first_draw_;
754 } 825 }
755 826
756 void SchedulerStateMachine::PollForAnticipatedDrawTriggers() { 827 void SchedulerStateMachine::PollForAnticipatedDrawTriggers() {
757 current_frame_number_++; 828 current_frame_number_++;
758 } 829 }
759 830
760 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 831 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
761 832
833 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
834
762 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 835 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
763 836
764 void SchedulerStateMachine::SetSwapUsedIncompleteTile( 837 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
765 bool used_incomplete_tile) { 838 bool used_incomplete_tile) {
766 swap_used_incomplete_tile_ = used_incomplete_tile; 839 swap_used_incomplete_tile_ = used_incomplete_tile;
767 } 840 }
768 841
769 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { 842 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
770 draw_if_possible_failed_ = !success; 843 draw_if_possible_failed_ = !success;
771 if (draw_if_possible_failed_) { 844 if (draw_if_possible_failed_) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 SetNeedsCommit(); 897 SetNeedsCommit();
825 } 898 }
826 } 899 }
827 900
828 void SchedulerStateMachine::DidLoseOutputSurface() { 901 void SchedulerStateMachine::DidLoseOutputSurface() {
829 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 902 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
830 output_surface_state_ == OUTPUT_SURFACE_CREATING) 903 output_surface_state_ == OUTPUT_SURFACE_CREATING)
831 return; 904 return;
832 output_surface_state_ = OUTPUT_SURFACE_LOST; 905 output_surface_state_ = OUTPUT_SURFACE_LOST;
833 needs_redraw_ = false; 906 needs_redraw_ = false;
907 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
834 } 908 }
835 909
836 void SchedulerStateMachine::NotifyReadyToActivate() { 910 void SchedulerStateMachine::NotifyReadyToActivate() {
837 if (has_pending_tree_) 911 if (has_pending_tree_)
838 pending_tree_is_ready_for_activation_ = true; 912 pending_tree_is_ready_for_activation_ = true;
839 } 913 }
840 914
841 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; }
842
843 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 915 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
844 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 916 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
845 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; 917 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
846 918
847 if (did_create_and_initialize_first_output_surface_) { 919 if (did_create_and_initialize_first_output_surface_) {
848 // TODO(boliu): See if we can remove this when impl-side painting is always 920 // TODO(boliu): See if we can remove this when impl-side painting is always
849 // on. Does anything on the main thread need to update after recreate? 921 // on. Does anything on the main thread need to update after recreate?
850 needs_commit_ = true; 922 needs_commit_ = true;
851 } 923 }
852 did_create_and_initialize_first_output_surface_ = true; 924 did_create_and_initialize_first_output_surface_ = true;
853 } 925 }
854 926
855 bool SchedulerStateMachine::HasInitializedOutputSurface() const { 927 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
856 switch (output_surface_state_) { 928 switch (output_surface_state_) {
857 case OUTPUT_SURFACE_LOST: 929 case OUTPUT_SURFACE_LOST:
858 case OUTPUT_SURFACE_CREATING: 930 case OUTPUT_SURFACE_CREATING:
859 return false; 931 return false;
860 932
861 case OUTPUT_SURFACE_ACTIVE: 933 case OUTPUT_SURFACE_ACTIVE:
862 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 934 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
863 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 935 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
864 return true; 936 return true;
865 } 937 }
866 NOTREACHED(); 938 NOTREACHED();
867 return false; 939 return false;
868 } 940 }
869 941
870 } // namespace cc 942 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698