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

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

Issue 24304002: cc: Implement deadline scheduling disabled by default (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase 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 needs_manage_tiles_(false), 29 needs_manage_tiles_(false),
29 swap_used_incomplete_tile_(false), 30 swap_used_incomplete_tile_(false),
30 needs_commit_(false), 31 needs_commit_(false),
31 main_thread_needs_layer_textures_(false), 32 main_thread_needs_layer_textures_(false),
32 inside_begin_frame_(false),
33 inside_poll_for_anticipated_draw_triggers_(false), 33 inside_poll_for_anticipated_draw_triggers_(false),
34 visible_(false), 34 visible_(false),
35 can_start_(false), 35 can_start_(false),
36 can_draw_(false), 36 can_draw_(false),
37 has_pending_tree_(false), 37 has_pending_tree_(false),
38 pending_tree_is_ready_for_activation_(false), 38 pending_tree_is_ready_for_activation_(false),
39 active_tree_needs_first_draw_(false), 39 active_tree_needs_first_draw_(false),
40 draw_if_possible_failed_(false), 40 draw_if_possible_failed_(false),
41 did_create_and_initialize_first_output_surface_(false) {} 41 did_create_and_initialize_first_output_surface_(false) {}
42 42
43 const char* SchedulerStateMachine::OutputSurfaceStateToString( 43 const char* SchedulerStateMachine::OutputSurfaceStateToString(
44 OutputSurfaceState state) { 44 OutputSurfaceState state) {
45 switch (state) { 45 switch (state) {
46 case OUTPUT_SURFACE_ACTIVE: 46 case OUTPUT_SURFACE_ACTIVE:
47 return "OUTPUT_SURFACE_ACTIVE"; 47 return "OUTPUT_SURFACE_ACTIVE";
48 case OUTPUT_SURFACE_LOST: 48 case OUTPUT_SURFACE_LOST:
49 return "OUTPUT_SURFACE_LOST"; 49 return "OUTPUT_SURFACE_LOST";
50 case OUTPUT_SURFACE_CREATING: 50 case OUTPUT_SURFACE_CREATING:
51 return "OUTPUT_SURFACE_CREATING"; 51 return "OUTPUT_SURFACE_CREATING";
52 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 52 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
53 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT"; 53 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
54 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 54 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
55 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION"; 55 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
56 } 56 }
57 NOTREACHED(); 57 NOTREACHED();
58 return "???"; 58 return "???";
59 } 59 }
60 60
61 const char* SchedulerStateMachine::BeginFrameStateToString(
62 BeginFrameState state) {
63 switch (state) {
64 case BEGIN_FRAME_STATE_IDLE:
65 return "BEGIN_FRAME_STATE_IDLE";
66 case BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING:
67 return "BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING";
68 case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
69 return "BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME";
70 case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
71 return "BEGIN_FRAME_STATE_INSIDE_DEADLINE";
72 }
73 NOTREACHED();
74 return "???";
75 }
76
61 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { 77 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
62 switch (state) { 78 switch (state) {
63 case COMMIT_STATE_IDLE: 79 case COMMIT_STATE_IDLE:
64 return "COMMIT_STATE_IDLE"; 80 return "COMMIT_STATE_IDLE";
65 case COMMIT_STATE_FRAME_IN_PROGRESS: 81 case COMMIT_STATE_FRAME_IN_PROGRESS:
66 return "COMMIT_STATE_FRAME_IN_PROGRESS"; 82 return "COMMIT_STATE_FRAME_IN_PROGRESS";
67 case COMMIT_STATE_READY_TO_COMMIT: 83 case COMMIT_STATE_READY_TO_COMMIT:
68 return "COMMIT_STATE_READY_TO_COMMIT"; 84 return "COMMIT_STATE_READY_TO_COMMIT";
69 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: 85 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
70 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW"; 86 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 } 169 }
154 NOTREACHED(); 170 NOTREACHED();
155 return "???"; 171 return "???";
156 } 172 }
157 173
158 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { 174 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
159 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 175 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
160 176
161 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue); 177 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
162 major_state->SetString("next_action", ActionToString(NextAction())); 178 major_state->SetString("next_action", ActionToString(NextAction()));
179 major_state->SetString("begin_frame_state",
180 BeginFrameStateToString(begin_frame_state_));
163 major_state->SetString("commit_state", CommitStateToString(commit_state_)); 181 major_state->SetString("commit_state", CommitStateToString(commit_state_));
164 major_state->SetString("texture_state_", 182 major_state->SetString("texture_state_",
165 TextureStateToString(texture_state_)); 183 TextureStateToString(texture_state_));
166 major_state->SetString("output_surface_state_", 184 major_state->SetString("output_surface_state_",
167 OutputSurfaceStateToString(output_surface_state_)); 185 OutputSurfaceStateToString(output_surface_state_));
168 major_state->SetString( 186 major_state->SetString(
169 "forced_redraw_state", 187 "forced_redraw_state",
170 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); 188 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
171 major_state->SetString("readback_state", 189 major_state->SetString("readback_state",
172 SynchronousReadbackStateToString(readback_state_)); 190 SynchronousReadbackStateToString(readback_state_));
(...skipping 22 matching lines...) Expand all
195 1000.0L); 213 1000.0L);
196 timestamps_state->SetDouble( 214 timestamps_state->SetDouble(
197 "6_deadline", 215 "6_deadline",
198 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / 216 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
199 1000.0L); 217 1000.0L);
200 state->Set("major_timestamps_in_ms", timestamps_state.release()); 218 state->Set("major_timestamps_in_ms", timestamps_state.release());
201 219
202 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); 220 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
203 minor_state->SetInteger("commit_count", commit_count_); 221 minor_state->SetInteger("commit_count", commit_count_);
204 minor_state->SetInteger("current_frame_number", current_frame_number_); 222 minor_state->SetInteger("current_frame_number", current_frame_number_);
205 minor_state->SetInteger( 223
206 "last_frame_number_where_begin_frame_sent_to_main_thread", 224 minor_state->SetInteger("last_frame_number_swap_performed",
207 last_frame_number_where_begin_frame_sent_to_main_thread_);
208 minor_state->SetInteger("last_frame_number_swap_performed_",
209 last_frame_number_swap_performed_); 225 last_frame_number_swap_performed_);
210 minor_state->SetInteger( 226 minor_state->SetInteger(
211 "last_frame_number_where_update_visible_tiles_was_called", 227 "last_frame_number_begin_frame_sent_to_main_thread",
212 last_frame_number_where_update_visible_tiles_was_called_); 228 last_frame_number_begin_frame_sent_to_main_thread_);
229 minor_state->SetInteger(
230 "last_frame_number_update_visible_tiles_was_called",
231 last_frame_number_update_visible_tiles_was_called_);
232
213 minor_state->SetInteger("consecutive_failed_draws", 233 minor_state->SetInteger("consecutive_failed_draws",
214 consecutive_failed_draws_); 234 consecutive_failed_draws_);
215 minor_state->SetBoolean("needs_redraw", needs_redraw_); 235 minor_state->SetBoolean("needs_redraw", needs_redraw_);
216 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_); 236 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
217 minor_state->SetBoolean("swap_used_incomplete_tile", 237 minor_state->SetBoolean("swap_used_incomplete_tile",
218 swap_used_incomplete_tile_); 238 swap_used_incomplete_tile_);
219 minor_state->SetBoolean("needs_commit", needs_commit_); 239 minor_state->SetBoolean("needs_commit", needs_commit_);
220 minor_state->SetBoolean("main_thread_needs_layer_textures", 240 minor_state->SetBoolean("main_thread_needs_layer_textures",
221 main_thread_needs_layer_textures_); 241 main_thread_needs_layer_textures_);
222 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_);
223 minor_state->SetBoolean("visible", visible_); 242 minor_state->SetBoolean("visible", visible_);
224 minor_state->SetBoolean("can_start", can_start_); 243 minor_state->SetBoolean("can_start", can_start_);
225 minor_state->SetBoolean("can_draw", can_draw_); 244 minor_state->SetBoolean("can_draw", can_draw_);
226 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); 245 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
227 minor_state->SetBoolean("pending_tree_is_ready_for_activation_", 246 minor_state->SetBoolean("pending_tree_is_ready_for_activation",
228 pending_tree_is_ready_for_activation_); 247 pending_tree_is_ready_for_activation_);
229 minor_state->SetBoolean("active_tree_needs_first_draw_", 248 minor_state->SetBoolean("active_tree_needs_first_draw",
230 active_tree_needs_first_draw_); 249 active_tree_needs_first_draw_);
231 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); 250 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
232 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", 251 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
233 did_create_and_initialize_first_output_surface_); 252 did_create_and_initialize_first_output_surface_);
234 state->Set("minor_state", minor_state.release()); 253 state->Set("minor_state", minor_state.release());
235 254
236 return state.PassAs<base::Value>(); 255 return state.PassAs<base::Value>();
237 } 256 }
238 257
239 bool SchedulerStateMachine::HasDrawnAndSwappedThisFrame() const { 258 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
240 return current_frame_number_ == last_frame_number_swap_performed_; 259 return current_frame_number_ ==
260 last_frame_number_begin_frame_sent_to_main_thread_;
241 } 261 }
242 262
243 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 263 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
244 return current_frame_number_ == 264 return current_frame_number_ ==
245 last_frame_number_where_update_visible_tiles_was_called_; 265 last_frame_number_update_visible_tiles_was_called_;
246 } 266 }
247 267
248 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const { 268 bool SchedulerStateMachine::HasSwappedThisFrame() const {
249 return current_frame_number_ == 269 return current_frame_number_ == last_frame_number_swap_performed_;
250 last_frame_number_where_begin_frame_sent_to_main_thread_;
251 } 270 }
252 271
253 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 272 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
254 // These are all the cases where we normally cannot or do not want to draw 273 // These are all the cases where we normally cannot or do not want to draw
255 // but, if needs_redraw_ is true and we do not draw to make forward progress, 274 // but, if needs_redraw_ is true and we do not draw to make forward progress,
256 // we might deadlock with the main thread. 275 // we might deadlock with the main thread.
257 // This should be a superset of PendingActivationsShouldBeForced() since 276 // This should be a superset of PendingActivationsShouldBeForced() since
258 // activation of the pending tree is blocked by drawing of the active tree and 277 // activation of the pending tree is blocked by drawing of the active tree and
259 // the main thread might be blocked on activation of the most recent commit. 278 // the main thread might be blocked on activation of the most recent commit.
260 if (PendingActivationsShouldBeForced()) 279 if (PendingActivationsShouldBeForced())
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 342 }
324 343
325 // If we need to abort draws, we should do so ASAP since the draw could 344 // If we need to abort draws, we should do so ASAP since the draw could
326 // be blocking other important actions (like output surface initialization), 345 // be blocking other important actions (like output surface initialization),
327 // from occuring. If we are waiting for the first draw, then perfom the 346 // from occuring. If we are waiting for the first draw, then perfom the
328 // aborted draw to keep things moving. If we are not waiting for the first 347 // aborted draw to keep things moving. If we are not waiting for the first
329 // draw however, we don't want to abort for no reason. 348 // draw however, we don't want to abort for no reason.
330 if (PendingDrawsShouldBeAborted()) 349 if (PendingDrawsShouldBeAborted())
331 return active_tree_needs_first_draw_; 350 return active_tree_needs_first_draw_;
332 351
333 // After this line, we only want to draw once per frame. 352 // After this line, we only want to swap once per frame.
334 if (HasDrawnAndSwappedThisFrame()) 353 if (HasSwappedThisFrame())
335 return false; 354 return false;
336 355
337 // We currently only draw within the BeginFrame. 356 // Except for the cases above, do not draw outside of the BeginFrame deadline.
338 if (!inside_begin_frame_) 357 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
339 return false; 358 return false;
340 359
341 // Only handle forced redraws due to timeouts on the regular deadline. 360 // Only handle forced redraws due to timeouts on the regular deadline.
342 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { 361 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
343 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 362 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
344 return true; 363 return true;
345 } 364 }
346 365
347 return needs_redraw_; 366 return needs_redraw_;
348 } 367 }
(...skipping 29 matching lines...) Expand all
378 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 397 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
379 if (!settings_.impl_side_painting) 398 if (!settings_.impl_side_painting)
380 return false; 399 return false;
381 if (HasUpdatedVisibleTilesThisFrame()) 400 if (HasUpdatedVisibleTilesThisFrame())
382 return false; 401 return false;
383 402
384 // There's no reason to check for tiles if we don't have an output surface. 403 // There's no reason to check for tiles if we don't have an output surface.
385 if (!HasInitializedOutputSurface()) 404 if (!HasInitializedOutputSurface())
386 return false; 405 return false;
387 406
388 // We always want to update the most recent visible tiles before drawing 407 // We should not check for visible tiles until we've entered the deadline so
389 // so we draw with fewer missing tiles. 408 // we check as late as possible and give the tiles more time to initialize.
390 if (ShouldDraw()) 409 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
391 return true; 410 return false;
392 411
393 // If the last swap drew with checkerboard or missing tiles, we should 412 // If the last swap drew with checkerboard or missing tiles, we should
394 // poll for any new visible tiles so we can be notified to draw again 413 // poll for any new visible tiles so we can be notified to draw again
395 // when there are. 414 // when there are.
396 if (swap_used_incomplete_tile_) 415 if (swap_used_incomplete_tile_)
397 return true; 416 return true;
398 417
399 return false; 418 return false;
400 } 419 }
401 420
402 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const { 421 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
403 if (!needs_commit_) 422 if (!needs_commit_)
404 return false; 423 return false;
405 424
406 // Only send BeginFrame to the main thread when idle. 425 // Only send BeginFrame to the main thread when there isn't another commit
426 // pending already.
407 if (commit_state_ != COMMIT_STATE_IDLE) 427 if (commit_state_ != COMMIT_STATE_IDLE)
408 return false; 428 return false;
409 429
410 // We can't accept a commit if we have a pending tree. 430 // We can't accept a commit if we have a pending tree.
411 if (has_pending_tree_) 431 if (has_pending_tree_)
412 return false; 432 return false;
413 433
414 // We want to handle readback commits immediately to unblock the main thread. 434 // We want to handle readback commits immediately to unblock the main thread.
415 // Note: This BeginFrame will correspond to the replacement commit that comes 435 // Note: This BeginFrame will correspond to the replacement commit that comes
416 // after the readback commit itself, so we only send the BeginFrame if a 436 // after the readback commit itself, so we only send the BeginFrame if a
417 // commit isn't already pending behind the readback. 437 // commit isn't already pending behind the readback.
418 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME) 438 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
419 return !CommitPending(); 439 return !CommitPending();
420 440
421 // We do not need commits if we are not visible, unless there's a 441 // We do not need commits if we are not visible, unless there's a
422 // request for a forced commit. 442 // request for a readback.
423 if (!visible_) 443 if (!visible_)
424 return false; 444 return false;
425 445
426 // We want to start the first commit after we get a new output surface ASAP. 446 // We want to start the first commit after we get a new output surface ASAP.
427 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) 447 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
428 return true; 448 return true;
429 449
450 // With deadline scheduling enabled, we should not send BeginFrame to the
451 // main thread while we are in BEGIN_FRAME_STATE_IDLE, since we might have
452 // new user input coming in soon.
453 // However, if we are not expecting a BeginFrame on the Impl thread to take
454 // us out of idle, we should not early out here to avoid blocking commits
455 // forever.
456 // This only works well when deadline scheduling is enabled because there is
457 // an interval over which to accept the commit and draw. Without deadline
458 // scheduling, delaying the commit could prevent us from having something
459 // to draw on the next BeginFrame.
460 // TODO(brianderson): Allow sending BeginFrame to main thread while idle
461 // when the main thread isn't consuming user input.
462 if (settings_.deadline_scheduling_enabled &&
463 begin_frame_state_ == BEGIN_FRAME_STATE_IDLE &&
464 BeginFrameNeededByImplThread())
465 return false;
466
430 // We need a new commit for the forced redraw. This honors the 467 // We need a new commit for the forced redraw. This honors the
431 // single commit per interval because the result will be swapped to screen. 468 // single commit per interval because the result will be swapped to screen.
432 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) 469 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
433 return true; 470 return true;
434 471
435 // After this point, we only start a commit once per frame. 472 // After this point, we only start a commit once per frame.
436 if (HasSentBeginFrameToMainThreadThisFrame()) 473 if (HasSentBeginFrameToMainThreadThisFrame())
437 return false; 474 return false;
438 475
439 // We shouldn't normally accept commits if there isn't an OutputSurface. 476 // We shouldn't normally accept commits if there isn't an OutputSurface.
440 if (!HasInitializedOutputSurface()) 477 if (!HasInitializedOutputSurface())
441 return false; 478 return false;
442 479
443 return true; 480 return true;
444 } 481 }
445 482
446 bool SchedulerStateMachine::ShouldCommit() const { 483 bool SchedulerStateMachine::ShouldCommit() const {
447 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; 484 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
448 } 485 }
449 486
450 bool SchedulerStateMachine::ShouldManageTiles() const { 487 bool SchedulerStateMachine::ShouldManageTiles() const {
451 // Limiting to once per-frame is not enough, since we only want to 488 // Limiting to once per-frame is not enough, since we only want to
452 // manage tiles _after_ draws. Polling for draw triggers and 489 // manage tiles _after_ draws. Polling for draw triggers and
453 // begin-frame are mutually exclusive, so we limit to these two cases. 490 // begin-frame are mutually exclusive, so we limit to these two cases.
454 if (!inside_begin_frame_ && !inside_poll_for_anticipated_draw_triggers_) 491 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE &&
492 !inside_poll_for_anticipated_draw_triggers_)
455 return false; 493 return false;
456 return needs_manage_tiles_; 494 return needs_manage_tiles_;
457 } 495 }
458 496
459 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 497 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
460 if (ShouldAcquireLayerTexturesForMainThread()) 498 if (ShouldAcquireLayerTexturesForMainThread())
461 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 499 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
462 if (ShouldUpdateVisibleTiles()) 500 if (ShouldUpdateVisibleTiles())
463 return ACTION_UPDATE_VISIBLE_TILES; 501 return ACTION_UPDATE_VISIBLE_TILES;
464 if (ShouldActivatePendingTree()) 502 if (ShouldActivatePendingTree())
(...skipping 25 matching lines...) Expand all
490 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW && 528 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
491 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)); 529 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
492 } 530 }
493 531
494 void SchedulerStateMachine::UpdateState(Action action) { 532 void SchedulerStateMachine::UpdateState(Action action) {
495 switch (action) { 533 switch (action) {
496 case ACTION_NONE: 534 case ACTION_NONE:
497 return; 535 return;
498 536
499 case ACTION_UPDATE_VISIBLE_TILES: 537 case ACTION_UPDATE_VISIBLE_TILES:
500 last_frame_number_where_update_visible_tiles_was_called_ = 538 last_frame_number_update_visible_tiles_was_called_ =
501 current_frame_number_; 539 current_frame_number_;
502 return; 540 return;
503 541
504 case ACTION_ACTIVATE_PENDING_TREE: 542 case ACTION_ACTIVATE_PENDING_TREE:
505 UpdateStateOnActivation(); 543 UpdateStateOnActivation();
506 return; 544 return;
507 545
508 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 546 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
509 DCHECK(!has_pending_tree_); 547 DCHECK(!has_pending_tree_);
510 DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME); 548 DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME);
511 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 549 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
512 needs_commit_ = false; 550 needs_commit_ = false;
513 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME) 551 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
514 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT; 552 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
515 last_frame_number_where_begin_frame_sent_to_main_thread_ = 553 last_frame_number_begin_frame_sent_to_main_thread_ =
516 current_frame_number_; 554 current_frame_number_;
517 return; 555 return;
518 556
519 case ACTION_COMMIT: { 557 case ACTION_COMMIT: {
520 bool commit_was_aborted = false; 558 bool commit_was_aborted = false;
521 UpdateStateOnCommit(commit_was_aborted); 559 UpdateStateOnCommit(commit_was_aborted);
522 return; 560 return;
523 } 561 }
524 562
525 case ACTION_DRAW_AND_SWAP_FORCED: 563 case ACTION_DRAW_AND_SWAP_FORCED:
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 void SchedulerStateMachine::UpdateStateOnManageTiles() { 738 void SchedulerStateMachine::UpdateStateOnManageTiles() {
701 needs_manage_tiles_ = false; 739 needs_manage_tiles_ = false;
702 } 740 }
703 741
704 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 742 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
705 DCHECK(!main_thread_needs_layer_textures_); 743 DCHECK(!main_thread_needs_layer_textures_);
706 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 744 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
707 main_thread_needs_layer_textures_ = true; 745 main_thread_needs_layer_textures_ = true;
708 } 746 }
709 747
748 bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
749 // Proactive BeginFrames are bad for the synchronous compositor because we
750 // have to draw when we get the BeginFrame and could end up drawing many
751 // duplicate frames if our new frame isn't ready in time.
752 // To poll for state with the synchronous compositor without having to draw,
753 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
754 if (settings_.using_synchronous_renderer_compositor)
755 return BeginFrameNeededToDrawByImplThread();
756
757 return BeginFrameNeededToDrawByImplThread() ||
758 ProactiveBeginFrameWantedByImplThread();
759 }
760
761 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
762 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
763 // ProactiveBeginFrameWantedByImplThread when we are using the synchronous
764 // compositor.
765 if (settings_.using_synchronous_renderer_compositor) {
766 return !BeginFrameNeededToDrawByImplThread() &&
767 ProactiveBeginFrameWantedByImplThread();
768 }
769
770 // Non synchronous compositors should rely on
771 // ProactiveBeginFrameWantedByImplThread to poll for state instead.
772 return false;
773 }
774
710 // These are the cases where we definitely (or almost definitely) have a 775 // These are the cases where we definitely (or almost definitely) have a
711 // new frame to draw and can draw. 776 // new frame to draw and can draw.
712 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 777 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
713 // The output surface is the provider of BeginFrames for the impl thread, 778 // The output surface is the provider of BeginFrames for the impl thread,
714 // so we are not going to get them even if we ask for them. 779 // so we are not going to get them even if we ask for them.
715 if (!HasInitializedOutputSurface()) 780 if (!HasInitializedOutputSurface())
716 return false; 781 return false;
717 782
718 // If we can't draw, don't tick until we are notified that we can draw again. 783 // If we can't draw, don't tick until we are notified that we can draw again.
719 if (!can_draw_) 784 if (!can_draw_)
(...skipping 14 matching lines...) Expand all
734 if (swap_used_incomplete_tile_) 799 if (swap_used_incomplete_tile_)
735 return true; 800 return true;
736 801
737 return needs_redraw_; 802 return needs_redraw_;
738 } 803 }
739 804
740 // These are cases where we are very likely to draw soon, but might not 805 // These are cases where we are very likely to draw soon, but might not
741 // actually have a new frame to draw when we receive the next BeginFrame. 806 // actually have a new frame to draw when we receive the next BeginFrame.
742 // Proactively requesting the BeginFrame helps hide the round trip latency of 807 // Proactively requesting the BeginFrame helps hide the round trip latency of
743 // the SetNeedsBeginFrame request that has to go to the Browser. 808 // the SetNeedsBeginFrame request that has to go to the Browser.
744 // However, this is bad for the synchronous compositor because we have to
745 // draw when we get the BeginFrame and could end up drawing many duplicate
746 // frames.
747 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 809 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
748 // The output surface is the provider of BeginFrames for the impl thread, 810 // The output surface is the provider of BeginFrames for the impl thread,
749 // so we are not going to get them even if we ask for them. 811 // so we are not going to get them even if we ask for them.
750 if (!HasInitializedOutputSurface()) 812 if (!HasInitializedOutputSurface())
751 return false; 813 return false;
752 814
815 // Do not be proactive if vsync is off.
816 if (!settings_.throttle_frame_production)
817 return false;
818
753 // Do not be proactive when invisible. 819 // Do not be proactive when invisible.
754 if (!visible_) 820 if (!visible_)
755 return false; 821 return false;
756 822
757 // We should proactively request a BeginFrame if a commit is pending 823 // We should proactively request a BeginFrame if a commit is pending
758 // because we will want to draw if the commit completes quickly. 824 // because we will want to draw if the commit completes quickly.
759 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) 825 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
760 return true; 826 return true;
761 827
762 // If the pending tree activates quickly, we'll want a BeginFrame soon 828 // If the pending tree activates quickly, we'll want a BeginFrame soon
763 // to draw the new active tree. 829 // to draw the new active tree.
764 if (has_pending_tree_) 830 if (has_pending_tree_)
765 return true; 831 return true;
766 832
767 // Changing priorities may allow us to activate (given the new priorities), 833 // Changing priorities may allow us to activate (given the new priorities),
768 // which may result in a new frame. 834 // which may result in a new frame.
769 if (needs_manage_tiles_) 835 if (needs_manage_tiles_)
770 return true; 836 return true;
771 837
772 // If we just swapped, it's likely that we are going to produce another 838 // If we just swapped, it's likely that we are going to produce another
773 // frame soon. This helps avoid negative glitches in our SetNeedsBeginFrame 839 // frame soon. This helps avoid negative glitches in our SetNeedsBeginFrame
774 // requests, which may propagate to the BeginFrame provider and get sampled 840 // requests, which may propagate to the BeginFrame provider and get sampled
775 // at an inopportune time, delaying the next BeginFrame. 841 // at an inopportune time, delaying the next BeginFrame.
776 if (last_frame_number_swap_performed_ == current_frame_number_) 842 if (last_frame_number_swap_performed_ == current_frame_number_)
777 return true; 843 return true;
778 844
779 return false; 845 return false;
780 } 846 }
781 847
782 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 848 void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
783 current_frame_number_++; 849 current_frame_number_++;
784 inside_begin_frame_ = true;
785 last_begin_frame_args_ = args; 850 last_begin_frame_args_ = args;
851 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_IDLE)
852 << *AsValue();
853 begin_frame_state_ = BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING;
786 } 854 }
787 855
788 void SchedulerStateMachine::DidLeaveBeginFrame() { 856 void SchedulerStateMachine::OnBeginFrameDeadlinePending() {
789 inside_begin_frame_ = false; 857 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING)
858 << *AsValue();
859 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
860 }
861
862 void SchedulerStateMachine::OnBeginFrameDeadline() {
863 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
864 << *AsValue();
865 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
866 }
867
868 void SchedulerStateMachine::OnBeginFrameIdle() {
869 if (HasInitializedOutputSurface()) {
870 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_DEADLINE)
871 << *AsValue();
872 }
873 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
874 }
875
876 bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
877 // If we are in the middle of the readback, we won't swap, so there is
878 // no reason to trigger the deadline early.
879 if (readback_state_ != READBACK_STATE_IDLE)
880 return false;
881
882 // TODO(brianderson): This should take into account multiple commit sources.
883 return begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME &&
884 active_tree_needs_first_draw_;
790 } 885 }
791 886
792 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { 887 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
793 current_frame_number_++; 888 current_frame_number_++;
794 inside_poll_for_anticipated_draw_triggers_ = true; 889 inside_poll_for_anticipated_draw_triggers_ = true;
795 } 890 }
796 891
797 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { 892 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
798 inside_poll_for_anticipated_draw_triggers_ = false; 893 inside_poll_for_anticipated_draw_triggers_ = false;
799 } 894 }
800 895
801 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 896 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
802 897
898 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
899
803 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 900 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
804 901
805 void SchedulerStateMachine::SetNeedsManageTiles() { 902 void SchedulerStateMachine::SetNeedsManageTiles() {
806 needs_manage_tiles_ = true; 903 needs_manage_tiles_ = true;
807 } 904 }
808 905
809 void SchedulerStateMachine::SetSwapUsedIncompleteTile( 906 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
810 bool used_incomplete_tile) { 907 bool used_incomplete_tile) {
811 swap_used_incomplete_tile_ = used_incomplete_tile; 908 swap_used_incomplete_tile_ = used_incomplete_tile;
812 } 909 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 SetNeedsCommit(); 966 SetNeedsCommit();
870 } 967 }
871 } 968 }
872 969
873 void SchedulerStateMachine::DidLoseOutputSurface() { 970 void SchedulerStateMachine::DidLoseOutputSurface() {
874 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 971 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
875 output_surface_state_ == OUTPUT_SURFACE_CREATING) 972 output_surface_state_ == OUTPUT_SURFACE_CREATING)
876 return; 973 return;
877 output_surface_state_ = OUTPUT_SURFACE_LOST; 974 output_surface_state_ = OUTPUT_SURFACE_LOST;
878 needs_redraw_ = false; 975 needs_redraw_ = false;
976 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
879 } 977 }
880 978
881 void SchedulerStateMachine::NotifyReadyToActivate() { 979 void SchedulerStateMachine::NotifyReadyToActivate() {
882 if (has_pending_tree_) 980 if (has_pending_tree_)
883 pending_tree_is_ready_for_activation_ = true; 981 pending_tree_is_ready_for_activation_ = true;
884 } 982 }
885 983
886 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; }
887
888 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 984 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
889 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 985 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
890 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; 986 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
891 987
892 if (did_create_and_initialize_first_output_surface_) { 988 if (did_create_and_initialize_first_output_surface_) {
893 // TODO(boliu): See if we can remove this when impl-side painting is always 989 // TODO(boliu): See if we can remove this when impl-side painting is always
894 // on. Does anything on the main thread need to update after recreate? 990 // on. Does anything on the main thread need to update after recreate?
895 needs_commit_ = true; 991 needs_commit_ = true;
896 } 992 }
897 did_create_and_initialize_first_output_surface_ = true; 993 did_create_and_initialize_first_output_surface_ = true;
898 } 994 }
899 995
900 bool SchedulerStateMachine::HasInitializedOutputSurface() const { 996 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
901 switch (output_surface_state_) { 997 switch (output_surface_state_) {
902 case OUTPUT_SURFACE_LOST: 998 case OUTPUT_SURFACE_LOST:
903 case OUTPUT_SURFACE_CREATING: 999 case OUTPUT_SURFACE_CREATING:
904 return false; 1000 return false;
905 1001
906 case OUTPUT_SURFACE_ACTIVE: 1002 case OUTPUT_SURFACE_ACTIVE:
907 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 1003 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
908 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 1004 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
909 return true; 1005 return true;
910 } 1006 }
911 NOTREACHED(); 1007 NOTREACHED();
912 return false; 1008 return false;
913 } 1009 }
914 1010
915 } // namespace cc 1011 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler_state_machine.h ('k') | cc/scheduler/scheduler_state_machine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698