OLD | NEW |
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 prepare_tiles_funnel_(0), | 30 prepare_tiles_funnel_(0), |
30 consecutive_checkerboard_animations_(0), | 31 consecutive_checkerboard_animations_(0), |
31 max_pending_swaps_(1), | 32 max_pending_swaps_(1), |
32 pending_swaps_(0), | 33 pending_swaps_(0), |
33 needs_redraw_(false), | 34 needs_redraw_(false), |
34 needs_animate_(false), | 35 needs_animate_(false), |
35 needs_prepare_tiles_(false), | 36 needs_prepare_tiles_(false), |
36 needs_commit_(false), | 37 needs_commit_(false), |
37 inside_poll_for_anticipated_draw_triggers_(false), | |
38 visible_(false), | 38 visible_(false), |
39 can_start_(false), | 39 can_start_(false), |
40 can_draw_(false), | 40 can_draw_(false), |
41 has_pending_tree_(false), | 41 has_pending_tree_(false), |
42 pending_tree_is_ready_for_activation_(false), | 42 pending_tree_is_ready_for_activation_(false), |
43 active_tree_needs_first_draw_(false), | 43 active_tree_needs_first_draw_(false), |
44 did_commit_after_animating_(false), | 44 did_commit_after_animating_(false), |
45 did_create_and_initialize_first_output_surface_(false), | 45 did_create_and_initialize_first_output_surface_(false), |
46 impl_latency_takes_priority_(false), | 46 impl_latency_takes_priority_(false), |
47 skip_next_begin_main_frame_to_reduce_latency_(false), | 47 skip_next_begin_main_frame_to_reduce_latency_(false), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; | 79 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; |
80 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: | 80 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: |
81 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; | 81 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; |
82 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: | 82 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: |
83 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; | 83 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; |
84 } | 84 } |
85 NOTREACHED(); | 85 NOTREACHED(); |
86 return "???"; | 86 return "???"; |
87 } | 87 } |
88 | 88 |
| 89 const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString( |
| 90 BeginImplFrameDeadlineMode mode) { |
| 91 switch (mode) { |
| 92 case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS: |
| 93 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS"; |
| 94 case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS: |
| 95 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS"; |
| 96 case BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR: |
| 97 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR"; |
| 98 case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE: |
| 99 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE"; |
| 100 } |
| 101 NOTREACHED(); |
| 102 return "???"; |
| 103 } |
| 104 |
89 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { | 105 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { |
90 switch (state) { | 106 switch (state) { |
91 case COMMIT_STATE_IDLE: | 107 case COMMIT_STATE_IDLE: |
92 return "COMMIT_STATE_IDLE"; | 108 return "COMMIT_STATE_IDLE"; |
93 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT: | 109 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT: |
94 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT"; | 110 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT"; |
95 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED: | 111 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED: |
96 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; | 112 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; |
97 case COMMIT_STATE_READY_TO_COMMIT: | 113 case COMMIT_STATE_READY_TO_COMMIT: |
98 return "COMMIT_STATE_READY_TO_COMMIT"; | 114 return "COMMIT_STATE_READY_TO_COMMIT"; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: | 152 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: |
137 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; | 153 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; |
138 case ACTION_DRAW_AND_SWAP_FORCED: | 154 case ACTION_DRAW_AND_SWAP_FORCED: |
139 return "ACTION_DRAW_AND_SWAP_FORCED"; | 155 return "ACTION_DRAW_AND_SWAP_FORCED"; |
140 case ACTION_DRAW_AND_SWAP_ABORT: | 156 case ACTION_DRAW_AND_SWAP_ABORT: |
141 return "ACTION_DRAW_AND_SWAP_ABORT"; | 157 return "ACTION_DRAW_AND_SWAP_ABORT"; |
142 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 158 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
143 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; | 159 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; |
144 case ACTION_PREPARE_TILES: | 160 case ACTION_PREPARE_TILES: |
145 return "ACTION_PREPARE_TILES"; | 161 return "ACTION_PREPARE_TILES"; |
| 162 case ACTION_INVALIDATE_OUTPUT_SURFACE: |
| 163 return "ACTION_INVALIDATE_OUTPUT_SURFACE"; |
146 } | 164 } |
147 NOTREACHED(); | 165 NOTREACHED(); |
148 return "???"; | 166 return "???"; |
149 } | 167 } |
150 | 168 |
151 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 169 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
152 SchedulerStateMachine::AsValue() const { | 170 SchedulerStateMachine::AsValue() const { |
153 scoped_refptr<base::trace_event::TracedValue> state = | 171 scoped_refptr<base::trace_event::TracedValue> state = |
154 new base::trace_event::TracedValue(); | 172 new base::trace_event::TracedValue(); |
155 AsValueInto(state.get(), gfx::FrameTime::Now()); | 173 AsValueInto(state.get(), gfx::FrameTime::Now()); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", | 254 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", |
237 skip_next_begin_main_frame_to_reduce_latency_); | 255 skip_next_begin_main_frame_to_reduce_latency_); |
238 state->SetBoolean("continuous_painting", continuous_painting_); | 256 state->SetBoolean("continuous_painting", continuous_painting_); |
239 state->SetBoolean("impl_latency_takes_priority_on_battery", | 257 state->SetBoolean("impl_latency_takes_priority_on_battery", |
240 impl_latency_takes_priority_on_battery_); | 258 impl_latency_takes_priority_on_battery_); |
241 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); | 259 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); |
242 state->SetBoolean("defer_commits", defer_commits_); | 260 state->SetBoolean("defer_commits", defer_commits_); |
243 state->EndDictionary(); | 261 state->EndDictionary(); |
244 } | 262 } |
245 | 263 |
246 void SchedulerStateMachine::AdvanceCurrentFrameNumber() { | 264 void SchedulerStateMachine::AdvanceFrame() { |
247 current_frame_number_++; | 265 current_frame_number_++; |
248 | 266 |
249 // "Drain" the PrepareTiles funnel. | 267 // "Drain" the PrepareTiles funnel. |
250 if (prepare_tiles_funnel_ > 0) | 268 if (prepare_tiles_funnel_ > 0) |
251 prepare_tiles_funnel_--; | 269 prepare_tiles_funnel_--; |
252 | 270 |
253 skip_begin_main_frame_to_reduce_latency_ = | 271 skip_begin_main_frame_to_reduce_latency_ = |
254 skip_next_begin_main_frame_to_reduce_latency_; | 272 skip_next_begin_main_frame_to_reduce_latency_; |
255 skip_next_begin_main_frame_to_reduce_latency_ = false; | 273 skip_next_begin_main_frame_to_reduce_latency_ = false; |
256 } | 274 } |
257 | 275 |
258 bool SchedulerStateMachine::HasAnimatedThisFrame() const { | 276 bool SchedulerStateMachine::HasAnimatedThisFrame() const { |
259 return last_frame_number_animate_performed_ == current_frame_number_; | 277 return last_frame_number_animate_performed_ == current_frame_number_; |
260 } | 278 } |
261 | 279 |
262 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { | 280 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { |
263 return current_frame_number_ == | 281 return current_frame_number_ == |
264 last_frame_number_begin_main_frame_sent_; | 282 last_frame_number_begin_main_frame_sent_; |
265 } | 283 } |
266 | 284 |
267 bool SchedulerStateMachine::HasSwappedThisFrame() const { | 285 bool SchedulerStateMachine::HasSwappedThisFrame() const { |
268 return current_frame_number_ == last_frame_number_swap_performed_; | 286 return current_frame_number_ == last_frame_number_swap_performed_; |
269 } | 287 } |
270 | 288 |
271 bool SchedulerStateMachine::HasRequestedSwapThisFrame() const { | 289 bool SchedulerStateMachine::HasRequestedSwapThisFrame() const { |
272 return current_frame_number_ == last_frame_number_swap_requested_; | 290 return current_frame_number_ == last_frame_number_swap_requested_; |
273 } | 291 } |
274 | 292 |
| 293 bool SchedulerStateMachine::HasInvalidatedOutputSurfaceThisFrame() const { |
| 294 return current_frame_number_ == |
| 295 last_frame_number_invalidate_output_surface_performed_; |
| 296 } |
| 297 |
275 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { | 298 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { |
276 // These are all the cases where we normally cannot or do not want to draw | 299 // These are all the cases where we normally cannot or do not want to draw |
277 // but, if needs_redraw_ is true and we do not draw to make forward progress, | 300 // but, if needs_redraw_ is true and we do not draw to make forward progress, |
278 // we might deadlock with the main thread. | 301 // we might deadlock with the main thread. |
279 // This should be a superset of PendingActivationsShouldBeForced() since | 302 // This should be a superset of PendingActivationsShouldBeForced() since |
280 // activation of the pending tree is blocked by drawing of the active tree and | 303 // activation of the pending tree is blocked by drawing of the active tree and |
281 // the main thread might be blocked on activation of the most recent commit. | 304 // the main thread might be blocked on activation of the most recent commit. |
282 if (PendingActivationsShouldBeForced()) | 305 if (PendingActivationsShouldBeForced()) |
283 return true; | 306 return true; |
284 | 307 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 // are initializing the output surface. | 352 // are initializing the output surface. |
330 if (active_tree_needs_first_draw_ || has_pending_tree_) | 353 if (active_tree_needs_first_draw_ || has_pending_tree_) |
331 return false; | 354 return false; |
332 | 355 |
333 // We need to create the output surface if we don't have one and we haven't | 356 // We need to create the output surface if we don't have one and we haven't |
334 // started creating one yet. | 357 // started creating one yet. |
335 return output_surface_state_ == OUTPUT_SURFACE_LOST; | 358 return output_surface_state_ == OUTPUT_SURFACE_LOST; |
336 } | 359 } |
337 | 360 |
338 bool SchedulerStateMachine::ShouldDraw() const { | 361 bool SchedulerStateMachine::ShouldDraw() const { |
| 362 // In the synchronous compositor mode, draw only when asked to. |
| 363 if (settings_.using_synchronous_renderer_compositor && |
| 364 begin_impl_frame_args_.type != BeginFrameArgs::SYNCHRONOUS_DRAW) |
| 365 return false; |
| 366 |
339 // If we need to abort draws, we should do so ASAP since the draw could | 367 // If we need to abort draws, we should do so ASAP since the draw could |
340 // be blocking other important actions (like output surface initialization), | 368 // be blocking other important actions (like output surface initialization), |
341 // from occuring. If we are waiting for the first draw, then perfom the | 369 // from occuring. If we are waiting for the first draw, then perfom the |
342 // aborted draw to keep things moving. If we are not waiting for the first | 370 // aborted draw to keep things moving. If we are not waiting for the first |
343 // draw however, we don't want to abort for no reason. | 371 // draw however, we don't want to abort for no reason. |
344 if (PendingDrawsShouldBeAborted()) | 372 if (PendingDrawsShouldBeAborted()) |
345 return active_tree_needs_first_draw_; | 373 return active_tree_needs_first_draw_; |
346 | 374 |
347 // Don't draw if we are waiting on the first commit after a surface. | 375 // Don't draw if we are waiting on the first commit after a surface. |
348 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) | 376 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 } | 520 } |
493 | 521 |
494 bool SchedulerStateMachine::ShouldPrepareTiles() const { | 522 bool SchedulerStateMachine::ShouldPrepareTiles() const { |
495 // PrepareTiles only really needs to be called immediately after commit | 523 // PrepareTiles only really needs to be called immediately after commit |
496 // and then periodically after that. Use a funnel to make sure we average | 524 // and then periodically after that. Use a funnel to make sure we average |
497 // one PrepareTiles per BeginImplFrame in the long run. | 525 // one PrepareTiles per BeginImplFrame in the long run. |
498 if (prepare_tiles_funnel_ > 0) | 526 if (prepare_tiles_funnel_ > 0) |
499 return false; | 527 return false; |
500 | 528 |
501 // Limiting to once per-frame is not enough, since we only want to | 529 // Limiting to once per-frame is not enough, since we only want to |
502 // prepare tiles _after_ draws. Polling for draw triggers and | 530 // prepare tiles _after_ draws. |
503 // begin-frame are mutually exclusive, so we limit to these two cases. | 531 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
504 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && | |
505 !inside_poll_for_anticipated_draw_triggers_) | |
506 return false; | 532 return false; |
| 533 |
507 return needs_prepare_tiles_; | 534 return needs_prepare_tiles_; |
508 } | 535 } |
509 | 536 |
| 537 bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const { |
| 538 // Only the synchronous compositor requires invalidations. |
| 539 if (!settings_.using_synchronous_renderer_compositor) |
| 540 return false; |
| 541 |
| 542 // Invalidations are only performed inside a BeginFrame deadline. |
| 543 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 544 return false; |
| 545 |
| 546 // Invalidate the output surface only once per frame. |
| 547 if (HasInvalidatedOutputSurfaceThisFrame()) |
| 548 return false; |
| 549 |
| 550 return needs_redraw_; |
| 551 } |
| 552 |
510 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { | 553 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
511 if (ShouldActivatePendingTree()) | 554 if (ShouldActivatePendingTree()) |
512 return ACTION_ACTIVATE_SYNC_TREE; | 555 return ACTION_ACTIVATE_SYNC_TREE; |
513 if (ShouldCommit()) | 556 if (ShouldCommit()) |
514 return ACTION_COMMIT; | 557 return ACTION_COMMIT; |
515 if (ShouldAnimate()) | 558 if (ShouldAnimate()) |
516 return ACTION_ANIMATE; | 559 return ACTION_ANIMATE; |
517 if (ShouldDraw()) { | 560 if (ShouldDraw()) { |
518 if (PendingDrawsShouldBeAborted()) | 561 if (PendingDrawsShouldBeAborted()) |
519 return ACTION_DRAW_AND_SWAP_ABORT; | 562 return ACTION_DRAW_AND_SWAP_ABORT; |
520 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 563 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
521 return ACTION_DRAW_AND_SWAP_FORCED; | 564 return ACTION_DRAW_AND_SWAP_FORCED; |
522 else | 565 else |
523 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; | 566 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; |
524 } | 567 } |
525 if (ShouldPrepareTiles()) | 568 if (ShouldPrepareTiles()) |
526 return ACTION_PREPARE_TILES; | 569 return ACTION_PREPARE_TILES; |
527 if (ShouldSendBeginMainFrame()) | 570 if (ShouldSendBeginMainFrame()) |
528 return ACTION_SEND_BEGIN_MAIN_FRAME; | 571 return ACTION_SEND_BEGIN_MAIN_FRAME; |
| 572 if (ShouldInvalidateOutputSurface()) |
| 573 return ACTION_INVALIDATE_OUTPUT_SURFACE; |
529 if (ShouldBeginOutputSurfaceCreation()) | 574 if (ShouldBeginOutputSurfaceCreation()) |
530 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; | 575 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; |
531 return ACTION_NONE; | 576 return ACTION_NONE; |
532 } | 577 } |
533 | 578 |
534 void SchedulerStateMachine::UpdateState(Action action) { | 579 void SchedulerStateMachine::UpdateState(Action action) { |
535 switch (action) { | 580 switch (action) { |
536 case ACTION_NONE: | 581 case ACTION_NONE: |
537 return; | 582 return; |
538 | 583 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 // The pipeline should be flushed entirely before we start output | 631 // The pipeline should be flushed entirely before we start output |
587 // surface creation to avoid complicated corner cases. | 632 // surface creation to avoid complicated corner cases. |
588 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); | 633 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); |
589 DCHECK(!has_pending_tree_); | 634 DCHECK(!has_pending_tree_); |
590 DCHECK(!active_tree_needs_first_draw_); | 635 DCHECK(!active_tree_needs_first_draw_); |
591 return; | 636 return; |
592 | 637 |
593 case ACTION_PREPARE_TILES: | 638 case ACTION_PREPARE_TILES: |
594 UpdateStateOnPrepareTiles(); | 639 UpdateStateOnPrepareTiles(); |
595 return; | 640 return; |
| 641 |
| 642 case ACTION_INVALIDATE_OUTPUT_SURFACE: |
| 643 last_frame_number_invalidate_output_surface_performed_ = |
| 644 current_frame_number_; |
| 645 return; |
596 } | 646 } |
597 } | 647 } |
598 | 648 |
599 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { | 649 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { |
600 commit_count_++; | 650 commit_count_++; |
601 | 651 |
602 if (!commit_has_no_updates && HasAnimatedThisFrame()) | 652 if (!commit_has_no_updates && HasAnimatedThisFrame()) |
603 did_commit_after_animating_ = true; | 653 did_commit_after_animating_ = true; |
604 | 654 |
605 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { | 655 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 return children_need_begin_frames_; | 749 return children_need_begin_frames_; |
700 | 750 |
701 return false; | 751 return false; |
702 } | 752 } |
703 | 753 |
704 bool SchedulerStateMachine::BeginFrameNeeded() const { | 754 bool SchedulerStateMachine::BeginFrameNeeded() const { |
705 // We can't handle BeginFrames when output surface isn't initialized. | 755 // We can't handle BeginFrames when output surface isn't initialized. |
706 // TODO(brianderson): Support output surface creation inside a BeginFrame. | 756 // TODO(brianderson): Support output surface creation inside a BeginFrame. |
707 if (!HasInitializedOutputSurface()) | 757 if (!HasInitializedOutputSurface()) |
708 return false; | 758 return false; |
709 | 759 return (BeginFrameNeededToAnimateOrDraw() || BeginFrameNeededForChildren() || |
710 if (SupportsProactiveBeginFrame()) { | 760 ProactiveBeginFrameWanted()); |
711 return (BeginFrameNeededToAnimateOrDraw() || | |
712 BeginFrameNeededForChildren() || | |
713 ProactiveBeginFrameWanted()); | |
714 } | |
715 | |
716 // Proactive BeginFrames are bad for the synchronous compositor because we | |
717 // have to draw when we get the BeginFrame and could end up drawing many | |
718 // duplicate frames if our new frame isn't ready in time. | |
719 // To poll for state with the synchronous compositor without having to draw, | |
720 // we rely on ShouldPollForAnticipatedDrawTriggers instead. | |
721 // Synchronous compositor doesn't have a browser. | |
722 DCHECK(!children_need_begin_frames_); | |
723 return BeginFrameNeededToAnimateOrDraw(); | |
724 } | 761 } |
725 | 762 |
726 bool SchedulerStateMachine::ShouldSetNeedsBeginFrames( | 763 bool SchedulerStateMachine::ShouldSetNeedsBeginFrames( |
727 bool frame_source_needs_begin_frames) const { | 764 bool frame_source_needs_begin_frames) const { |
728 bool needs_begin_frame = BeginFrameNeeded(); | 765 bool needs_begin_frame = BeginFrameNeeded(); |
729 | 766 |
730 // Never call SetNeedsBeginFrames if the frame source has the right value. | 767 // Never call SetNeedsBeginFrames if the frame source has the right value. |
731 if (needs_begin_frame == frame_source_needs_begin_frames) | 768 if (needs_begin_frame == frame_source_needs_begin_frames) |
732 return false; | 769 return false; |
733 | 770 |
734 // Always request the BeginFrame immediately if it's needed. | 771 // Always request the BeginFrame immediately if it's needed. |
735 if (needs_begin_frame) | 772 if (needs_begin_frame) |
736 return true; | 773 return true; |
737 | 774 |
738 // Stop requesting BeginFrames after a deadline. | 775 // Stop requesting BeginFrames after a deadline. |
739 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 776 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
740 return true; | 777 return true; |
741 | 778 |
742 // Stop requesting BeginFrames immediately when output surface is lost. | 779 // Stop requesting BeginFrames immediately when output surface is lost. |
743 if (!HasInitializedOutputSurface()) | 780 if (!HasInitializedOutputSurface()) |
744 return true; | 781 return true; |
745 | 782 |
746 return false; | 783 return false; |
747 } | 784 } |
748 | 785 |
749 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { | |
750 // ShouldPollForAnticipatedDrawTriggers is what we use in place of | |
751 // ProactiveBeginFrameWanted when we are using the synchronous | |
752 // compositor. | |
753 if (!SupportsProactiveBeginFrame()) { | |
754 return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted(); | |
755 } | |
756 | |
757 // Non synchronous compositors should rely on | |
758 // ProactiveBeginFrameWanted to poll for state instead. | |
759 return false; | |
760 } | |
761 | |
762 // Note: If SupportsProactiveBeginFrame is false, the scheduler should poll | |
763 // for changes in it's draw state so it can request a BeginFrame when it's | |
764 // actually ready. | |
765 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const { | |
766 // It is undesirable to proactively request BeginFrames if we are | |
767 // using a synchronous compositor because we *must* draw for every | |
768 // BeginFrame, which could cause duplicate draws. | |
769 return !settings_.using_synchronous_renderer_compositor; | |
770 } | |
771 | |
772 void SchedulerStateMachine::SetChildrenNeedBeginFrames( | 786 void SchedulerStateMachine::SetChildrenNeedBeginFrames( |
773 bool children_need_begin_frames) { | 787 bool children_need_begin_frames) { |
774 DCHECK(settings_.forward_begin_frames_to_children); | 788 DCHECK(settings_.forward_begin_frames_to_children); |
775 children_need_begin_frames_ = children_need_begin_frames; | 789 children_need_begin_frames_ = children_need_begin_frames; |
776 } | 790 } |
777 | 791 |
778 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { | 792 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { |
779 defer_commits_ = defer_commits; | 793 defer_commits_ = defer_commits; |
780 } | 794 } |
781 | 795 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame | 833 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame |
820 // provider and get sampled at an inopportune time, delaying the next | 834 // provider and get sampled at an inopportune time, delaying the next |
821 // BeginImplFrame. | 835 // BeginImplFrame. |
822 if (HasRequestedSwapThisFrame()) | 836 if (HasRequestedSwapThisFrame()) |
823 return true; | 837 return true; |
824 | 838 |
825 return false; | 839 return false; |
826 } | 840 } |
827 | 841 |
828 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { | 842 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { |
829 AdvanceCurrentFrameNumber(); | |
830 begin_impl_frame_args_ = args; | 843 begin_impl_frame_args_ = args; |
| 844 |
| 845 // Advance frame for synchronous compositor on SYNCHRONOUS_ANIMATE only. |
| 846 if (!settings_.using_synchronous_renderer_compositor || |
| 847 begin_impl_frame_args_.type == BeginFrameArgs::SYNCHRONOUS_ANIMATE) |
| 848 AdvanceFrame(); |
| 849 |
831 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) | 850 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) |
832 << AsValue()->ToString(); | 851 << AsValue()->ToString(); |
833 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; | 852 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; |
834 } | 853 } |
835 | 854 |
836 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 855 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
837 DCHECK_EQ(begin_impl_frame_state_, | 856 DCHECK_EQ(begin_impl_frame_state_, |
838 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) | 857 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) |
839 << AsValue()->ToString(); | 858 << AsValue()->ToString(); |
840 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 859 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
841 } | 860 } |
842 | 861 |
843 void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 862 void SchedulerStateMachine::OnBeginImplFrameDeadline() { |
844 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 863 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
845 << AsValue()->ToString(); | 864 << AsValue()->ToString(); |
846 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 865 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
847 } | 866 } |
848 | 867 |
849 void SchedulerStateMachine::OnBeginImplFrameIdle() { | 868 void SchedulerStateMachine::OnBeginImplFrameIdle() { |
850 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 869 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
851 << AsValue()->ToString(); | 870 << AsValue()->ToString(); |
852 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; | 871 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; |
853 } | 872 } |
854 | 873 |
855 SchedulerStateMachine::BeginImplFrameDeadlineMode | 874 SchedulerStateMachine::BeginImplFrameDeadlineMode |
856 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 875 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
857 if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { | 876 if (settings_.using_synchronous_renderer_compositor) { |
858 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; | 877 // If the synchronous compositor wants to draw now. |
| 878 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS; |
| 879 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { |
| 880 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS; |
859 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { | 881 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { |
860 // We have an animation or fast input path on the impl thread that wants | 882 // We have an animation or fast input path on the impl thread that wants |
861 // to draw, so don't wait too long for a new active tree. | 883 // to draw, so don't wait too long for a new active tree. |
862 // If we are swap throttled we should wait until we are unblocked. | 884 // If we are swap throttled we should wait until we are unblocked. |
863 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; | 885 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; |
864 } else { | 886 } else { |
865 // The impl thread doesn't have anything it wants to draw and we are just | 887 // The impl thread doesn't have anything it wants to draw and we are just |
866 // waiting for a new active tree or we are swap throttled. In short we are | 888 // waiting for a new active tree or we are swap throttled. In short we are |
867 // blocked. | 889 // blocked. |
868 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; | 890 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; |
869 } | 891 } |
870 } | 892 } |
871 | 893 |
872 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() | 894 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() |
873 const { | 895 const { |
874 // TODO(brianderson): This should take into account multiple commit sources. | 896 // TODO(brianderson): This should take into account multiple commit sources. |
875 | |
876 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 897 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
877 return false; | 898 return false; |
878 | 899 |
879 // If we've lost the output surface, end the current BeginImplFrame ASAP | 900 // If we've lost the output surface, end the current BeginImplFrame ASAP |
880 // so we can start creating the next output surface. | 901 // so we can start creating the next output surface. |
881 if (output_surface_state_ == OUTPUT_SURFACE_LOST) | 902 if (output_surface_state_ == OUTPUT_SURFACE_LOST) |
882 return true; | 903 return true; |
883 | 904 |
884 // SwapAck throttle the deadline since we wont draw and swap anyway. | 905 // SwapAck throttle the deadline since we wont draw and swap anyway. |
885 if (pending_swaps_ >= max_pending_swaps_) | 906 if (pending_swaps_ >= max_pending_swaps_) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 // which case the main thread is in a high latency mode. | 966 // which case the main thread is in a high latency mode. |
946 return (active_tree_needs_first_draw_ || HasSwappedThisFrame()) && | 967 return (active_tree_needs_first_draw_ || HasSwappedThisFrame()) && |
947 !HasSentBeginMainFrameThisFrame(); | 968 !HasSentBeginMainFrameThisFrame(); |
948 } | 969 } |
949 | 970 |
950 // If the active tree needs its first draw in any other state, we know the | 971 // If the active tree needs its first draw in any other state, we know the |
951 // main thread is in a high latency mode. | 972 // main thread is in a high latency mode. |
952 return active_tree_needs_first_draw_; | 973 return active_tree_needs_first_draw_; |
953 } | 974 } |
954 | 975 |
955 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { | |
956 AdvanceCurrentFrameNumber(); | |
957 inside_poll_for_anticipated_draw_triggers_ = true; | |
958 } | |
959 | |
960 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { | |
961 inside_poll_for_anticipated_draw_triggers_ = false; | |
962 } | |
963 | |
964 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } | 976 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } |
965 | 977 |
966 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } | 978 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } |
967 | 979 |
968 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } | 980 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } |
969 | 981 |
970 void SchedulerStateMachine::SetNeedsAnimate() { | 982 void SchedulerStateMachine::SetNeedsAnimate() { |
971 needs_animate_ = true; | 983 needs_animate_ = true; |
972 } | 984 } |
973 | 985 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 static_cast<int>(begin_impl_frame_state_), | 1144 static_cast<int>(begin_impl_frame_state_), |
1133 static_cast<int>(commit_state_), | 1145 static_cast<int>(commit_state_), |
1134 has_pending_tree_ ? 'T' : 'F', | 1146 has_pending_tree_ ? 'T' : 'F', |
1135 pending_tree_is_ready_for_activation_ ? 'T' : 'F', | 1147 pending_tree_is_ready_for_activation_ ? 'T' : 'F', |
1136 active_tree_needs_first_draw_ ? 'T' : 'F', | 1148 active_tree_needs_first_draw_ ? 'T' : 'F', |
1137 max_pending_swaps_, | 1149 max_pending_swaps_, |
1138 pending_swaps_); | 1150 pending_swaps_); |
1139 } | 1151 } |
1140 | 1152 |
1141 } // namespace cc | 1153 } // namespace cc |
OLD | NEW |