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

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

Issue 817603002: cc: Make scheduling be driven by vsync for android webview. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address boliu's comments. Created 5 years, 9 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/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
11 #include "base/trace_event/trace_event_argument.h" 11 #include "base/trace_event/trace_event_argument.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "ui/gfx/frame_time.h" 13 #include "ui/gfx/frame_time.h"
14 14
15 namespace cc { 15 namespace cc {
16 16
17 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 17 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
18 : settings_(settings), 18 : settings_(settings),
19 output_surface_state_(OUTPUT_SURFACE_LOST), 19 output_surface_state_(OUTPUT_SURFACE_LOST),
20 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE), 20 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
21 commit_state_(COMMIT_STATE_IDLE), 21 commit_state_(COMMIT_STATE_IDLE),
22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), 22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
23 commit_count_(0), 23 commit_count_(0),
24 current_frame_number_(0), 24 current_frame_number_(0),
25 last_frame_number_animate_performed_(-1), 25 last_frame_number_animate_performed_(-1),
26 last_frame_number_swap_performed_(-1), 26 last_frame_number_swap_performed_(-1),
27 last_frame_number_swap_requested_(-1), 27 last_frame_number_swap_requested_(-1),
28 last_frame_number_begin_main_frame_sent_(-1), 28 last_frame_number_begin_main_frame_sent_(-1),
29 last_frame_number_invalidate_output_surface_performed_(-1),
29 animate_funnel_(false), 30 animate_funnel_(false),
30 perform_swap_funnel_(false), 31 perform_swap_funnel_(false),
31 request_swap_funnel_(false), 32 request_swap_funnel_(false),
32 send_begin_main_frame_funnel_(false), 33 send_begin_main_frame_funnel_(false),
34 invalidate_output_surface_funnel_(false),
33 prepare_tiles_funnel_(0), 35 prepare_tiles_funnel_(0),
34 consecutive_checkerboard_animations_(0), 36 consecutive_checkerboard_animations_(0),
35 max_pending_swaps_(1), 37 max_pending_swaps_(1),
36 pending_swaps_(0), 38 pending_swaps_(0),
37 needs_redraw_(false), 39 needs_redraw_(false),
38 needs_animate_(false), 40 needs_animate_(false),
39 needs_prepare_tiles_(false), 41 needs_prepare_tiles_(false),
40 needs_commit_(false), 42 needs_commit_(false),
41 inside_poll_for_anticipated_draw_triggers_(false),
42 visible_(false), 43 visible_(false),
43 can_start_(false), 44 can_start_(false),
44 can_draw_(false), 45 can_draw_(false),
45 has_pending_tree_(false), 46 has_pending_tree_(false),
46 pending_tree_is_ready_for_activation_(false), 47 pending_tree_is_ready_for_activation_(false),
47 active_tree_needs_first_draw_(false), 48 active_tree_needs_first_draw_(false),
48 did_create_and_initialize_first_output_surface_(false), 49 did_create_and_initialize_first_output_surface_(false),
49 impl_latency_takes_priority_(false), 50 impl_latency_takes_priority_(false),
50 skip_next_begin_main_frame_to_reduce_latency_(false), 51 skip_next_begin_main_frame_to_reduce_latency_(false),
51 skip_begin_main_frame_to_reduce_latency_(false), 52 skip_begin_main_frame_to_reduce_latency_(false),
(...skipping 29 matching lines...) Expand all
81 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; 82 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
82 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: 83 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
83 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; 84 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
84 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: 85 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
85 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; 86 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
86 } 87 }
87 NOTREACHED(); 88 NOTREACHED();
88 return "???"; 89 return "???";
89 } 90 }
90 91
92 const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
93 BeginImplFrameDeadlineMode mode) {
94 switch (mode) {
95 case BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
96 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE";
97 case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
98 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE";
99 case BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
100 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR";
101 case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
102 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE";
103 }
104 NOTREACHED();
105 return "???";
106 }
107
91 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { 108 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
92 switch (state) { 109 switch (state) {
93 case COMMIT_STATE_IDLE: 110 case COMMIT_STATE_IDLE:
94 return "COMMIT_STATE_IDLE"; 111 return "COMMIT_STATE_IDLE";
95 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT: 112 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
96 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT"; 113 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
97 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED: 114 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
98 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; 115 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
99 case COMMIT_STATE_READY_TO_COMMIT: 116 case COMMIT_STATE_READY_TO_COMMIT:
100 return "COMMIT_STATE_READY_TO_COMMIT"; 117 return "COMMIT_STATE_READY_TO_COMMIT";
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: 155 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
139 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; 156 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
140 case ACTION_DRAW_AND_SWAP_FORCED: 157 case ACTION_DRAW_AND_SWAP_FORCED:
141 return "ACTION_DRAW_AND_SWAP_FORCED"; 158 return "ACTION_DRAW_AND_SWAP_FORCED";
142 case ACTION_DRAW_AND_SWAP_ABORT: 159 case ACTION_DRAW_AND_SWAP_ABORT:
143 return "ACTION_DRAW_AND_SWAP_ABORT"; 160 return "ACTION_DRAW_AND_SWAP_ABORT";
144 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 161 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
145 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; 162 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
146 case ACTION_PREPARE_TILES: 163 case ACTION_PREPARE_TILES:
147 return "ACTION_PREPARE_TILES"; 164 return "ACTION_PREPARE_TILES";
165 case ACTION_INVALIDATE_OUTPUT_SURFACE:
166 return "ACTION_INVALIDATE_OUTPUT_SURFACE";
148 } 167 }
149 NOTREACHED(); 168 NOTREACHED();
150 return "???"; 169 return "???";
151 } 170 }
152 171
153 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 172 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
154 SchedulerStateMachine::AsValue() const { 173 SchedulerStateMachine::AsValue() const {
155 scoped_refptr<base::trace_event::TracedValue> state = 174 scoped_refptr<base::trace_event::TracedValue> state =
156 new base::trace_event::TracedValue(); 175 new base::trace_event::TracedValue();
157 AsValueInto(state.get()); 176 AsValueInto(state.get());
(...skipping 23 matching lines...) Expand all
181 state->SetInteger("last_frame_number_swap_requested", 200 state->SetInteger("last_frame_number_swap_requested",
182 last_frame_number_swap_requested_); 201 last_frame_number_swap_requested_);
183 state->SetInteger("last_frame_number_begin_main_frame_sent", 202 state->SetInteger("last_frame_number_begin_main_frame_sent",
184 last_frame_number_begin_main_frame_sent_); 203 last_frame_number_begin_main_frame_sent_);
185 state->SetBoolean("funnel: animate_funnel", animate_funnel_); 204 state->SetBoolean("funnel: animate_funnel", animate_funnel_);
186 state->SetBoolean("funnel: perform_swap_funnel", perform_swap_funnel_); 205 state->SetBoolean("funnel: perform_swap_funnel", perform_swap_funnel_);
187 state->SetBoolean("funnel: request_swap_funnel", request_swap_funnel_); 206 state->SetBoolean("funnel: request_swap_funnel", request_swap_funnel_);
188 state->SetBoolean("funnel: send_begin_main_frame_funnel", 207 state->SetBoolean("funnel: send_begin_main_frame_funnel",
189 send_begin_main_frame_funnel_); 208 send_begin_main_frame_funnel_);
190 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_); 209 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_);
210 state->SetBoolean("funnel: invalidate_output_surface_funnel",
211 invalidate_output_surface_funnel_);
191 state->SetInteger("consecutive_checkerboard_animations", 212 state->SetInteger("consecutive_checkerboard_animations",
192 consecutive_checkerboard_animations_); 213 consecutive_checkerboard_animations_);
193 state->SetInteger("max_pending_swaps_", max_pending_swaps_); 214 state->SetInteger("max_pending_swaps_", max_pending_swaps_);
194 state->SetInteger("pending_swaps_", pending_swaps_); 215 state->SetInteger("pending_swaps_", pending_swaps_);
195 state->SetBoolean("needs_redraw", needs_redraw_); 216 state->SetBoolean("needs_redraw", needs_redraw_);
196 state->SetBoolean("needs_animate_", needs_animate_); 217 state->SetBoolean("needs_animate_", needs_animate_);
197 state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_); 218 state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_);
198 state->SetBoolean("needs_commit", needs_commit_); 219 state->SetBoolean("needs_commit", needs_commit_);
199 state->SetBoolean("visible", visible_); 220 state->SetBoolean("visible", visible_);
200 state->SetBoolean("can_start", can_start_); 221 state->SetBoolean("can_start", can_start_);
(...skipping 12 matching lines...) Expand all
213 state->SetBoolean("skip_begin_main_frame_to_reduce_latency", 234 state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
214 skip_begin_main_frame_to_reduce_latency_); 235 skip_begin_main_frame_to_reduce_latency_);
215 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", 236 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
216 skip_next_begin_main_frame_to_reduce_latency_); 237 skip_next_begin_main_frame_to_reduce_latency_);
217 state->SetBoolean("continuous_painting", continuous_painting_); 238 state->SetBoolean("continuous_painting", continuous_painting_);
218 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); 239 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
219 state->SetBoolean("defer_commits", defer_commits_); 240 state->SetBoolean("defer_commits", defer_commits_);
220 state->EndDictionary(); 241 state->EndDictionary();
221 } 242 }
222 243
223 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
224 current_frame_number_++;
225
226 animate_funnel_ = false;
227 perform_swap_funnel_ = false;
228 request_swap_funnel_ = false;
229 send_begin_main_frame_funnel_ = false;
230
231 // "Drain" the PrepareTiles funnel.
232 if (prepare_tiles_funnel_ > 0)
233 prepare_tiles_funnel_--;
234
235 skip_begin_main_frame_to_reduce_latency_ =
236 skip_next_begin_main_frame_to_reduce_latency_;
237 skip_next_begin_main_frame_to_reduce_latency_ = false;
238 }
239
240 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 244 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
241 // These are all the cases where we normally cannot or do not want to draw 245 // These are all the cases where we normally cannot or do not want to draw
242 // but, if needs_redraw_ is true and we do not draw to make forward progress, 246 // but, if needs_redraw_ is true and we do not draw to make forward progress,
243 // we might deadlock with the main thread. 247 // we might deadlock with the main thread.
244 // This should be a superset of PendingActivationsShouldBeForced() since 248 // This should be a superset of PendingActivationsShouldBeForced() since
245 // activation of the pending tree is blocked by drawing of the active tree and 249 // activation of the pending tree is blocked by drawing of the active tree and
246 // the main thread might be blocked on activation of the most recent commit. 250 // the main thread might be blocked on activation of the most recent commit.
247 if (PendingActivationsShouldBeForced()) 251 if (PendingActivationsShouldBeForced())
248 return true; 252 return true;
249 253
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } 458 }
455 459
456 bool SchedulerStateMachine::ShouldPrepareTiles() const { 460 bool SchedulerStateMachine::ShouldPrepareTiles() const {
457 // PrepareTiles only really needs to be called immediately after commit 461 // PrepareTiles only really needs to be called immediately after commit
458 // and then periodically after that. Use a funnel to make sure we average 462 // and then periodically after that. Use a funnel to make sure we average
459 // one PrepareTiles per BeginImplFrame in the long run. 463 // one PrepareTiles per BeginImplFrame in the long run.
460 if (prepare_tiles_funnel_ > 0) 464 if (prepare_tiles_funnel_ > 0)
461 return false; 465 return false;
462 466
463 // Limiting to once per-frame is not enough, since we only want to 467 // Limiting to once per-frame is not enough, since we only want to
464 // prepare tiles _after_ draws. Polling for draw triggers and 468 // prepare tiles _after_ draws.
465 // begin-frame are mutually exclusive, so we limit to these two cases. 469 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
466 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
467 !inside_poll_for_anticipated_draw_triggers_)
468 return false; 470 return false;
471
469 return needs_prepare_tiles_; 472 return needs_prepare_tiles_;
470 } 473 }
471 474
475 bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const {
476 // Do not invalidate too many times in a frame.
477 if (invalidate_output_surface_funnel_)
478 return false;
479
480 // Only the synchronous compositor requires invalidations.
481 if (!settings_.using_synchronous_renderer_compositor)
482 return false;
483
484 // Invalidations are only performed inside a BeginFrame or inside deadline.
485 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING &&
486 begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
487 return false;
488
489 return needs_redraw_ || needs_prepare_tiles_;
490 }
491
472 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 492 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
473 if (ShouldActivatePendingTree()) 493 if (ShouldActivatePendingTree())
474 return ACTION_ACTIVATE_SYNC_TREE; 494 return ACTION_ACTIVATE_SYNC_TREE;
475 if (ShouldCommit()) 495 if (ShouldCommit())
476 return ACTION_COMMIT; 496 return ACTION_COMMIT;
477 if (ShouldAnimate()) 497 if (ShouldAnimate())
478 return ACTION_ANIMATE; 498 return ACTION_ANIMATE;
479 if (ShouldDraw()) { 499 if (ShouldDraw()) {
480 if (PendingDrawsShouldBeAborted()) 500 if (PendingDrawsShouldBeAborted())
481 return ACTION_DRAW_AND_SWAP_ABORT; 501 return ACTION_DRAW_AND_SWAP_ABORT;
482 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) 502 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
483 return ACTION_DRAW_AND_SWAP_FORCED; 503 return ACTION_DRAW_AND_SWAP_FORCED;
484 else 504 else
485 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; 505 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
486 } 506 }
487 if (ShouldPrepareTiles()) 507 if (ShouldPrepareTiles())
488 return ACTION_PREPARE_TILES; 508 return ACTION_PREPARE_TILES;
489 if (ShouldSendBeginMainFrame()) 509 if (ShouldSendBeginMainFrame())
490 return ACTION_SEND_BEGIN_MAIN_FRAME; 510 return ACTION_SEND_BEGIN_MAIN_FRAME;
511 if (ShouldInvalidateOutputSurface())
512 return ACTION_INVALIDATE_OUTPUT_SURFACE;
491 if (ShouldBeginOutputSurfaceCreation()) 513 if (ShouldBeginOutputSurfaceCreation())
492 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 514 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
493 return ACTION_NONE; 515 return ACTION_NONE;
494 } 516 }
495 517
496 void SchedulerStateMachine::UpdateState(Action action) { 518 void SchedulerStateMachine::UpdateState(Action action) {
497 switch (action) { 519 switch (action) {
498 case ACTION_NONE: 520 case ACTION_NONE:
499 return; 521 return;
500 522
501 case ACTION_ACTIVATE_SYNC_TREE: 523 case ACTION_ACTIVATE_SYNC_TREE:
502 UpdateStateOnActivation(); 524 UpdateStateOnActivation();
503 return; 525 return;
504 526
505 case ACTION_ANIMATE: 527 case ACTION_ANIMATE:
506 DCHECK(!animate_funnel_); 528 UpdateStateOnAnimate();
507 last_frame_number_animate_performed_ = current_frame_number_;
508 animate_funnel_ = true;
509 needs_animate_ = false;
510 // TODO(skyostil): Instead of assuming this, require the client to tell
511 // us.
512 SetNeedsRedraw();
513 return; 529 return;
514 530
515 case ACTION_SEND_BEGIN_MAIN_FRAME: 531 case ACTION_SEND_BEGIN_MAIN_FRAME:
516 DCHECK(!has_pending_tree_ || 532 UpdateStateOnSendBeginMainFrame();
517 settings_.main_frame_before_activation_enabled);
518 DCHECK(visible_);
519 DCHECK(!send_begin_main_frame_funnel_);
520 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
521 needs_commit_ = false;
522 send_begin_main_frame_funnel_ = true;
523 last_frame_number_begin_main_frame_sent_ =
524 current_frame_number_;
525 return; 533 return;
526 534
527 case ACTION_COMMIT: { 535 case ACTION_COMMIT: {
528 bool commit_has_no_updates = false; 536 bool commit_has_no_updates = false;
529 UpdateStateOnCommit(commit_has_no_updates); 537 UpdateStateOnCommit(commit_has_no_updates);
530 return; 538 return;
531 } 539 }
532 540
533 case ACTION_DRAW_AND_SWAP_FORCED: 541 case ACTION_DRAW_AND_SWAP_FORCED:
534 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { 542 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
535 bool did_request_swap = true; 543 bool did_request_swap = true;
536 UpdateStateOnDraw(did_request_swap); 544 UpdateStateOnDraw(did_request_swap);
537 return; 545 return;
538 } 546 }
539 547
540 case ACTION_DRAW_AND_SWAP_ABORT: { 548 case ACTION_DRAW_AND_SWAP_ABORT: {
541 bool did_request_swap = false; 549 bool did_request_swap = false;
542 UpdateStateOnDraw(did_request_swap); 550 UpdateStateOnDraw(did_request_swap);
543 return; 551 return;
544 } 552 }
545 553
546 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 554 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
547 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 555 UpdateStateOnBeginOutputSurfaceCreation();
548 output_surface_state_ = OUTPUT_SURFACE_CREATING;
549
550 // The following DCHECKs make sure we are in the proper quiescent state.
551 // The pipeline should be flushed entirely before we start output
552 // surface creation to avoid complicated corner cases.
553 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
554 DCHECK(!has_pending_tree_);
555 DCHECK(!active_tree_needs_first_draw_);
556 return; 556 return;
557 557
558 case ACTION_PREPARE_TILES: 558 case ACTION_PREPARE_TILES:
559 UpdateStateOnPrepareTiles(); 559 UpdateStateOnPrepareTiles();
560 return; 560 return;
561
562 case ACTION_INVALIDATE_OUTPUT_SURFACE:
563 UpdateStateOnInvalidateOutputSurface();
564 return;
561 } 565 }
562 } 566 }
563 567
568 void SchedulerStateMachine::UpdateStateOnAnimate() {
569 DCHECK(!animate_funnel_);
570 last_frame_number_animate_performed_ = current_frame_number_;
571 animate_funnel_ = true;
572 needs_animate_ = false;
573 // TODO(skyostil): Instead of assuming this, require the client to tell
574 // us.
575 SetNeedsRedraw();
576 }
577
578 void SchedulerStateMachine::UpdateStateOnSendBeginMainFrame() {
579 DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
580 DCHECK(visible_);
581 DCHECK(!send_begin_main_frame_funnel_);
582 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
583 needs_commit_ = false;
584 send_begin_main_frame_funnel_ = true;
585 last_frame_number_begin_main_frame_sent_ = current_frame_number_;
586 }
587
564 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { 588 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
565 commit_count_++; 589 commit_count_++;
566 590
567 if (!commit_has_no_updates) 591 if (!commit_has_no_updates)
568 animate_funnel_ = false; 592 animate_funnel_ = false;
569 593
570 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { 594 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) {
571 commit_state_ = COMMIT_STATE_IDLE; 595 commit_state_ = COMMIT_STATE_IDLE;
572 } else if (settings_.impl_side_painting) { 596 } else if (settings_.impl_side_painting) {
573 commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION; 597 commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 DCHECK(!request_swap_funnel_); 672 DCHECK(!request_swap_funnel_);
649 request_swap_funnel_ = true; 673 request_swap_funnel_ = true;
650 last_frame_number_swap_requested_ = current_frame_number_; 674 last_frame_number_swap_requested_ = current_frame_number_;
651 } 675 }
652 } 676 }
653 677
654 void SchedulerStateMachine::UpdateStateOnPrepareTiles() { 678 void SchedulerStateMachine::UpdateStateOnPrepareTiles() {
655 needs_prepare_tiles_ = false; 679 needs_prepare_tiles_ = false;
656 } 680 }
657 681
682 void SchedulerStateMachine::UpdateStateOnBeginOutputSurfaceCreation() {
683 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
684 output_surface_state_ = OUTPUT_SURFACE_CREATING;
685
686 // The following DCHECKs make sure we are in the proper quiescent state.
687 // The pipeline should be flushed entirely before we start output
688 // surface creation to avoid complicated corner cases.
689 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
690 DCHECK(!has_pending_tree_);
691 DCHECK(!active_tree_needs_first_draw_);
692 }
693
694 void SchedulerStateMachine::UpdateStateOnInvalidateOutputSurface() {
695 DCHECK(!invalidate_output_surface_funnel_);
696 invalidate_output_surface_funnel_ = true;
697 last_frame_number_invalidate_output_surface_performed_ =
698 current_frame_number_;
699 // There is no guarantee that a draw will arrive from the synchronous
700 // compositor. We clear this flag here so that the pipeline isn't blocked.
701 active_tree_needs_first_draw_ = false;
702 }
703
658 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() { 704 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
659 TRACE_EVENT_INSTANT0("cc", 705 TRACE_EVENT_INSTANT0("cc",
660 "Scheduler: SkipNextBeginMainFrameToReduceLatency", 706 "Scheduler: SkipNextBeginMainFrameToReduceLatency",
661 TRACE_EVENT_SCOPE_THREAD); 707 TRACE_EVENT_SCOPE_THREAD);
662 skip_next_begin_main_frame_to_reduce_latency_ = true; 708 skip_next_begin_main_frame_to_reduce_latency_ = true;
663 } 709 }
664 710
665 bool SchedulerStateMachine::BeginFrameNeededForChildren() const { 711 bool SchedulerStateMachine::BeginFrameNeededForChildren() const {
666 if (HasInitializedOutputSurface()) 712 if (HasInitializedOutputSurface())
667 return children_need_begin_frames_; 713 return children_need_begin_frames_;
668 714
669 return false; 715 return false;
670 } 716 }
671 717
672 bool SchedulerStateMachine::BeginFrameNeeded() const { 718 bool SchedulerStateMachine::BeginFrameNeeded() const {
673 // We can't handle BeginFrames when output surface isn't initialized. 719 // We can't handle BeginFrames when output surface isn't initialized.
674 // TODO(brianderson): Support output surface creation inside a BeginFrame. 720 // TODO(brianderson): Support output surface creation inside a BeginFrame.
675 if (!HasInitializedOutputSurface()) 721 if (!HasInitializedOutputSurface())
676 return false; 722 return false;
677 723 return (BeginFrameNeededToAnimateOrDraw() || BeginFrameNeededForChildren() ||
678 if (SupportsProactiveBeginFrame()) { 724 ProactiveBeginFrameWanted());
679 return (BeginFrameNeededToAnimateOrDraw() ||
680 BeginFrameNeededForChildren() ||
681 ProactiveBeginFrameWanted());
682 }
683
684 // Proactive BeginFrames are bad for the synchronous compositor because we
685 // have to draw when we get the BeginFrame and could end up drawing many
686 // duplicate frames if our new frame isn't ready in time.
687 // To poll for state with the synchronous compositor without having to draw,
688 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
689 // Synchronous compositor doesn't have a browser.
690 DCHECK(!children_need_begin_frames_);
691 return BeginFrameNeededToAnimateOrDraw();
692 }
693
694 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
695 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
696 // ProactiveBeginFrameWanted when we are using the synchronous
697 // compositor.
698 if (!SupportsProactiveBeginFrame()) {
699 return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
700 }
701
702 // Non synchronous compositors should rely on
703 // ProactiveBeginFrameWanted to poll for state instead.
704 return false;
705 }
706
707 // Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
708 // for changes in it's draw state so it can request a BeginFrame when it's
709 // actually ready.
710 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
711 // It is undesirable to proactively request BeginFrames if we are
712 // using a synchronous compositor because we *must* draw for every
713 // BeginFrame, which could cause duplicate draws.
714 return !settings_.using_synchronous_renderer_compositor;
715 } 725 }
716 726
717 void SchedulerStateMachine::SetChildrenNeedBeginFrames( 727 void SchedulerStateMachine::SetChildrenNeedBeginFrames(
718 bool children_need_begin_frames) { 728 bool children_need_begin_frames) {
719 children_need_begin_frames_ = children_need_begin_frames; 729 children_need_begin_frames_ = children_need_begin_frames;
720 } 730 }
721 731
722 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { 732 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) {
723 defer_commits_ = defer_commits; 733 defer_commits_ = defer_commits;
724 } 734 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame 773 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
764 // provider and get sampled at an inopportune time, delaying the next 774 // provider and get sampled at an inopportune time, delaying the next
765 // BeginImplFrame. 775 // BeginImplFrame.
766 if (request_swap_funnel_) 776 if (request_swap_funnel_)
767 return true; 777 return true;
768 778
769 return false; 779 return false;
770 } 780 }
771 781
772 void SchedulerStateMachine::OnBeginImplFrame() { 782 void SchedulerStateMachine::OnBeginImplFrame() {
773 AdvanceCurrentFrameNumber();
774 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE)
775 << AsValue()->ToString();
776 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; 783 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
784
785 current_frame_number_++;
786
787 // Clear funnels for any actions we perform during the frame.
788 animate_funnel_ = false;
789 perform_swap_funnel_ = false;
790 request_swap_funnel_ = false;
791 send_begin_main_frame_funnel_ = false;
792 invalidate_output_surface_funnel_ = false;
793
794 skip_begin_main_frame_to_reduce_latency_ =
795 skip_next_begin_main_frame_to_reduce_latency_;
796 skip_next_begin_main_frame_to_reduce_latency_ = false;
777 } 797 }
778 798
779 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { 799 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
780 DCHECK_EQ(begin_impl_frame_state_,
781 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
782 << AsValue()->ToString();
783 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; 800 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
784 } 801 }
785 802
786 void SchedulerStateMachine::OnBeginImplFrameDeadline() { 803 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
787 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
788 << AsValue()->ToString();
789 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; 804 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
805
806 // Clear funnels for any actions we perform during the deadline.
807 perform_swap_funnel_ = false;
808 request_swap_funnel_ = false;
809 invalidate_output_surface_funnel_ = false;
810
811 // "Drain" the PrepareTiles funnel.
812 if (prepare_tiles_funnel_ > 0)
813 prepare_tiles_funnel_--;
790 } 814 }
791 815
792 void SchedulerStateMachine::OnBeginImplFrameIdle() { 816 void SchedulerStateMachine::OnBeginImplFrameIdle() {
793 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
794 << AsValue()->ToString();
795 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; 817 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
796 } 818 }
797 819
798 SchedulerStateMachine::BeginImplFrameDeadlineMode 820 SchedulerStateMachine::BeginImplFrameDeadlineMode
799 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { 821 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
800 if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { 822 if (settings_.using_synchronous_renderer_compositor) {
823 // No deadline for synchronous compositor.
824 return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE;
825 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
801 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; 826 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
802 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { 827 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
803 // We have an animation or fast input path on the impl thread that wants 828 // We have an animation or fast input path on the impl thread that wants
804 // to draw, so don't wait too long for a new active tree. 829 // to draw, so don't wait too long for a new active tree.
805 // If we are swap throttled we should wait until we are unblocked. 830 // If we are swap throttled we should wait until we are unblocked.
806 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; 831 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR;
807 } else { 832 } else {
808 // The impl thread doesn't have anything it wants to draw and we are just 833 // The impl thread doesn't have anything it wants to draw and we are just
809 // waiting for a new active tree or we are swap throttled. In short we are 834 // waiting for a new active tree or we are swap throttled. In short we are
810 // blocked. 835 // blocked.
811 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; 836 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE;
812 } 837 }
813 } 838 }
814 839
815 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() 840 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
816 const { 841 const {
817 // TODO(brianderson): This should take into account multiple commit sources. 842 // TODO(brianderson): This should take into account multiple commit sources.
818
819 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) 843 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
820 return false; 844 return false;
821 845
822 // If we've lost the output surface, end the current BeginImplFrame ASAP 846 // If we've lost the output surface, end the current BeginImplFrame ASAP
823 // so we can start creating the next output surface. 847 // so we can start creating the next output surface.
824 if (output_surface_state_ == OUTPUT_SURFACE_LOST) 848 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
825 return true; 849 return true;
826 850
827 // SwapAck throttle the deadline since we wont draw and swap anyway. 851 // SwapAck throttle the deadline since we wont draw and swap anyway.
828 if (pending_swaps_ >= max_pending_swaps_) 852 if (pending_swaps_ >= max_pending_swaps_)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 // which case the main thread is in a high latency mode. 907 // which case the main thread is in a high latency mode.
884 return (active_tree_needs_first_draw_ || perform_swap_funnel_) && 908 return (active_tree_needs_first_draw_ || perform_swap_funnel_) &&
885 !send_begin_main_frame_funnel_; 909 !send_begin_main_frame_funnel_;
886 } 910 }
887 911
888 // If the active tree needs its first draw in any other state, we know the 912 // If the active tree needs its first draw in any other state, we know the
889 // main thread is in a high latency mode. 913 // main thread is in a high latency mode.
890 return active_tree_needs_first_draw_; 914 return active_tree_needs_first_draw_;
891 } 915 }
892 916
893 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
894 AdvanceCurrentFrameNumber();
895 inside_poll_for_anticipated_draw_triggers_ = true;
896 }
897
898 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
899 inside_poll_for_anticipated_draw_triggers_ = false;
900 }
901
902 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 917 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
903 918
904 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } 919 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
905 920
906 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 921 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
907 922
908 void SchedulerStateMachine::SetNeedsAnimate() { 923 void SchedulerStateMachine::SetNeedsAnimate() {
909 needs_animate_ = true; 924 needs_animate_ = true;
910 } 925 }
911 926
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 static_cast<int>(begin_impl_frame_state_), 1087 static_cast<int>(begin_impl_frame_state_),
1073 static_cast<int>(commit_state_), 1088 static_cast<int>(commit_state_),
1074 has_pending_tree_ ? 'T' : 'F', 1089 has_pending_tree_ ? 'T' : 'F',
1075 pending_tree_is_ready_for_activation_ ? 'T' : 'F', 1090 pending_tree_is_ready_for_activation_ ? 'T' : 'F',
1076 active_tree_needs_first_draw_ ? 'T' : 'F', 1091 active_tree_needs_first_draw_ ? 'T' : 'F',
1077 max_pending_swaps_, 1092 max_pending_swaps_,
1078 pending_swaps_); 1093 pending_swaps_);
1079 } 1094 }
1080 1095
1081 } // namespace cc 1096 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698