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

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

Issue 2753843003: Create a new action triggered when a BeginMainFrame is not expected before vsync (Closed)
Patch Set: Never schedule idle work if we're already scheduling a main frame Created 3 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"
(...skipping 27 matching lines...) Expand all
38 commit_count_(0), 38 commit_count_(0),
39 current_frame_number_(0), 39 current_frame_number_(0),
40 last_frame_number_submit_performed_(-1), 40 last_frame_number_submit_performed_(-1),
41 last_frame_number_draw_performed_(-1), 41 last_frame_number_draw_performed_(-1),
42 last_frame_number_begin_main_frame_sent_(-1), 42 last_frame_number_begin_main_frame_sent_(-1),
43 last_frame_number_invalidate_compositor_frame_sink_performed_(-1), 43 last_frame_number_invalidate_compositor_frame_sink_performed_(-1),
44 draw_funnel_(false), 44 draw_funnel_(false),
45 send_begin_main_frame_funnel_(true), 45 send_begin_main_frame_funnel_(true),
46 invalidate_compositor_frame_sink_funnel_(false), 46 invalidate_compositor_frame_sink_funnel_(false),
47 impl_side_invalidation_funnel_(false), 47 impl_side_invalidation_funnel_(false),
48 do_idle_work_funnel_(false),
48 prepare_tiles_funnel_(0), 49 prepare_tiles_funnel_(0),
49 consecutive_checkerboard_animations_(0), 50 consecutive_checkerboard_animations_(0),
50 pending_submit_frames_(0), 51 pending_submit_frames_(0),
51 submit_frames_with_current_compositor_frame_sink_(0), 52 submit_frames_with_current_compositor_frame_sink_(0),
52 needs_redraw_(false), 53 needs_redraw_(false),
53 needs_prepare_tiles_(false), 54 needs_prepare_tiles_(false),
54 needs_begin_main_frame_(false), 55 needs_begin_main_frame_(false),
55 needs_one_begin_impl_frame_(false), 56 needs_one_begin_impl_frame_(false),
56 visible_(false), 57 visible_(false),
57 begin_frame_source_paused_(false), 58 begin_frame_source_paused_(false),
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 case ACTION_DRAW_ABORT: 188 case ACTION_DRAW_ABORT:
188 return "ACTION_DRAW_ABORT"; 189 return "ACTION_DRAW_ABORT";
189 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION: 190 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION:
190 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION"; 191 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION";
191 case ACTION_PREPARE_TILES: 192 case ACTION_PREPARE_TILES:
192 return "ACTION_PREPARE_TILES"; 193 return "ACTION_PREPARE_TILES";
193 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK: 194 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK:
194 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK"; 195 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK";
195 case ACTION_PERFORM_IMPL_SIDE_INVALIDATION: 196 case ACTION_PERFORM_IMPL_SIDE_INVALIDATION:
196 return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION"; 197 return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION";
198 case ACTION_DO_IDLE_WORK:
199 return "ACTION_DO_IDLE_WORK";
197 } 200 }
198 NOTREACHED(); 201 NOTREACHED();
199 return "???"; 202 return "???";
200 } 203 }
201 204
202 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> 205 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
203 SchedulerStateMachine::AsValue() const { 206 SchedulerStateMachine::AsValue() const {
204 std::unique_ptr<base::trace_event::TracedValue> state( 207 std::unique_ptr<base::trace_event::TracedValue> state(
205 new base::trace_event::TracedValue()); 208 new base::trace_event::TracedValue());
206 AsValueInto(state.get()); 209 AsValueInto(state.get());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 state->SetInteger("last_begin_frame_sequence_number_pending_tree_was_fresh", 242 state->SetInteger("last_begin_frame_sequence_number_pending_tree_was_fresh",
240 last_begin_frame_sequence_number_pending_tree_was_fresh_); 243 last_begin_frame_sequence_number_pending_tree_was_fresh_);
241 state->SetInteger("last_begin_frame_sequence_number_active_tree_was_fresh", 244 state->SetInteger("last_begin_frame_sequence_number_active_tree_was_fresh",
242 last_begin_frame_sequence_number_active_tree_was_fresh_); 245 last_begin_frame_sequence_number_active_tree_was_fresh_);
243 state->SetInteger( 246 state->SetInteger(
244 "last_begin_frame_sequence_number_compositor_frame_was_fresh", 247 "last_begin_frame_sequence_number_compositor_frame_was_fresh",
245 last_begin_frame_sequence_number_compositor_frame_was_fresh_); 248 last_begin_frame_sequence_number_compositor_frame_was_fresh_);
246 state->SetBoolean("funnel: draw_funnel", draw_funnel_); 249 state->SetBoolean("funnel: draw_funnel", draw_funnel_);
247 state->SetBoolean("funnel: send_begin_main_frame_funnel", 250 state->SetBoolean("funnel: send_begin_main_frame_funnel",
248 send_begin_main_frame_funnel_); 251 send_begin_main_frame_funnel_);
252 state->SetBoolean("funnel: do_idle_work_funnel", do_idle_work_funnel_);
249 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_); 253 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_);
250 state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel", 254 state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel",
251 invalidate_compositor_frame_sink_funnel_); 255 invalidate_compositor_frame_sink_funnel_);
252 state->SetBoolean("funnel: impl_side_invalidation_funnel", 256 state->SetBoolean("funnel: impl_side_invalidation_funnel",
253 impl_side_invalidation_funnel_); 257 impl_side_invalidation_funnel_);
254 state->SetInteger("consecutive_checkerboard_animations", 258 state->SetInteger("consecutive_checkerboard_animations",
255 consecutive_checkerboard_animations_); 259 consecutive_checkerboard_animations_);
256 state->SetInteger("pending_submit_frames_", pending_submit_frames_); 260 state->SetInteger("pending_submit_frames_", pending_submit_frames_);
257 state->SetInteger("submit_frames_with_current_compositor_frame_sink", 261 state->SetInteger("submit_frames_with_current_compositor_frame_sink",
258 submit_frames_with_current_compositor_frame_sink_); 262 submit_frames_with_current_compositor_frame_sink_);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 return false; 425 return false;
422 426
423 // If we want to force activation, do so ASAP. 427 // If we want to force activation, do so ASAP.
424 if (PendingActivationsShouldBeForced()) 428 if (PendingActivationsShouldBeForced())
425 return true; 429 return true;
426 430
427 // At this point, only activate if we are ready to activate. 431 // At this point, only activate if we are ready to activate.
428 return pending_tree_is_ready_for_activation_; 432 return pending_tree_is_ready_for_activation_;
429 } 433 }
430 434
435 bool SchedulerStateMachine::CouldDoIdleWork() const {
436 if (needs_begin_main_frame_ || send_begin_main_frame_funnel_)
Dan Elphick 2017/03/21 11:23:51 I made this change here because needs_begin_main_f
Sami 2017/03/21 11:35:21 I wonder if we should look at begin_main_frame_sta
Sami 2017/03/21 11:36:39 Just to clarify: the problem with looking at the f
Dan Elphick 2017/03/21 15:56:25 I've renamed the funnel as discussed in comments e
437 return false;
438
439 // We can not perform commits if we are not visible.
440 if (!visible_)
441 return false;
442
443 // There are no BeginImplFrames while BeginFrameSource is paused,
444 // so should also stop BeginMainFrames.
445 if (begin_frame_source_paused_)
446 return false;
447
448 // Do not make a new commits when it is deferred.
449 if (defer_commits_)
450 return false;
451
452 return true;
453 }
454
455 bool SchedulerStateMachine::ShouldDoIdleWork() const {
456 if (!CouldDoIdleWork())
457 return false;
458
459 // Do not do idle work too many times in a single frame or before
460 // the first BeginFrame.
461 if (do_idle_work_funnel_)
462 return false;
463
464 // Only send BeginMainFrame when there isn't another commit pending already.
465 // Other parts of the state machine indirectly defer the BeginMainFrame
466 // by transitioning to WAITING commit states rather than going
467 // immediately to IDLE.
468 if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE)
469 return false;
470
471 // MFBA is disabled and we are waiting for previous activation.
472 if (!settings_.main_frame_before_activation_enabled && has_pending_tree_)
473 return false;
474
475 // We are waiting for previous frame to be drawn, submitted and acked.
476 if (settings_.commit_to_active_tree &&
477 (active_tree_needs_first_draw_ || IsDrawThrottled())) {
478 return false;
479 }
480
481 // Don't send BeginMainFrame early if we are prioritizing the active tree
482 // because of ImplLatencyTakesPriority.
483 if (ImplLatencyTakesPriority() &&
484 (has_pending_tree_ || active_tree_needs_first_draw_)) {
485 return false;
486 }
487
488 // We should not send BeginMainFrame while we are in the idle state since we
489 // might have new user input arriving soon. It's okay to send BeginMainFrame
490 // for the synchronous compositor because the main thread is always high
491 // latency in that case.
492 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
493 // thread isn't consuming user input for non-synchronous compositor.
494 if (!settings_.using_synchronous_renderer_compositor &&
495 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE) {
496 return false;
497 }
498
499 // We need a new commit for the forced redraw. This honors the
500 // single commit per interval because the result will be swapped to screen.
501 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
502 return true;
503
504 // We shouldn't normally accept commits if there isn't an CompositorFrameSink.
505 if (!HasInitializedCompositorFrameSink())
506 return false;
507
508 if (!settings_.main_frame_while_submit_frame_throttled_enabled) {
509 // Throttle the BeginMainFrames on CompositorFrameAck unless we just
510 // submitted a frame to potentially improve impl-thread latency over
511 // main-thread throughput.
512 // TODO(brianderson): Remove this restriction to improve throughput or
513 // make it conditional on ImplLatencyTakesPriority.
514 bool just_submitted_in_deadline =
515 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
516 did_submit_in_last_frame_;
517 if (IsDrawThrottled() && !just_submitted_in_deadline)
518 return false;
519 }
520
521 if (skip_next_begin_main_frame_to_reduce_latency_)
522 return false;
523
524 return true;
525 }
526
431 bool SchedulerStateMachine::CouldSendBeginMainFrame() const { 527 bool SchedulerStateMachine::CouldSendBeginMainFrame() const {
432 if (!needs_begin_main_frame_) 528 if (!needs_begin_main_frame_)
433 return false; 529 return false;
434 530
435 // We can not perform commits if we are not visible. 531 // We can not perform commits if we are not visible.
436 if (!visible_) 532 if (!visible_)
437 return false; 533 return false;
438 534
439 // There are no BeginImplFrames while BeginFrameSource is paused, 535 // There are no BeginImplFrames while BeginFrameSource is paused,
440 // so should also stop BeginMainFrames. 536 // so should also stop BeginMainFrames.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 return ACTION_DRAW_FORCED; 683 return ACTION_DRAW_FORCED;
588 else 684 else
589 return ACTION_DRAW_IF_POSSIBLE; 685 return ACTION_DRAW_IF_POSSIBLE;
590 } 686 }
591 if (ShouldPerformImplSideInvalidation()) 687 if (ShouldPerformImplSideInvalidation())
592 return ACTION_PERFORM_IMPL_SIDE_INVALIDATION; 688 return ACTION_PERFORM_IMPL_SIDE_INVALIDATION;
593 if (ShouldPrepareTiles()) 689 if (ShouldPrepareTiles())
594 return ACTION_PREPARE_TILES; 690 return ACTION_PREPARE_TILES;
595 if (ShouldSendBeginMainFrame()) 691 if (ShouldSendBeginMainFrame())
596 return ACTION_SEND_BEGIN_MAIN_FRAME; 692 return ACTION_SEND_BEGIN_MAIN_FRAME;
693 if (ShouldDoIdleWork())
694 return ACTION_DO_IDLE_WORK;
597 if (ShouldInvalidateCompositorFrameSink()) 695 if (ShouldInvalidateCompositorFrameSink())
598 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; 696 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK;
599 if (ShouldBeginCompositorFrameSinkCreation()) 697 if (ShouldBeginCompositorFrameSinkCreation())
600 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION; 698 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION;
601 return ACTION_NONE; 699 return ACTION_NONE;
602 } 700 }
603 701
604 bool SchedulerStateMachine::ShouldPerformImplSideInvalidation() const { 702 bool SchedulerStateMachine::ShouldPerformImplSideInvalidation() const {
605 if (!needs_impl_side_invalidation_) 703 if (!needs_impl_side_invalidation_)
606 return false; 704 return false;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 DCHECK(!begin_frame_source_paused_); 783 DCHECK(!begin_frame_source_paused_);
686 DCHECK(!send_begin_main_frame_funnel_); 784 DCHECK(!send_begin_main_frame_funnel_);
687 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT; 785 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT;
688 needs_begin_main_frame_ = false; 786 needs_begin_main_frame_ = false;
689 send_begin_main_frame_funnel_ = true; 787 send_begin_main_frame_funnel_ = true;
690 last_frame_number_begin_main_frame_sent_ = current_frame_number_; 788 last_frame_number_begin_main_frame_sent_ = current_frame_number_;
691 last_begin_frame_sequence_number_begin_main_frame_sent_ = 789 last_begin_frame_sequence_number_begin_main_frame_sent_ =
692 begin_frame_sequence_number_; 790 begin_frame_sequence_number_;
693 } 791 }
694 792
793 void SchedulerStateMachine::WillDoIdleWork() {
794 DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
795 DCHECK(visible_);
796 DCHECK(!begin_frame_source_paused_);
797 DCHECK(!do_idle_work_funnel_);
798 do_idle_work_funnel_ = true;
799 }
800
695 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { 801 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) {
696 bool can_have_pending_tree = 802 bool can_have_pending_tree =
697 commit_has_no_updates && 803 commit_has_no_updates &&
698 (settings_.main_frame_before_activation_enabled || 804 (settings_.main_frame_before_activation_enabled ||
699 current_pending_tree_is_impl_side_); 805 current_pending_tree_is_impl_side_);
700 DCHECK(!has_pending_tree_ || can_have_pending_tree); 806 DCHECK(!has_pending_tree_ || can_have_pending_tree);
701 commit_count_++; 807 commit_count_++;
702 last_commit_had_no_updates_ = commit_has_no_updates; 808 last_commit_had_no_updates_ = commit_has_no_updates;
703 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; 809 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
704 810
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 1146
1041 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; 1147 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
1042 current_frame_number_++; 1148 current_frame_number_++;
1043 1149
1044 last_commit_had_no_updates_ = false; 1150 last_commit_had_no_updates_ = false;
1045 did_draw_in_last_frame_ = false; 1151 did_draw_in_last_frame_ = false;
1046 did_submit_in_last_frame_ = false; 1152 did_submit_in_last_frame_ = false;
1047 needs_one_begin_impl_frame_ = false; 1153 needs_one_begin_impl_frame_ = false;
1048 1154
1049 // Clear funnels for any actions we perform during the frame. 1155 // Clear funnels for any actions we perform during the frame.
1156 do_idle_work_funnel_ = false;
1050 send_begin_main_frame_funnel_ = false; 1157 send_begin_main_frame_funnel_ = false;
1051 invalidate_compositor_frame_sink_funnel_ = false; 1158 invalidate_compositor_frame_sink_funnel_ = false;
1052 impl_side_invalidation_funnel_ = false; 1159 impl_side_invalidation_funnel_ = false;
1053 1160
1054 // "Drain" the PrepareTiles funnel. 1161 // "Drain" the PrepareTiles funnel.
1055 if (prepare_tiles_funnel_ > 0) 1162 if (prepare_tiles_funnel_ > 0)
1056 prepare_tiles_funnel_--; 1163 prepare_tiles_funnel_--;
1057 } 1164 }
1058 1165
1059 void SchedulerStateMachine::OnBeginImplFrameDeadline() { 1166 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 case COMPOSITOR_FRAME_SINK_ACTIVE: 1442 case COMPOSITOR_FRAME_SINK_ACTIVE:
1336 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: 1443 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT:
1337 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: 1444 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION:
1338 return true; 1445 return true;
1339 } 1446 }
1340 NOTREACHED(); 1447 NOTREACHED();
1341 return false; 1448 return false;
1342 } 1449 }
1343 1450
1344 } // namespace cc 1451 } // 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