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

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

Powered by Google App Engine
This is Rietveld 408576698