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

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

Issue 16871016: cc: Use BeginFrameArgs (Closed) Base URL: http://git.chromium.org/chromium/src.git@bfargs2
Patch Set: Add an --enable-deadline-scheduler commandline flag. Created 7 years, 4 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 10
11 namespace cc { 11 namespace cc {
12 12
13 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 13 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
14 : settings_(settings), 14 : settings_(settings),
15 output_surface_state_(OUTPUT_SURFACE_LOST),
16 begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
15 commit_state_(COMMIT_STATE_IDLE), 17 commit_state_(COMMIT_STATE_IDLE),
18 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
19 readback_state_(READBACK_STATE_IDLE),
20 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
16 commit_count_(0), 21 commit_count_(0),
17 current_frame_number_(0), 22 begin_frame_count_(0),
18 last_frame_number_where_begin_frame_sent_to_main_thread_(-1), 23 draw_attempt_count_(0),
19 last_frame_number_where_draw_was_called_(-1), 24 last_begin_frame_count_swap_performed_(-1),
20 last_frame_number_where_tree_activation_attempted_(-1), 25 last_draw_attempt_count_draw_was_called_(-1),
21 last_frame_number_where_update_visible_tiles_was_called_(-1), 26 last_begin_frame_count_begin_frame_sent_to_main_thread_(-1),
27 last_draw_attempt_count_tree_activation_attempted_(-1),
28 last_draw_attempt_count_update_visible_tiles_was_called_(-1),
22 consecutive_failed_draws_(0), 29 consecutive_failed_draws_(0),
23 maximum_number_of_failed_draws_before_draw_is_forced_(3), 30 maximum_number_of_failed_draws_before_draw_is_forced_(3),
24 needs_redraw_(false), 31 needs_redraw_(false),
25 swap_used_incomplete_tile_(false), 32 swap_used_incomplete_tile_(false),
26 needs_forced_redraw_(false),
27 needs_forced_redraw_after_next_commit_(false),
28 needs_redraw_after_next_commit_(false),
29 needs_commit_(false), 33 needs_commit_(false),
30 needs_forced_commit_(false),
31 expect_immediate_begin_frame_for_main_thread_(false),
32 main_thread_needs_layer_textures_(false), 34 main_thread_needs_layer_textures_(false),
33 inside_begin_frame_(false), 35 active_tree_has_been_drawn_(false),
36 active_tree_is_null_(true),
34 visible_(false), 37 visible_(false),
35 can_start_(false), 38 can_start_(false),
36 can_draw_(false), 39 can_draw_(false),
37 has_pending_tree_(false), 40 has_pending_tree_(false),
41 pending_tree_is_ready_for_activation_(false),
38 draw_if_possible_failed_(false), 42 draw_if_possible_failed_(false),
39 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
40 output_surface_state_(OUTPUT_SURFACE_LOST),
41 did_create_and_initialize_first_output_surface_(false) {} 43 did_create_and_initialize_first_output_surface_(false) {}
42 44
43 std::string SchedulerStateMachine::ToString() { 45 std::string SchedulerStateMachine::ToString() {
44 std::string str; 46 std::string str;
45 base::StringAppendF(&str, 47 base::StringAppendF(&str,
46 "settings_.impl_side_painting = %d; ", 48 "settings_.impl_side_painting = %d; ",
47 settings_.impl_side_painting); 49 settings_.impl_side_painting);
50 base::StringAppendF(
51 &str, "output_surface_state_ = %d; ", output_surface_state_);
52 base::StringAppendF(&str, "begin_frame_state_ = %d; ", begin_frame_state_);
48 base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_); 53 base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_);
54 base::StringAppendF(&str, "texture_state_ = %d; ", texture_state_);
55 base::StringAppendF(&str, "readback_state_ = %d; ", readback_state_);
56 base::StringAppendF(
57 &str, "forced_redraw_state_ = %d; ", forced_redraw_state_);
49 base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_); 58 base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_);
50 base::StringAppendF( 59 base::StringAppendF(&str, "begin_frame_count_ = %d; ", begin_frame_count_);
51 &str, "current_frame_number_ = %d; ", current_frame_number_); 60 base::StringAppendF(&str, "draw_attempt_count_ = %d; ", draw_attempt_count_);
52 base::StringAppendF(&str, 61 base::StringAppendF(&str,
53 "last_frame_number_where_draw_was_called_ = %d; ", 62 "last_begin_frame_count_swap_performed_ = %d; ",
54 last_frame_number_where_draw_was_called_); 63 last_begin_frame_count_swap_performed_);
64 base::StringAppendF(&str,
65 "last_draw_attempt_count_draw_was_called_ = %d; ",
66 last_draw_attempt_count_draw_was_called_);
55 base::StringAppendF( 67 base::StringAppendF(
56 &str, 68 &str,
57 "last_frame_number_where_tree_activation_attempted_ = %d; ", 69 "last_begin_frame_count_begin_frame_sent_to_main_thread_ = %d; ",
58 last_frame_number_where_tree_activation_attempted_); 70 last_begin_frame_count_begin_frame_sent_to_main_thread_);
59 base::StringAppendF( 71 base::StringAppendF(
60 &str, 72 &str,
61 "last_frame_number_where_update_visible_tiles_was_called_ = %d; ", 73 "last_draw_attempt_count_tree_activation_attempted_ = %d; ",
62 last_frame_number_where_update_visible_tiles_was_called_); 74 last_draw_attempt_count_tree_activation_attempted_);
75 base::StringAppendF(
76 &str,
77 "last_draw_attempt_count_update_visible_tiles_was_called_ = %d; ",
78 last_draw_attempt_count_update_visible_tiles_was_called_);
63 base::StringAppendF( 79 base::StringAppendF(
64 &str, "consecutive_failed_draws_ = %d; ", consecutive_failed_draws_); 80 &str, "consecutive_failed_draws_ = %d; ", consecutive_failed_draws_);
65 base::StringAppendF( 81 base::StringAppendF(
66 &str, 82 &str,
67 "maximum_number_of_failed_draws_before_draw_is_forced_ = %d; ", 83 "maximum_number_of_failed_draws_before_draw_is_forced_ = %d; ",
68 maximum_number_of_failed_draws_before_draw_is_forced_); 84 maximum_number_of_failed_draws_before_draw_is_forced_);
69 base::StringAppendF(&str, "needs_redraw_ = %d; ", needs_redraw_); 85 base::StringAppendF(&str, "needs_redraw_ = %d; ", needs_redraw_);
70 base::StringAppendF( 86 base::StringAppendF(
71 &str, "swap_used_incomplete_tile_ = %d; ", swap_used_incomplete_tile_); 87 &str, "swap_used_incomplete_tile_ = %d; ", swap_used_incomplete_tile_);
72 base::StringAppendF(
73 &str, "needs_forced_redraw_ = %d; ", needs_forced_redraw_);
74 base::StringAppendF(&str,
75 "needs_forced_redraw_after_next_commit_ = %d; ",
76 needs_forced_redraw_after_next_commit_);
77 base::StringAppendF(&str, "needs_commit_ = %d; ", needs_commit_); 88 base::StringAppendF(&str, "needs_commit_ = %d; ", needs_commit_);
78 base::StringAppendF(
79 &str, "needs_forced_commit_ = %d; ", needs_forced_commit_);
80 base::StringAppendF(&str,
81 "expect_immediate_begin_frame_for_main_thread_ = %d; ",
82 expect_immediate_begin_frame_for_main_thread_);
83 base::StringAppendF(&str, 89 base::StringAppendF(&str,
84 "main_thread_needs_layer_textures_ = %d; ", 90 "main_thread_needs_layer_textures_ = %d; ",
85 main_thread_needs_layer_textures_); 91 main_thread_needs_layer_textures_);
86 base::StringAppendF(&str, "inside_begin_frame_ = %d; ",
87 inside_begin_frame_);
88 base::StringAppendF(&str, "last_frame_time_ = %" PRId64 "; ", 92 base::StringAppendF(&str, "last_frame_time_ = %" PRId64 "; ",
89 (last_begin_frame_args_.frame_time - base::TimeTicks()) 93 (last_begin_frame_args_.frame_time - base::TimeTicks())
90 .InMilliseconds()); 94 .InMilliseconds());
91 base::StringAppendF(&str, "last_deadline_ = %" PRId64 "; ", 95 base::StringAppendF(&str, "last_deadline_ = %" PRId64 "; ",
92 (last_begin_frame_args_.deadline - base::TimeTicks()).InMilliseconds()); 96 (last_begin_frame_args_.deadline - base::TimeTicks()).InMilliseconds());
93 base::StringAppendF(&str, "last_interval_ = %" PRId64 "; ", 97 base::StringAppendF(&str, "last_interval_ = %" PRId64 "; ",
94 last_begin_frame_args_.interval.InMilliseconds()); 98 last_begin_frame_args_.interval.InMilliseconds());
95 base::StringAppendF(&str, "visible_ = %d; ", visible_); 99 base::StringAppendF(&str, "visible_ = %d; ", visible_);
96 base::StringAppendF(&str, "can_start_ = %d; ", can_start_); 100 base::StringAppendF(&str, "can_start_ = %d; ", can_start_);
97 base::StringAppendF(&str, "can_draw_ = %d; ", can_draw_); 101 base::StringAppendF(&str, "can_draw_ = %d; ", can_draw_);
98 base::StringAppendF( 102 base::StringAppendF(
99 &str, "draw_if_possible_failed_ = %d; ", draw_if_possible_failed_); 103 &str, "draw_if_possible_failed_ = %d; ", draw_if_possible_failed_);
100 base::StringAppendF(&str, "has_pending_tree_ = %d; ", has_pending_tree_); 104 base::StringAppendF(&str, "has_pending_tree_ = %d; ", has_pending_tree_);
101 base::StringAppendF(&str, "texture_state_ = %d; ", texture_state_); 105 base::StringAppendF(&str,
106 "pending_tree_is_ready_for_activation_ = %d; ",
107 pending_tree_is_ready_for_activation_);
102 base::StringAppendF( 108 base::StringAppendF(
103 &str, "output_surface_state_ = %d; ", output_surface_state_); 109 &str, "active_tree_has_been_drawn_ = %d; ", active_tree_has_been_drawn_);
110 base::StringAppendF(
111 &str, "active_tree_is_null_ = %d; ", active_tree_is_null_);
104 return str; 112 return str;
105 } 113 }
106 114
107 bool SchedulerStateMachine::HasDrawnThisFrame() const { 115 bool SchedulerStateMachine::HasDrawnThisFrame() const {
108 return current_frame_number_ == last_frame_number_where_draw_was_called_; 116 return begin_frame_count_ == last_begin_frame_count_swap_performed_;
109 } 117 }
110 118
111 bool SchedulerStateMachine::HasAttemptedTreeActivationThisFrame() const { 119 bool SchedulerStateMachine::HasDrawnThisDrawAttempt() const {
112 return current_frame_number_ == 120 return draw_attempt_count_ == last_draw_attempt_count_draw_was_called_;
113 last_frame_number_where_tree_activation_attempted_;
114 } 121 }
115 122
116 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 123 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
117 return current_frame_number_ == 124 return begin_frame_count_ ==
118 last_frame_number_where_update_visible_tiles_was_called_; 125 last_begin_frame_count_begin_frame_sent_to_main_thread_;
119 } 126 }
120 127
121 void SchedulerStateMachine::SetPostCommitFlags() { 128 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisDrawAttempt() const {
122 // This post-commit work is common to both completed and aborted commits. 129 return draw_attempt_count_ ==
123 if (needs_forced_redraw_after_next_commit_) { 130 last_draw_attempt_count_update_visible_tiles_was_called_;
124 needs_forced_redraw_after_next_commit_ = false; 131 }
125 needs_forced_redraw_ = true; 132
133 bool SchedulerStateMachine::HasActivatedPendingTreeThisDrawAttempt() const {
134 return draw_attempt_count_ ==
135 last_draw_attempt_count_tree_activation_attempted_;
136 }
137
138 void SchedulerStateMachine::HandleCommitInternal(bool commit_was_aborted) {
139 commit_count_++;
140 draw_attempt_count_++;
141
142 // If we are impl-side-painting but the commit was aborted, then we behave
143 // as if we are not impl-side-painting since there is no pending tree.
144 if (settings_.impl_side_painting && !commit_was_aborted) {
145 commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
146
147 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
148 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
149
150 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
151 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION;
152 else if (readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
153 readback_state_ = READBACK_STATE_WAITING_FOR_ACTIVATION;
154 else if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING)
155 readback_state_ = READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING;
156
157 } else {
158 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
159 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
160 needs_redraw_ = true;
161 }
162
163 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
164 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
165 else if (readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
166 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
167 else if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING)
168 readback_state_ = READBACK_STATE_IDLE;
169
170 if (draw_if_possible_failed_) {
171 last_begin_frame_count_swap_performed_ = -1;
172 last_draw_attempt_count_draw_was_called_ = -1;
173 }
174
175 if (commit_was_aborted) {
176 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW ||
177 readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
178 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
179 else
180 commit_state_ = COMMIT_STATE_IDLE;
181 } else {
182 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
183 active_tree_has_been_drawn_ = false;
184 needs_redraw_ = true;
185 }
126 } 186 }
127 if (needs_redraw_after_next_commit_) { 187
128 needs_redraw_after_next_commit_ = false;
129 needs_redraw_ = true;
130 }
131 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; 188 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
132 } 189 }
133 190
134 bool SchedulerStateMachine::DrawSuspendedUntilCommit() const { 191 bool SchedulerStateMachine::DrawSuspendedUntilCommit() const {
135 if (!can_draw_) 192 if (!can_draw_)
136 return true; 193 return true;
137 if (!visible_) 194 if (!visible_)
138 return true; 195 return true;
139 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) 196 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
140 return true; 197 return true;
141 return false; 198 return false;
142 } 199 }
143 200
144 bool SchedulerStateMachine::ScheduledToDraw() const { 201 bool SchedulerStateMachine::ScheduledToDraw() const {
145 if (!needs_redraw_) 202 if (!needs_redraw_)
146 return false; 203 return false;
147 if (DrawSuspendedUntilCommit()) 204 if (DrawSuspendedUntilCommit())
148 return false; 205 return false;
149 return true; 206 return true;
150 } 207 }
151 208
152 bool SchedulerStateMachine::ShouldDraw() const { 209 bool SchedulerStateMachine::ShouldDraw() const {
153 if (needs_forced_redraw_) 210 if (HasDrawnThisDrawAttempt())
211 return false;
212
213 // After a readback, make sure not to draw again until we've replaced the
214 // readback commit with a real one.
215 if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING ||
216 readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING)
217 return false;
218
219 // Draw outside of the BeginFrame deadline for readbacks.
220 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
221 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
154 return true; 222 return true;
223 }
224
225 // If we've lost the output surface or draw is suspended, we want to be able
226 // to abort a draw and make forward progress to unblock the main thread.
227 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
228 DrawSuspendedUntilCommit()) {
229 return !active_tree_has_been_drawn_ &&
230 (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW ||
231 commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION ||
232 (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
233 !active_tree_is_null_));
234 }
235
236 // Except for the cases above, do not draw outside of the BeginFrame deadline.
237 if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
238 return false;
239
240 // Only handle forced redraws due to timeouts on the regular deadline.
241 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
242 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
243 return true;
244 }
155 245
156 if (!ScheduledToDraw()) 246 if (!ScheduledToDraw())
157 return false; 247 return false;
158 if (!inside_begin_frame_)
159 return false;
160 if (HasDrawnThisFrame()) 248 if (HasDrawnThisFrame())
161 return false; 249 return false;
162 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 250 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE)
163 return false; 251 return false;
164 return true; 252 return true;
165 } 253 }
166 254
167 bool SchedulerStateMachine::ShouldAttemptTreeActivation() const { 255 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
168 return has_pending_tree_ && inside_begin_frame_ && 256 // Some quick early outs.
169 !HasAttemptedTreeActivationThisFrame(); 257 if (!has_pending_tree_)
258 return false;
259 if (HasActivatedPendingTreeThisDrawAttempt())
260 return false;
261
262 // If this is our first activation, we don't want to activate early.
263 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
264 return pending_tree_is_ready_for_activation_;
265
266 // In these cases, we want to activate even if the pending tree isn't ready
267 // because we aren't going to draw the pending tree or need to make
268 // forward progress to unblock the main thread.
269 if (!visible_ || output_surface_state_ == OUTPUT_SURFACE_LOST ||
270 output_surface_state_ == OUTPUT_SURFACE_CREATING ||
271 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
272 return true;
273
274 // After this line, we only want to activate if we are ready to activate.
275 if (!pending_tree_is_ready_for_activation_)
276 return false;
277
278 // We do not want to activate a second tree before drawing the first one.
279 // Note: If we cannot draw, activation will eventually be unblocked by
280 // ACTION_DRAW_AND_SWAP_ABORT which will set active_tree_has_been_drawn_.
281 return active_tree_has_been_drawn_ || active_tree_is_null_;
170 } 282 }
171 283
172 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 284 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
173 if (!settings_.impl_side_painting) 285 if (!settings_.impl_side_painting)
174 return false; 286 return false;
175 if (HasUpdatedVisibleTilesThisFrame()) 287 if (HasUpdatedVisibleTilesThisDrawAttempt())
176 return false; 288 return false;
177 289
178 return ShouldAttemptTreeActivation() || ShouldDraw() || 290 return ShouldActivatePendingTree() || ShouldDraw() ||
179 swap_used_incomplete_tile_; 291 swap_used_incomplete_tile_;
180 } 292 }
181 293
182 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const { 294 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
183 if (!main_thread_needs_layer_textures_) 295 if (!main_thread_needs_layer_textures_)
184 return false; 296 return false;
185 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED) 297 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
186 return true; 298 return true;
187 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); 299 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
188 // Transfer the lock from impl thread to main thread immediately if the 300 // Transfer the lock from impl thread to main thread immediately if the
189 // impl thread is not even scheduled to draw. Guards against deadlocking. 301 // impl thread is not even scheduled to draw. Guards against deadlocking.
190 if (!ScheduledToDraw()) 302 if (!ScheduledToDraw())
191 return true; 303 return true;
192 if (!BeginFrameNeededToDrawByImplThread()) 304 if (!BeginFrameNeededToDrawByImplThread())
193 return true; 305 return true;
194 return false; 306 return false;
195 } 307 }
196 308
309 bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
310 if (HasSentBeginFrameToMainThreadThisFrame())
311 return false;
312
313 // Only send BeginFrame to the main thread when idle.
314 if (commit_state_ != COMMIT_STATE_IDLE)
315 return false;
316
317 // We can't accept a commit if we have a pending tree.
318 if (has_pending_tree_)
319 return false;
320
321 // We want to handle readback commits ASAP.
322 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED)
323 return !CommitPending();
324
325 // We want to start the first commit after we get a new output surface
326 // immediately.
327 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT &&
328 needs_commit_)
329 return true;
330
331 // We usually want to slave the main thread's BeginFrame to the impl thread's
332 // BeginFrame. However, if we aren't expecting a BeginFrame on the impl
333 // thread, we should send a BeginFrame to the main thread anyway to make
334 // progress.
335 // TODO(brianderson): Also allow sending BeginFrame to main thread while idle
336 // when the main thread isn't consuming user input.
337 if (begin_frame_state_ == BEGIN_FRAME_STATE_IDLE &&
338 BeginFrameNeededByImplThread())
339 return false;
340
341 // Do not send begin frame to main thread in the deadline until we have drawn.
342 // We have a train to catch!
343 if (begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_DEADLINE &&
344 !HasDrawnThisFrame())
345 return false;
346
347 // If not impl-side-painting, do not send a BeginFrame to the main thread if
348 // we haven't drawn the active tree. Otherwise, the commit could overwrite the
349 // active tree before we have a chance to draw it.
350 if (!settings_.impl_side_painting && !active_tree_has_been_drawn_ &&
351 !active_tree_is_null_)
352 return false;
353
354 bool can_commit =
355 needs_commit_ && (visible_ || forced_redraw_state_ ==
356 FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
357 return can_commit &&
358 (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT ||
359 HasInitializedOutputSurface());
360 }
361
197 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 362 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
198 if (ShouldAcquireLayerTexturesForMainThread()) 363 if (ShouldAcquireLayerTexturesForMainThread())
199 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 364 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
200 365
201 switch (commit_state_) { 366 switch (commit_state_) {
202 case COMMIT_STATE_IDLE: { 367 case COMMIT_STATE_IDLE:
203 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE && 368 if (ShouldSendBeginFrameToMainThread())
204 needs_forced_redraw_) 369 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
205 return ACTION_DRAW_FORCED;
206 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE &&
207 needs_forced_commit_)
208 // TODO(enne): Should probably drop the active tree on force commit.
209 return has_pending_tree_ ? ACTION_NONE
210 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
211 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_) 370 if (output_surface_state_ == OUTPUT_SURFACE_LOST && can_start_)
212 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 371 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
213 if (output_surface_state_ == OUTPUT_SURFACE_CREATING) 372 if (output_surface_state_ == OUTPUT_SURFACE_CREATING)
214 return ACTION_NONE; 373 return ACTION_NONE;
215 if (ShouldUpdateVisibleTiles()) 374 if (ShouldUpdateVisibleTiles())
216 return ACTION_UPDATE_VISIBLE_TILES; 375 return ACTION_UPDATE_VISIBLE_TILES;
217 if (ShouldAttemptTreeActivation()) 376 if (ShouldActivatePendingTree())
218 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 377 return ACTION_ACTIVATE_PENDING_TREE;
219 if (ShouldDraw()) { 378 if (ShouldDraw()) {
220 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 379 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
221 : ACTION_DRAW_IF_POSSIBLE; 380 DrawSuspendedUntilCommit())
381 return ACTION_DRAW_AND_SWAP_ABORT;
382 else
383 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
222 } 384 }
223 bool can_commit_this_frame =
224 visible_ &&
225 current_frame_number_ >
226 last_frame_number_where_begin_frame_sent_to_main_thread_;
227 if (needs_commit_ && ((can_commit_this_frame &&
228 output_surface_state_ == OUTPUT_SURFACE_ACTIVE) ||
229 needs_forced_commit_))
230 // TODO(enne): Should probably drop the active tree on force commit.
231 return has_pending_tree_ ? ACTION_NONE
232 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
233 return ACTION_NONE; 385 return ACTION_NONE;
234 } 386
235 case COMMIT_STATE_FRAME_IN_PROGRESS: 387 case COMMIT_STATE_FRAME_IN_PROGRESS:
236 if (ShouldUpdateVisibleTiles()) 388 if (ShouldUpdateVisibleTiles())
237 return ACTION_UPDATE_VISIBLE_TILES; 389 return ACTION_UPDATE_VISIBLE_TILES;
238 if (ShouldAttemptTreeActivation()) 390 if (ShouldActivatePendingTree())
239 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 391 return ACTION_ACTIVATE_PENDING_TREE;
240 if (ShouldDraw()) { 392 if (ShouldDraw()) {
241 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 393 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
242 : ACTION_DRAW_IF_POSSIBLE; 394 DrawSuspendedUntilCommit())
395 return ACTION_DRAW_AND_SWAP_ABORT;
396 else
397 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
243 } 398 }
244 return ACTION_NONE; 399 return ACTION_NONE;
245 400
246 case COMMIT_STATE_READY_TO_COMMIT: 401 case COMMIT_STATE_READY_TO_COMMIT:
247 return ACTION_COMMIT; 402 return ACTION_COMMIT;
248 403
404 case COMMIT_STATE_WAITING_FOR_ACTIVATION: {
405 if (ShouldUpdateVisibleTiles())
406 return ACTION_UPDATE_VISIBLE_TILES;
407 if (ShouldActivatePendingTree())
408 return ACTION_ACTIVATE_PENDING_TREE;
409 if (ShouldDraw()) {
410 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
411 DrawSuspendedUntilCommit())
412 return ACTION_DRAW_AND_SWAP_ABORT;
413 else
414 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
415 }
416 return ACTION_NONE;
417 }
418
249 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: { 419 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: {
250 if (ShouldUpdateVisibleTiles()) 420 if (ShouldUpdateVisibleTiles())
251 return ACTION_UPDATE_VISIBLE_TILES; 421 return ACTION_UPDATE_VISIBLE_TILES;
252 if (ShouldAttemptTreeActivation()) 422 if (ShouldActivatePendingTree())
253 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED; 423 return ACTION_ACTIVATE_PENDING_TREE;
254 if (ShouldDraw() || output_surface_state_ == OUTPUT_SURFACE_LOST) { 424 if (ShouldDraw()) {
255 return needs_forced_redraw_ ? ACTION_DRAW_FORCED 425 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
256 : ACTION_DRAW_IF_POSSIBLE; 426 return ACTION_DRAW_AND_SWAP_FORCED;
427 else if (readback_state_ ==
428 READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
429 return ACTION_DRAW_AND_READBACK;
430 else if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE ||
431 DrawSuspendedUntilCommit())
432 return ACTION_DRAW_AND_SWAP_ABORT;
433 else
434 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
257 } 435 }
258 // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If
259 // can_draw_ is false or textures are not available, proceed to the next
260 // step (similar as in COMMIT_STATE_IDLE).
261 bool can_commit =
262 needs_forced_commit_ ||
263 (visible_ &&
264 current_frame_number_ >
265 last_frame_number_where_begin_frame_sent_to_main_thread_);
266 if (needs_commit_ && can_commit && DrawSuspendedUntilCommit())
267 return has_pending_tree_ ? ACTION_NONE
268 : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
269 return ACTION_NONE; 436 return ACTION_NONE;
270 } 437 }
271
272 case COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW:
273 if (ShouldUpdateVisibleTiles())
274 return ACTION_UPDATE_VISIBLE_TILES;
275 if (ShouldAttemptTreeActivation())
276 return ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED;
277 if (needs_forced_redraw_)
278 return ACTION_DRAW_FORCED;
279 return ACTION_NONE;
280 } 438 }
281 NOTREACHED(); 439 NOTREACHED();
282 return ACTION_NONE; 440 return ACTION_NONE;
283 } 441 }
284 442
285 void SchedulerStateMachine::UpdateState(Action action) { 443 void SchedulerStateMachine::UpdateState(Action action) {
286 switch (action) { 444 switch (action) {
287 case ACTION_NONE: 445 case ACTION_NONE:
288 return; 446 return;
289 447
290 case ACTION_UPDATE_VISIBLE_TILES: 448 case ACTION_UPDATE_VISIBLE_TILES:
291 last_frame_number_where_update_visible_tiles_was_called_ = 449 last_draw_attempt_count_update_visible_tiles_was_called_ =
292 current_frame_number_; 450 draw_attempt_count_;
293 return; 451 return;
294 452
295 case ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: 453 case ACTION_ACTIVATE_PENDING_TREE:
296 last_frame_number_where_tree_activation_attempted_ = 454 last_draw_attempt_count_tree_activation_attempted_ = draw_attempt_count_;
297 current_frame_number_;
298 return; 455 return;
299 456
300 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 457 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
301 DCHECK(!has_pending_tree_); 458 DCHECK(!has_pending_tree_);
302 if (!needs_forced_commit_) { 459 DCHECK(visible_ ||
303 DCHECK(visible_); 460 readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED ||
304 DCHECK_GT(current_frame_number_, 461 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT ||
305 last_frame_number_where_begin_frame_sent_to_main_thread_); 462 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
306 }
307 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 463 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
308 needs_commit_ = false; 464 needs_commit_ = false;
309 needs_forced_commit_ = false; 465 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED)
310 last_frame_number_where_begin_frame_sent_to_main_thread_ = 466 readback_state_ = READBACK_STATE_FORCED_COMMIT_PENDING;
311 current_frame_number_; 467 last_begin_frame_count_begin_frame_sent_to_main_thread_ =
468 begin_frame_count_;
312 return; 469 return;
313 470
314 case ACTION_COMMIT: 471 case ACTION_COMMIT:
315 commit_count_++; 472 HandleCommitInternal(false);
316 if (expect_immediate_begin_frame_for_main_thread_)
317 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
318 else
319 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
320 // When impl-side painting, we draw on activation instead of on commit.
321 if (!settings_.impl_side_painting)
322 needs_redraw_ = true;
323 if (draw_if_possible_failed_)
324 last_frame_number_where_draw_was_called_ = -1;
325 SetPostCommitFlags();
326 return; 473 return;
327 474
328 case ACTION_DRAW_FORCED: 475 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
329 case ACTION_DRAW_IF_POSSIBLE: 476 case ACTION_DRAW_AND_SWAP_FORCED:
330 needs_redraw_ = false; 477 UpdateStateOnDraw(true);
331 needs_forced_redraw_ = false; 478 return;
332 draw_if_possible_failed_ = false; 479
333 swap_used_incomplete_tile_ = false; 480 case ACTION_DRAW_AND_READBACK:
334 if (inside_begin_frame_) 481 case ACTION_DRAW_AND_SWAP_ABORT:
335 last_frame_number_where_draw_was_called_ = current_frame_number_; 482 UpdateStateOnDraw(false);
336 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) {
337 DCHECK(expect_immediate_begin_frame_for_main_thread_);
338 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
339 expect_immediate_begin_frame_for_main_thread_ = false;
340 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
341 commit_state_ = COMMIT_STATE_IDLE;
342 }
343 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
344 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
345 return; 483 return;
346 484
347 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 485 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
348 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); 486 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
349 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 487 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
350 output_surface_state_ = OUTPUT_SURFACE_CREATING; 488 output_surface_state_ = OUTPUT_SURFACE_CREATING;
351 return; 489 return;
352 490
353 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 491 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
354 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; 492 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
355 main_thread_needs_layer_textures_ = false; 493 main_thread_needs_layer_textures_ = false;
356 return; 494 return;
357 } 495 }
358 } 496 }
359 497
498 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
499 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
500 commit_state_ = COMMIT_STATE_IDLE;
501 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
502 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
503 DCHECK(!has_pending_tree_);
504 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
505 readback_state_ = READBACK_STATE_REPLACEMENT_COMMIT_PENDING;
506 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
507 commit_state_ = COMMIT_STATE_IDLE;
508 }
509
510 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
511 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
512
513 needs_redraw_ = false;
514 active_tree_has_been_drawn_ = true;
515 draw_if_possible_failed_ = false;
516 last_draw_attempt_count_draw_was_called_ = draw_attempt_count_;
517
518 if (did_swap) {
519 swap_used_incomplete_tile_ = false;
520 last_begin_frame_count_swap_performed_ = begin_frame_count_;
521 }
522 }
523
524 void SchedulerStateMachine::AdvanceBeginFrameStateWhenNoActionsRemain() {
525 switch (begin_frame_state_) {
526 case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
527 begin_frame_state_ = BEGIN_FRAME_STATE_DEADLINE_PENDING;
528 break;
529 case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
530 begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
531 break;
532 case BEGIN_FRAME_STATE_IDLE:
533 case BEGIN_FRAME_STATE_DEADLINE_PENDING:
534 break;
535 }
536 }
537
360 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 538 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
361 DCHECK(!main_thread_needs_layer_textures_); 539 DCHECK(!main_thread_needs_layer_textures_);
362 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 540 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
363 main_thread_needs_layer_textures_ = true; 541 main_thread_needs_layer_textures_ = true;
364 } 542 }
365 543
544 bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
545 return BeginFrameNeededToDrawByImplThread() ||
546 BeginFrameProactivelyNeededByImplThread();
547 }
548
366 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 549 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
367 // If we can't draw, don't tick until we are notified that we can draw again. 550 // If we can't draw, don't tick until we are notified that we can draw again.
368 if (!can_draw_) 551 if (!can_draw_)
369 return false; 552 return false;
370 553
371 if (needs_forced_redraw_) 554 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
372 return true; 555 return true;
373 556
374 if (visible_ && swap_used_incomplete_tile_) 557 if (visible_ && swap_used_incomplete_tile_)
375 return true; 558 return true;
376 559
377 return needs_redraw_ && visible_ && 560 return needs_redraw_ && visible_ && HasInitializedOutputSurface();
378 output_surface_state_ == OUTPUT_SURFACE_ACTIVE;
379 } 561 }
380 562
381 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 563 bool SchedulerStateMachine::BeginFrameProactivelyNeededByImplThread() const {
382 // Do not be proactive when invisible. 564 if (settings_.using_synchronous_renderer_compositor)
383 if (!visible_ || output_surface_state_ != OUTPUT_SURFACE_ACTIVE) 565 return false;
566
567 if (!settings_.throttle_frame_production)
568 return false;
569
570 if (!visible_ || !HasInitializedOutputSurface())
384 return false; 571 return false;
385 572
386 // We should proactively request a BeginFrame if a commit or a tree activation 573 // We should proactively request a BeginFrame if a commit or a tree activation
387 // is pending. 574 // is pending.
388 return (needs_commit_ || needs_forced_commit_ || 575 return (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE ||
389 commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_); 576 has_pending_tree_);
390 } 577 }
391 578
392 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 579 void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
393 current_frame_number_++; 580 begin_frame_count_++;
394 inside_begin_frame_ = true; 581 draw_attempt_count_++;
395 last_begin_frame_args_ = args; 582 last_begin_frame_args_ = args;
583 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
396 } 584 }
397 585
398 void SchedulerStateMachine::DidLeaveBeginFrame() { 586 bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
399 inside_begin_frame_ = false; 587 // TODO(brianderson): This should take into account multiple commit sources.
588 return begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING &&
589 !active_tree_has_been_drawn_;
590 }
591
592 bool SchedulerStateMachine::InsideBeginFrame() const {
593 return begin_frame_state_ != BEGIN_FRAME_STATE_IDLE;
594 }
595
596 void SchedulerStateMachine::OnBeginFrameDeadline() {
597 DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_DEADLINE_PENDING);
598 draw_attempt_count_++;
599 begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
400 } 600 }
401 601
402 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 602 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
403 603
404 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 604 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
405 605
406 void SchedulerStateMachine::DidSwapUseIncompleteTile() { 606 void SchedulerStateMachine::DidSwapUseIncompleteTile() {
407 swap_used_incomplete_tile_ = true; 607 swap_used_incomplete_tile_ = true;
408 } 608 }
409 609
410 void SchedulerStateMachine::SetNeedsForcedRedraw() {
411 needs_forced_redraw_ = true;
412 }
413
414 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { 610 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
415 draw_if_possible_failed_ = !success; 611 draw_if_possible_failed_ = !success;
416 if (draw_if_possible_failed_) { 612 if (draw_if_possible_failed_) {
417 needs_redraw_ = true; 613 needs_redraw_ = true;
418 needs_commit_ = true; 614 needs_commit_ = true;
419 consecutive_failed_draws_++; 615 consecutive_failed_draws_++;
420 if (settings_.timeout_and_draw_when_animation_checkerboards && 616 if (settings_.timeout_and_draw_when_animation_checkerboards &&
421 consecutive_failed_draws_ >= 617 consecutive_failed_draws_ >=
422 maximum_number_of_failed_draws_before_draw_is_forced_) { 618 maximum_number_of_failed_draws_before_draw_is_forced_) {
423 consecutive_failed_draws_ = 0; 619 consecutive_failed_draws_ = 0;
424 // We need to force a draw, but it doesn't make sense to do this until 620 // We need to force a draw, but it doesn't make sense to do this until
425 // we've committed and have new textures. 621 // we've committed and have new textures.
426 needs_forced_redraw_after_next_commit_ = true; 622 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
427 } 623 }
428 } else { 624 } else {
429 consecutive_failed_draws_ = 0; 625 consecutive_failed_draws_ = 0;
430 } 626 }
431 } 627 }
432 628
433 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } 629 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
434 630
435 void SchedulerStateMachine::SetNeedsForcedCommit() { 631 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
436 needs_forced_commit_ = true; 632 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
437 expect_immediate_begin_frame_for_main_thread_ = true; 633 readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_PENDING);
634 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
635 readback_state_ = READBACK_STATE_FORCED_COMMIT_PENDING;
636 else
637 readback_state_ = READBACK_STATE_FORCED_COMMIT_REQUESTED;
438 } 638 }
439 639
440 void SchedulerStateMachine::FinishCommit() { 640 void SchedulerStateMachine::FinishCommit() {
441 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || 641 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
442 (expect_immediate_begin_frame_for_main_thread_ && 642 readback_state_ == READBACK_STATE_FORCED_COMMIT_PENDING)
443 commit_state_ != COMMIT_STATE_IDLE))
444 << ToString(); 643 << ToString();
445 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; 644 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
446 } 645 }
447 646
448 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) { 647 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
449 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS); 648 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
450 if (expect_immediate_begin_frame_for_main_thread_) { 649 if (readback_state_ == READBACK_STATE_FORCED_COMMIT_REQUESTED) {
451 expect_immediate_begin_frame_for_main_thread_ = false; 650 readback_state_ = READBACK_STATE_IDLE;
452 } else if (did_handle) { 651 } else if (did_handle) {
453 commit_state_ = COMMIT_STATE_IDLE; 652 HandleCommitInternal(true);
454 SetPostCommitFlags();
455 } else { 653 } else {
456 commit_state_ = COMMIT_STATE_IDLE; 654 commit_state_ = COMMIT_STATE_IDLE;
457 SetNeedsCommit(); 655 SetNeedsCommit();
458 } 656 }
459 } 657 }
460 658
461 void SchedulerStateMachine::DidLoseOutputSurface() { 659 void SchedulerStateMachine::DidLoseOutputSurface() {
462 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 660 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
463 output_surface_state_ == OUTPUT_SURFACE_CREATING) 661 output_surface_state_ == OUTPUT_SURFACE_CREATING)
464 return; 662 return;
465 output_surface_state_ = OUTPUT_SURFACE_LOST; 663 output_surface_state_ = OUTPUT_SURFACE_LOST;
664 needs_redraw_ = false;
466 } 665 }
467 666
468 void SchedulerStateMachine::SetHasPendingTree(bool has_pending_tree) { 667 void SchedulerStateMachine::NotifyReadyToActivate() {
668 if (has_pending_tree_)
669 pending_tree_is_ready_for_activation_ = true;
670 }
671
672 void SchedulerStateMachine::SetHasTrees(bool has_pending_tree,
673 bool active_tree_is_null) {
674 active_tree_is_null_ = active_tree_is_null;
675 if (has_pending_tree_ && !has_pending_tree) {
676 // There is a new active tree.
677 draw_attempt_count_++;
678 pending_tree_is_ready_for_activation_ = false;
679 active_tree_has_been_drawn_ = false;
680 needs_redraw_ = true;
681
682 if (draw_if_possible_failed_) {
683 last_begin_frame_count_swap_performed_ = -1;
684 last_draw_attempt_count_draw_was_called_ = -1;
685 }
686
687 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
688 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
689
690 DCHECK_EQ(COMMIT_STATE_WAITING_FOR_ACTIVATION, commit_state_);
691 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION) {
692 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
693 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
694 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) {
695 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
696 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
697 } else {
698 if (settings_.deadline_scheduling_enabled) {
699 // When deadline scheduling, we allow the next commit to start after
700 // the previous commit has activated but before it has been drawn.
701 commit_state_ = COMMIT_STATE_IDLE;
702 } else {
703 // When not deadline scheduling, we respect the old scheduling
704 // behavior of blocking the next commit until after the draw.
brianderson 2013/08/20 02:03:01 Since the feature of sending the BeginFrame to the
danakj 2013/08/20 02:27:21 If you can imagine people wanting to toggle the tw
705 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
706 }
707 if (readback_state_ == READBACK_STATE_REPLACEMENT_COMMIT_ACTIVATING)
708 readback_state_ = READBACK_STATE_IDLE;
709 }
710 } else if (!has_pending_tree_ && has_pending_tree) {
711 // There is a new pending tree.
712 pending_tree_is_ready_for_activation_ = false;
713 }
714
469 has_pending_tree_ = has_pending_tree; 715 has_pending_tree_ = has_pending_tree;
470 } 716 }
471 717
472 void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; } 718 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
473 719
474 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 720 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
475 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 721 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
476 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 722 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
477 723 if (did_create_and_initialize_first_output_surface_)
478 if (did_create_and_initialize_first_output_surface_) {
479 // TODO(boliu): See if we can remove this when impl-side painting is always
480 // on. Does anything on the main thread need to update after recreate?
481 needs_commit_ = true; 724 needs_commit_ = true;
482 // If anything has requested a redraw, we don't want to actually draw
483 // when the output surface is restored until things have a chance to
484 // sort themselves out with a commit.
485 needs_redraw_ = false;
486 }
487 needs_redraw_after_next_commit_ = true;
488 did_create_and_initialize_first_output_surface_ = true; 725 did_create_and_initialize_first_output_surface_ = true;
489 } 726 }
490 727
491 bool SchedulerStateMachine::HasInitializedOutputSurface() const { 728 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
492 return output_surface_state_ == OUTPUT_SURFACE_ACTIVE; 729 return output_surface_state_ != OUTPUT_SURFACE_LOST &&
730 output_surface_state_ != OUTPUT_SURFACE_CREATING;
493 } 731 }
494 732
495 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced( 733 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(
496 int num_draws) { 734 int num_draws) {
497 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws; 735 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws;
498 } 736 }
499 737
500 } // namespace cc 738 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698