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

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

Issue 23503003: cc: Add readback and forced draw states to the Scheduler (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedReorg3
Patch Set: rebase Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/scheduler/scheduler_state_machine.h" 5 #include "cc/scheduler/scheduler_state_machine.h"
6 6
7 #include "base/format_macros.h" 7 #include "base/format_macros.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 11
12 namespace cc { 12 namespace cc {
13 13
14 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 14 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
15 : settings_(settings), 15 : settings_(settings),
16 output_surface_state_(OUTPUT_SURFACE_LOST), 16 output_surface_state_(OUTPUT_SURFACE_LOST),
17 commit_state_(COMMIT_STATE_IDLE), 17 commit_state_(COMMIT_STATE_IDLE),
18 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
19 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
20 readback_state_(READBACK_STATE_IDLE),
18 commit_count_(0), 21 commit_count_(0),
19 current_frame_number_(0), 22 current_frame_number_(0),
20 last_frame_number_where_begin_frame_sent_to_main_thread_(-1), 23 last_frame_number_where_begin_frame_sent_to_main_thread_(-1),
21 last_frame_number_where_draw_was_called_(-1), 24 last_frame_number_swap_performed_(-1),
22 last_frame_number_where_update_visible_tiles_was_called_(-1), 25 last_frame_number_where_update_visible_tiles_was_called_(-1),
23 consecutive_failed_draws_(0), 26 consecutive_failed_draws_(0),
24 maximum_number_of_failed_draws_before_draw_is_forced_(3),
25 needs_redraw_(false), 27 needs_redraw_(false),
26 swap_used_incomplete_tile_(false), 28 swap_used_incomplete_tile_(false),
27 needs_forced_redraw_(false),
28 needs_forced_redraw_after_next_commit_(false),
29 needs_commit_(false), 29 needs_commit_(false),
30 needs_forced_commit_(false),
31 expect_immediate_begin_frame_for_main_thread_(false),
32 main_thread_needs_layer_textures_(false), 30 main_thread_needs_layer_textures_(false),
33 inside_begin_frame_(false), 31 inside_begin_frame_(false),
34 visible_(false), 32 visible_(false),
35 can_start_(false), 33 can_start_(false),
36 can_draw_(false), 34 can_draw_(false),
37 has_pending_tree_(false), 35 has_pending_tree_(false),
38 pending_tree_is_ready_for_activation_(false), 36 pending_tree_is_ready_for_activation_(false),
39 active_tree_has_been_drawn_(false), 37 active_tree_needs_first_draw_(false),
40 draw_if_possible_failed_(false), 38 draw_if_possible_failed_(false),
41 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
42 did_create_and_initialize_first_output_surface_(false) {} 39 did_create_and_initialize_first_output_surface_(false) {}
43 40
44 const char* SchedulerStateMachine::OutputSurfaceStateToString( 41 const char* SchedulerStateMachine::OutputSurfaceStateToString(
45 OutputSurfaceState state) { 42 OutputSurfaceState state) {
46 switch (state) { 43 switch (state) {
47 case OUTPUT_SURFACE_ACTIVE: 44 case OUTPUT_SURFACE_ACTIVE:
48 return "OUTPUT_SURFACE_ACTIVE"; 45 return "OUTPUT_SURFACE_ACTIVE";
49 case OUTPUT_SURFACE_LOST: 46 case OUTPUT_SURFACE_LOST:
50 return "OUTPUT_SURFACE_LOST"; 47 return "OUTPUT_SURFACE_LOST";
51 case OUTPUT_SURFACE_CREATING: 48 case OUTPUT_SURFACE_CREATING:
(...skipping 10 matching lines...) Expand all
62 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { 59 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
63 switch (state) { 60 switch (state) {
64 case COMMIT_STATE_IDLE: 61 case COMMIT_STATE_IDLE:
65 return "COMMIT_STATE_IDLE"; 62 return "COMMIT_STATE_IDLE";
66 case COMMIT_STATE_FRAME_IN_PROGRESS: 63 case COMMIT_STATE_FRAME_IN_PROGRESS:
67 return "COMMIT_STATE_FRAME_IN_PROGRESS"; 64 return "COMMIT_STATE_FRAME_IN_PROGRESS";
68 case COMMIT_STATE_READY_TO_COMMIT: 65 case COMMIT_STATE_READY_TO_COMMIT:
69 return "COMMIT_STATE_READY_TO_COMMIT"; 66 return "COMMIT_STATE_READY_TO_COMMIT";
70 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: 67 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
71 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW"; 68 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
72 case COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW:
73 return "COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW";
74 } 69 }
75 NOTREACHED(); 70 NOTREACHED();
76 return "???"; 71 return "???";
77 } 72 }
78 73
79 const char* SchedulerStateMachine::TextureStateToString(TextureState state) { 74 const char* SchedulerStateMachine::TextureStateToString(TextureState state) {
80 switch (state) { 75 switch (state) {
81 case LAYER_TEXTURE_STATE_UNLOCKED: 76 case LAYER_TEXTURE_STATE_UNLOCKED:
82 return "LAYER_TEXTURE_STATE_UNLOCKED"; 77 return "LAYER_TEXTURE_STATE_UNLOCKED";
83 case LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD: 78 case LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD:
84 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD"; 79 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD";
85 case LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD: 80 case LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD:
86 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD"; 81 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD";
87 } 82 }
88 NOTREACHED(); 83 NOTREACHED();
89 return "???"; 84 return "???";
90 } 85 }
91 86
87 const char* SchedulerStateMachine::SynchronousReadbackStateToString(
88 SynchronousReadbackState state) {
89 switch (state) {
90 case READBACK_STATE_IDLE:
91 return "READBACK_STATE_IDLE";
92 case READBACK_STATE_NEEDS_BEGIN_FRAME:
93 return "READBACK_STATE_NEEDS_BEGIN_FRAME";
94 case READBACK_STATE_WAITING_FOR_COMMIT:
95 return "READBACK_STATE_WAITING_FOR_COMMIT";
96 case READBACK_STATE_WAITING_FOR_ACTIVATION:
97 return "READBACK_STATE_WAITING_FOR_ACTIVATION";
98 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK:
99 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK";
100 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT:
101 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT";
102 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION:
103 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION";
104 }
105 NOTREACHED();
106 return "???";
107 }
108
109 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
110 ForcedRedrawOnTimeoutState state) {
111 switch (state) {
112 case FORCED_REDRAW_STATE_IDLE:
113 return "FORCED_REDRAW_STATE_IDLE";
114 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
115 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
116 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
117 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
118 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
119 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
120 }
121 NOTREACHED();
122 return "???";
123 }
124
92 const char* SchedulerStateMachine::ActionToString(Action action) { 125 const char* SchedulerStateMachine::ActionToString(Action action) {
93 switch (action) { 126 switch (action) {
94 case ACTION_NONE: 127 case ACTION_NONE:
95 return "ACTION_NONE"; 128 return "ACTION_NONE";
96 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 129 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
97 return "ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD"; 130 return "ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD";
98 case ACTION_COMMIT: 131 case ACTION_COMMIT:
99 return "ACTION_COMMIT"; 132 return "ACTION_COMMIT";
100 case ACTION_UPDATE_VISIBLE_TILES: 133 case ACTION_UPDATE_VISIBLE_TILES:
101 return "ACTION_UPDATE_VISIBLE_TILES"; 134 return "ACTION_UPDATE_VISIBLE_TILES";
102 case ACTION_ACTIVATE_PENDING_TREE: 135 case ACTION_ACTIVATE_PENDING_TREE:
103 return "ACTION_ACTIVATE_PENDING_TREE"; 136 return "ACTION_ACTIVATE_PENDING_TREE";
104 case ACTION_DRAW_IF_POSSIBLE: 137 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
105 return "ACTION_DRAW_IF_POSSIBLE"; 138 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
106 case ACTION_DRAW_FORCED: 139 case ACTION_DRAW_AND_SWAP_FORCED:
107 return "ACTION_DRAW_FORCED"; 140 return "ACTION_DRAW_AND_SWAP_FORCED";
108 case ACTION_DRAW_AND_SWAP_ABORT: 141 case ACTION_DRAW_AND_SWAP_ABORT:
109 return "ACTION_DRAW_AND_SWAP_ABORT"; 142 return "ACTION_DRAW_AND_SWAP_ABORT";
143 case ACTION_DRAW_AND_READBACK:
144 return "ACTION_DRAW_AND_READBACK";
110 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 145 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
111 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; 146 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
112 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 147 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
113 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD"; 148 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD";
114 } 149 }
115 NOTREACHED(); 150 NOTREACHED();
116 return "???"; 151 return "???";
117 } 152 }
118 153
119 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { 154 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
120 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 155 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
121 156
122 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue); 157 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
123 major_state->SetString("next_action", ActionToString(NextAction())); 158 major_state->SetString("next_action", ActionToString(NextAction()));
124 major_state->SetString("commit_state", CommitStateToString(commit_state_)); 159 major_state->SetString("commit_state", CommitStateToString(commit_state_));
125 major_state->SetString("texture_state_", 160 major_state->SetString("texture_state_",
126 TextureStateToString(texture_state_)); 161 TextureStateToString(texture_state_));
127 major_state->SetString("output_surface_state_", 162 major_state->SetString("output_surface_state_",
128 OutputSurfaceStateToString(output_surface_state_)); 163 OutputSurfaceStateToString(output_surface_state_));
164 major_state->SetString(
165 "forced_redraw_state",
166 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
167 major_state->SetString("readback_state",
168 SynchronousReadbackStateToString(readback_state_));
129 state->Set("major_state", major_state.release()); 169 state->Set("major_state", major_state.release());
130 170
131 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); 171 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
132 base::TimeTicks now = base::TimeTicks::Now(); 172 base::TimeTicks now = base::TimeTicks::Now();
133 timestamps_state->SetDouble( 173 timestamps_state->SetDouble(
134 "0_interval", last_begin_frame_args_.interval.InMicroseconds() / 1000.0L); 174 "0_interval", last_begin_frame_args_.interval.InMicroseconds() / 1000.0L);
135 timestamps_state->SetDouble( 175 timestamps_state->SetDouble(
136 "1_now_to_deadline", 176 "1_now_to_deadline",
137 (last_begin_frame_args_.deadline - now).InMicroseconds() / 1000.0L); 177 (last_begin_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
138 timestamps_state->SetDouble( 178 timestamps_state->SetDouble(
139 "2_frame_time_to_now", 179 "2_frame_time_to_now",
140 (last_begin_frame_args_.deadline - now).InMicroseconds() / 1000.0L); 180 (now - last_begin_frame_args_.frame_time).InMicroseconds() / 1000.0L);
141 timestamps_state->SetDouble( 181 timestamps_state->SetDouble(
142 "3_frame_time_to_deadline", 182 "3_frame_time_to_deadline",
143 (last_begin_frame_args_.deadline - last_begin_frame_args_.frame_time) 183 (last_begin_frame_args_.deadline - last_begin_frame_args_.frame_time)
144 .InMicroseconds() / 184 .InMicroseconds() /
145 1000.0L); 185 1000.0L);
146 timestamps_state->SetDouble( 186 timestamps_state->SetDouble(
147 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); 187 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
148 timestamps_state->SetDouble( 188 timestamps_state->SetDouble(
149 "5_frame_time", 189 "5_frame_time",
150 (last_begin_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() / 190 (last_begin_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
151 1000.0L); 191 1000.0L);
152 timestamps_state->SetDouble( 192 timestamps_state->SetDouble(
153 "6_deadline", 193 "6_deadline",
154 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() / 194 (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
155 1000.0L); 195 1000.0L);
156 state->Set("major_timestamps_in_ms", timestamps_state.release()); 196 state->Set("major_timestamps_in_ms", timestamps_state.release());
157 197
158 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); 198 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
159 minor_state->SetInteger("commit_count", commit_count_); 199 minor_state->SetInteger("commit_count", commit_count_);
160 minor_state->SetInteger("current_frame_number", current_frame_number_); 200 minor_state->SetInteger("current_frame_number", current_frame_number_);
161 minor_state->SetInteger( 201 minor_state->SetInteger(
162 "last_frame_number_where_begin_frame_sent_to_main_thread", 202 "last_frame_number_where_begin_frame_sent_to_main_thread",
163 last_frame_number_where_begin_frame_sent_to_main_thread_); 203 last_frame_number_where_begin_frame_sent_to_main_thread_);
164 minor_state->SetInteger("last_frame_number_where_draw_was_called", 204 minor_state->SetInteger("last_frame_number_swap_performed_",
165 last_frame_number_where_draw_was_called_); 205 last_frame_number_swap_performed_);
166 minor_state->SetInteger( 206 minor_state->SetInteger(
167 "last_frame_number_where_update_visible_tiles_was_called", 207 "last_frame_number_where_update_visible_tiles_was_called",
168 last_frame_number_where_update_visible_tiles_was_called_); 208 last_frame_number_where_update_visible_tiles_was_called_);
169 minor_state->SetInteger("consecutive_failed_draws", 209 minor_state->SetInteger("consecutive_failed_draws",
170 consecutive_failed_draws_); 210 consecutive_failed_draws_);
171 minor_state->SetInteger(
172 "maximum_number_of_failed_draws_before_draw_is_forced",
173 maximum_number_of_failed_draws_before_draw_is_forced_);
174 minor_state->SetBoolean("needs_redraw", needs_redraw_); 211 minor_state->SetBoolean("needs_redraw", needs_redraw_);
175 minor_state->SetBoolean("swap_used_incomplete_tile", 212 minor_state->SetBoolean("swap_used_incomplete_tile",
176 swap_used_incomplete_tile_); 213 swap_used_incomplete_tile_);
177 minor_state->SetBoolean("needs_forced_redraw", needs_forced_redraw_);
178 minor_state->SetBoolean("needs_forced_redraw_after_next_commit",
179 needs_forced_redraw_after_next_commit_);
180 minor_state->SetBoolean("needs_commit", needs_commit_); 214 minor_state->SetBoolean("needs_commit", needs_commit_);
181 minor_state->SetBoolean("needs_forced_commit", needs_forced_commit_);
182 minor_state->SetBoolean("expect_immediate_begin_frame_for_main_thread",
183 expect_immediate_begin_frame_for_main_thread_);
184 minor_state->SetBoolean("main_thread_needs_layer_textures", 215 minor_state->SetBoolean("main_thread_needs_layer_textures",
185 main_thread_needs_layer_textures_); 216 main_thread_needs_layer_textures_);
186 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_); 217 minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_);
187 minor_state->SetBoolean("visible", visible_); 218 minor_state->SetBoolean("visible", visible_);
188 minor_state->SetBoolean("can_start", can_start_); 219 minor_state->SetBoolean("can_start", can_start_);
189 minor_state->SetBoolean("can_draw", can_draw_); 220 minor_state->SetBoolean("can_draw", can_draw_);
190 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); 221 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
191 minor_state->SetBoolean("pending_tree_is_ready_for_activation_", 222 minor_state->SetBoolean("pending_tree_is_ready_for_activation_",
192 pending_tree_is_ready_for_activation_); 223 pending_tree_is_ready_for_activation_);
193 minor_state->SetBoolean("active_tree_has_been_drawn_", 224 minor_state->SetBoolean("active_tree_needs_first_draw_",
194 active_tree_has_been_drawn_); 225 active_tree_needs_first_draw_);
195 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); 226 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
196 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", 227 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
197 did_create_and_initialize_first_output_surface_); 228 did_create_and_initialize_first_output_surface_);
198 state->Set("minor_state", minor_state.release()); 229 state->Set("minor_state", minor_state.release());
199 230
200 return state.PassAs<base::Value>(); 231 return state.PassAs<base::Value>();
201 } 232 }
202 233
203 bool SchedulerStateMachine::HasDrawnThisFrame() const { 234 bool SchedulerStateMachine::HasDrawnAndSwappedThisFrame() const {
204 return current_frame_number_ == last_frame_number_where_draw_was_called_; 235 return current_frame_number_ == last_frame_number_swap_performed_;
205 } 236 }
206 237
207 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 238 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
208 return current_frame_number_ == 239 return current_frame_number_ ==
209 last_frame_number_where_update_visible_tiles_was_called_; 240 last_frame_number_where_update_visible_tiles_was_called_;
210 } 241 }
211 242
212 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const { 243 bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
213 return current_frame_number_ == 244 return current_frame_number_ ==
214 last_frame_number_where_begin_frame_sent_to_main_thread_; 245 last_frame_number_where_begin_frame_sent_to_main_thread_;
215 } 246 }
216 247
217 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 248 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
218 // These are all the cases where we normally cannot or do not want to draw 249 // These are all the cases where we normally cannot or do not want to draw
219 // but, if needs_redraw_ is true and we do not draw to make forward progress, 250 // but, if needs_redraw_ is true and we do not draw to make forward progress,
220 // we might deadlock with the main thread. 251 // we might deadlock with the main thread.
221 // This should be a superset of PendingActivationsShouldBeForced() since 252 // This should be a superset of PendingActivationsShouldBeForced() since
222 // activation of the pending tree is blocked by drawing of the active tree and 253 // activation of the pending tree is blocked by drawing of the active tree and
223 // the main thread might be blocked on activation of the most recent commit. 254 // the main thread might be blocked on activation of the most recent commit.
224 if (PendingActivationsShouldBeForced()) 255 if (PendingActivationsShouldBeForced())
225 return true; 256 return true;
226 257
227 // Additional states where we should abort draws. 258 // Additional states where we should abort draws.
228 // Note: We don't force activation in these cases because doing so would 259 // Note: We don't force activation in these cases because doing so would
229 // result in checkerboarding on resize, becoming visible, etc. 260 // result in checkerboarding on resize, becoming visible, etc.
230 if (!can_draw_) 261 if (!can_draw_)
231 return true; 262 return true;
232 if (!visible_) 263 if (!visible_)
233 return true; 264 return true;
234 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
235 return true;
236 return false; 265 return false;
237 } 266 }
238 267
239 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const { 268 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
240 // These are all the cases where, if we do not force activations to make 269 // These are all the cases where, if we do not force activations to make
241 // forward progress, we might deadlock with the main thread. 270 // forward progress, we might deadlock with the main thread.
271
272 // The impl thread cannot lock layer textures unless the pending
273 // tree can be activated to unblock the commit.
242 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) 274 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
243 return true; 275 return true;
244 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 276
245 output_surface_state_ == OUTPUT_SURFACE_CREATING || 277 // There is no output surface to trigger our activations.
246 output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) 278 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
247 return true; 279 return true;
280
248 return false; 281 return false;
249 } 282 }
250 283
251 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const { 284 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
252 // Don't try to initialize too early. 285 // Don't try to initialize too early.
253 if (!can_start_) 286 if (!can_start_)
254 return false; 287 return false;
255 288
256 // We only want to start output surface initialization after the 289 // We only want to start output surface initialization after the
257 // previous commit is complete. 290 // previous commit is complete.
258 if (commit_state_ != COMMIT_STATE_IDLE) 291 if (commit_state_ != COMMIT_STATE_IDLE)
259 return false; 292 return false;
260 293
294 // We want to clear the pipline of any pending draws and activations
295 // before starting output surface initialization. This allows us to avoid
296 // weird corner cases where we abort draws or force activation while we
297 // are initializing the output surface and can potentially have a pending
298 // readback.
299 if (active_tree_needs_first_draw_ || has_pending_tree_)
300 return false;
301
261 // We need to create the output surface if we don't have one and we haven't 302 // We need to create the output surface if we don't have one and we haven't
262 // started creating one yet. 303 // started creating one yet.
263 return output_surface_state_ == OUTPUT_SURFACE_LOST; 304 return output_surface_state_ == OUTPUT_SURFACE_LOST;
264 } 305 }
265 306
266 bool SchedulerStateMachine::ShouldDraw() const { 307 bool SchedulerStateMachine::ShouldDraw() const {
267 // We should not draw or abort draws while we are waiting for the 308 // After a readback, make sure not to draw again until we've replaced the
268 // first activation. Doing so will cause us to transition to 309 // readback commit with a real one.
269 // COMMIT_STATE_IDLE and start the 2nd commit before the 1st commit 310 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
270 // has been drawn. It will also cause us to fail readbacks when we could 311 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
271 // have succeeded by waiting a little longer.
272 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
273 return false; 312 return false;
274 313
275 // When we are waiting for a forced draw, only force draw once 314 // Draw immediately for readbacks to unblock the main thread quickly.
276 // needs_forced_redraw_ is true. 315 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
277 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) 316 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
278 return needs_forced_redraw_;
279
280 // Always handle forced draws ASAP.
281 if (needs_forced_redraw_)
282 return true; 317 return true;
318 }
283 319
284 // If we need to abort draws, we should do so ASAP since the draw could 320 // If we need to abort draws, we should do so ASAP since the draw could
285 // be blocking other important actions (like output surface initialization), 321 // be blocking other important actions (like output surface initialization),
286 // from occuring. If we are waiting for the first draw, then perfom the 322 // from occuring. If we are waiting for the first draw, then perfom the
287 // aborted draw to keep things moving. If we are not waiting for the first 323 // aborted draw to keep things moving. If we are not waiting for the first
288 // draw however, we don't want to abort for no reason. 324 // draw however, we don't want to abort for no reason.
289 if (PendingDrawsShouldBeAborted()) 325 if (PendingDrawsShouldBeAborted())
290 return commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 326 return active_tree_needs_first_draw_;
291 327
292 // After this line, we only want to draw once per frame. 328 // After this line, we only want to draw once per frame.
293 if (HasDrawnThisFrame()) 329 if (HasDrawnAndSwappedThisFrame())
294 return false; 330 return false;
295 331
296 // We currently only draw within the BeginFrame. 332 // We currently only draw within the BeginFrame.
297 if (!inside_begin_frame_) 333 if (!inside_begin_frame_)
298 return false; 334 return false;
299 335
336 // Only handle forced redraws due to timeouts on the regular deadline.
337 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
338 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
339 return true;
340 }
341
300 return needs_redraw_; 342 return needs_redraw_;
301 } 343 }
302 344
303 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const { 345 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
304 if (!main_thread_needs_layer_textures_) 346 if (!main_thread_needs_layer_textures_)
305 return false; 347 return false;
306 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED) 348 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
307 return true; 349 return true;
308 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); 350 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
309 return false; 351 return false;
310 } 352 }
311 353
312 bool SchedulerStateMachine::ShouldActivatePendingTree() const { 354 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
313 // There is nothing to activate. 355 // There is nothing to activate.
314 if (!has_pending_tree_) 356 if (!has_pending_tree_)
315 return false; 357 return false;
316 358
317 // We don't want to activate a second tree before drawing the first one. 359 // We should not activate a second tree before drawing the first one.
318 // Note: It is possible that there is no active tree to draw when 360 // Even if we need to force activation of the pending tree, we should abort
319 // output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION, 361 // drawing the active tree first.
320 // so we don't block activation on draw in that case. 362 if (active_tree_needs_first_draw_)
321 if (!active_tree_has_been_drawn_ &&
322 output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
323 return false; 363 return false;
324 364
325 // If we want to force activation, do so ASAP. 365 // If we want to force activation, do so ASAP.
326 if (PendingActivationsShouldBeForced()) 366 if (PendingActivationsShouldBeForced())
327 return true; 367 return true;
328 368
329 // At this point, only activate if we are ready to activate. 369 // At this point, only activate if we are ready to activate.
330 return pending_tree_is_ready_for_activation_; 370 return pending_tree_is_ready_for_activation_;
331 } 371 }
332 372
(...skipping 26 matching lines...) Expand all
359 return false; 399 return false;
360 400
361 // Only send BeginFrame to the main thread when idle. 401 // Only send BeginFrame to the main thread when idle.
362 if (commit_state_ != COMMIT_STATE_IDLE) 402 if (commit_state_ != COMMIT_STATE_IDLE)
363 return false; 403 return false;
364 404
365 // We can't accept a commit if we have a pending tree. 405 // We can't accept a commit if we have a pending tree.
366 if (has_pending_tree_) 406 if (has_pending_tree_)
367 return false; 407 return false;
368 408
369 // We want to start forced commits ASAP. 409 // We want to handle readback commits immediately to unblock the main thread.
370 if (needs_forced_commit_) 410 // Note: This BeginFrame will correspond to the replacement commit that comes
371 return true; 411 // after the readback commit itself, so we only send the BeginFrame if a
412 // commit isn't already pending behind the readback.
413 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
414 return !CommitPending();
372 415
373 // We do not need commits if we are not visible, unless there's a 416 // We do not need commits if we are not visible, unless there's a
374 // request for a forced commit. 417 // request for a forced commit.
375 if (!visible_) 418 if (!visible_)
376 return false; 419 return false;
377 420
378 // We want to start the first commit after we get a new output surface ASAP. 421 // We want to start the first commit after we get a new output surface ASAP.
379 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) 422 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
380 return true; 423 return true;
381 424
425 // We need a new commit for the forced redraw. This honors the
426 // single commit per interval because the result will be swapped to screen.
427 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
428 return true;
429
382 // After this point, we only start a commit once per frame. 430 // After this point, we only start a commit once per frame.
383 if (HasSentBeginFrameToMainThreadThisFrame()) 431 if (HasSentBeginFrameToMainThreadThisFrame())
384 return false; 432 return false;
385 433
386 // We shouldn't normally accept commits if there isn't an OutputSurface. 434 // We shouldn't normally accept commits if there isn't an OutputSurface.
387 if (!HasInitializedOutputSurface()) 435 if (!HasInitializedOutputSurface())
388 return false; 436 return false;
389 437
390 return true; 438 return true;
391 } 439 }
392 440
393 bool SchedulerStateMachine::ShouldCommit() const { 441 bool SchedulerStateMachine::ShouldCommit() const {
394 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; 442 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
395 } 443 }
396 444
397 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 445 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
398 if (ShouldAcquireLayerTexturesForMainThread()) 446 if (ShouldAcquireLayerTexturesForMainThread())
399 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 447 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
400 if (ShouldUpdateVisibleTiles()) 448 if (ShouldUpdateVisibleTiles())
401 return ACTION_UPDATE_VISIBLE_TILES; 449 return ACTION_UPDATE_VISIBLE_TILES;
402 if (ShouldActivatePendingTree()) 450 if (ShouldActivatePendingTree())
403 return ACTION_ACTIVATE_PENDING_TREE; 451 return ACTION_ACTIVATE_PENDING_TREE;
404 if (ShouldCommit()) 452 if (ShouldCommit())
405 return ACTION_COMMIT; 453 return ACTION_COMMIT;
406 if (ShouldDraw()) { 454 if (ShouldDraw()) {
407 if (needs_forced_redraw_) 455 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
408 return ACTION_DRAW_FORCED; 456 return ACTION_DRAW_AND_READBACK;
409 else if (PendingDrawsShouldBeAborted()) 457 else if (PendingDrawsShouldBeAborted())
410 return ACTION_DRAW_AND_SWAP_ABORT; 458 return ACTION_DRAW_AND_SWAP_ABORT;
459 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
460 return ACTION_DRAW_AND_SWAP_FORCED;
411 else 461 else
412 return ACTION_DRAW_IF_POSSIBLE; 462 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
413 } 463 }
414 if (ShouldSendBeginFrameToMainThread()) 464 if (ShouldSendBeginFrameToMainThread())
415 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD; 465 return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
416 if (ShouldBeginOutputSurfaceCreation()) 466 if (ShouldBeginOutputSurfaceCreation())
417 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 467 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
418 return ACTION_NONE; 468 return ACTION_NONE;
419 } 469 }
420 470
471 void SchedulerStateMachine::CheckInvariants() {
472 // We should never try to perform a draw for readback and forced draw due to
473 // timeout simultaneously.
474 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
475 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
476 }
477
421 void SchedulerStateMachine::UpdateState(Action action) { 478 void SchedulerStateMachine::UpdateState(Action action) {
422 switch (action) { 479 switch (action) {
423 case ACTION_NONE: 480 case ACTION_NONE:
424 return; 481 return;
425 482
426 case ACTION_UPDATE_VISIBLE_TILES: 483 case ACTION_UPDATE_VISIBLE_TILES:
427 last_frame_number_where_update_visible_tiles_was_called_ = 484 last_frame_number_where_update_visible_tiles_was_called_ =
428 current_frame_number_; 485 current_frame_number_;
429 return; 486 return;
430 487
431 case ACTION_ACTIVATE_PENDING_TREE: 488 case ACTION_ACTIVATE_PENDING_TREE:
432 UpdateStateOnActivation(); 489 UpdateStateOnActivation();
433 return; 490 return;
434 491
435 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: 492 case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
436 DCHECK(!has_pending_tree_); 493 DCHECK(!has_pending_tree_);
437 if (!needs_forced_commit_ && 494 DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME);
438 output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
439 DCHECK(visible_);
440 DCHECK_GT(current_frame_number_,
441 last_frame_number_where_begin_frame_sent_to_main_thread_);
442 }
443 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 495 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
444 needs_commit_ = false; 496 needs_commit_ = false;
445 needs_forced_commit_ = false; 497 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
498 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
446 last_frame_number_where_begin_frame_sent_to_main_thread_ = 499 last_frame_number_where_begin_frame_sent_to_main_thread_ =
447 current_frame_number_; 500 current_frame_number_;
448 return; 501 return;
449 502
450 case ACTION_COMMIT: { 503 case ACTION_COMMIT: {
451 bool commit_was_aborted = false; 504 bool commit_was_aborted = false;
452 UpdateStateOnCommit(commit_was_aborted); 505 UpdateStateOnCommit(commit_was_aborted);
453 return; 506 return;
454 } 507 }
455 508
456 case ACTION_DRAW_FORCED: 509 case ACTION_DRAW_AND_SWAP_FORCED:
457 case ACTION_DRAW_IF_POSSIBLE: { 510 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
458 bool did_swap = true; 511 bool did_swap = true;
459 UpdateStateOnDraw(did_swap); 512 UpdateStateOnDraw(did_swap);
460 return; 513 return;
461 } 514 }
462 515
463 case ACTION_DRAW_AND_SWAP_ABORT: { 516 case ACTION_DRAW_AND_SWAP_ABORT:
517 case ACTION_DRAW_AND_READBACK: {
464 bool did_swap = false; 518 bool did_swap = false;
465 UpdateStateOnDraw(did_swap); 519 UpdateStateOnDraw(did_swap);
466 return; 520 return;
467 } 521 }
468 522
469 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 523 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
470 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
471 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 524 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
472 output_surface_state_ = OUTPUT_SURFACE_CREATING; 525 output_surface_state_ = OUTPUT_SURFACE_CREATING;
526
527 // The following DCHECKs make sure we are in the proper quiecent state.
enne (OOO) 2013/09/06 22:24:30 typo: quiescent
brianderson 2013/09/06 22:45:00 Done.
528 // The pipeline should be flushed entirely before we start output
529 // surface creation to avoid complicated corner cases.
530 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
531 DCHECK(!has_pending_tree_);
532 DCHECK(!active_tree_needs_first_draw_);
473 return; 533 return;
474 534
475 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 535 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
476 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; 536 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
477 main_thread_needs_layer_textures_ = false; 537 main_thread_needs_layer_textures_ = false;
478 return; 538 return;
479 } 539 }
480 } 540 }
481 541
482 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) { 542 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
483 commit_count_++; 543 commit_count_++;
484 544
485 // If we are impl-side-painting but the commit was aborted, then we behave 545 // If we are impl-side-painting but the commit was aborted, then we behave
486 // mostly as if we are not impl-side-painting since there is no pending tree. 546 // mostly as if we are not impl-side-painting since there is no pending tree.
487 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted; 547 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
488 548
489 // Update the commit state. 549 // Update state related to readbacks.
490 if (expect_immediate_begin_frame_for_main_thread_) 550 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
491 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW; 551 // Update the state if this is the readback commit.
492 else if (!commit_was_aborted) 552 readback_state_ = has_pending_tree_
553 ? READBACK_STATE_WAITING_FOR_ACTIVATION
554 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
555 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
556 // Update the state if this is the commit replacing the readback commit.
557 readback_state_ = has_pending_tree_
558 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
559 : READBACK_STATE_IDLE;
560 } else {
561 DCHECK(readback_state_ == READBACK_STATE_IDLE);
562 }
563
564 // Readbacks can interrupt output surface initialization and forced draws,
565 // so we do not want to advance those states if we are in the middle of a
566 // readback. Note: It is possible for the readback's replacement commit to
567 // be the output surface's first commit and/or the forced redraw's commit.
568 if (readback_state_ == READBACK_STATE_IDLE ||
569 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
570 // Update state related to forced draws.
571 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
572 forced_redraw_state_ = has_pending_tree_
573 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
574 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
575 }
576
577 // Update the output surface state.
578 DCHECK_NE(output_surface_state_,
579 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
580 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
581 if (has_pending_tree_) {
582 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
583 } else {
584 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
585 needs_redraw_ = true;
586 }
587 }
588 }
589
590 // Update the commit state. We expect and wait for a draw if the commit
591 // was not aborted or if we are in a readback or forced draw.
592 if (!commit_was_aborted)
593 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
594 else if (readback_state_ != READBACK_STATE_IDLE ||
595 forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
493 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 596 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
494 else 597 else
495 commit_state_ = COMMIT_STATE_IDLE; 598 commit_state_ = COMMIT_STATE_IDLE;
496 599
497 // Update the output surface state.
498 DCHECK_NE(output_surface_state_, OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
499 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
500 if (has_pending_tree_) {
501 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
502 } else {
503 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
504 needs_redraw_ = true;
505 }
506 }
507
508 // Update state if we have a new active tree to draw, or if the active tree 600 // Update state if we have a new active tree to draw, or if the active tree
509 // was unchanged but we need to do a readback. 601 // was unchanged but we need to do a readback or forced draw.
510 if (!has_pending_tree_ && 602 if (!has_pending_tree_ &&
511 (!commit_was_aborted || expect_immediate_begin_frame_for_main_thread_)) { 603 (!commit_was_aborted ||
604 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
605 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
512 needs_redraw_ = true; 606 needs_redraw_ = true;
513 active_tree_has_been_drawn_ = false; 607 active_tree_needs_first_draw_ = true;
514 } 608 }
515 609
516 // This post-commit work is common to both completed and aborted commits. 610 // This post-commit work is common to both completed and aborted commits.
517 pending_tree_is_ready_for_activation_ = false; 611 pending_tree_is_ready_for_activation_ = false;
518 612
519 if (draw_if_possible_failed_) 613 if (draw_if_possible_failed_)
520 last_frame_number_where_draw_was_called_ = -1; 614 last_frame_number_swap_performed_ = -1;
521
522 if (needs_forced_redraw_after_next_commit_) {
523 needs_forced_redraw_after_next_commit_ = false;
524 needs_forced_redraw_ = true;
525 }
526 615
527 // If we are planing to draw with the new commit, lock the layer textures for 616 // If we are planing to draw with the new commit, lock the layer textures for
528 // use on the impl thread. Otherwise, leave them unlocked. 617 // use on the impl thread. Otherwise, leave them unlocked.
529 if (has_pending_tree_ || needs_redraw_ || needs_forced_redraw_) 618 if (has_pending_tree_ || needs_redraw_)
530 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; 619 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
531 else 620 else
532 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 621 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
533 } 622 }
534 623
535 void SchedulerStateMachine::UpdateStateOnActivation() { 624 void SchedulerStateMachine::UpdateStateOnActivation() {
625 // Update output surface state.
536 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION) 626 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
537 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 627 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
538 628
629 // Update readback state
630 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
631 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
632
633 // Update forced redraw state
634 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION)
635 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
636 else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
637 readback_state_ = READBACK_STATE_IDLE;
638
539 has_pending_tree_ = false; 639 has_pending_tree_ = false;
540 pending_tree_is_ready_for_activation_ = false; 640 pending_tree_is_ready_for_activation_ = false;
541 active_tree_has_been_drawn_ = false; 641 active_tree_needs_first_draw_ = true;
542 needs_redraw_ = true; 642 needs_redraw_ = true;
543 } 643 }
544 644
545 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) { 645 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
546 if (inside_begin_frame_) 646 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
547 last_frame_number_where_draw_was_called_ = current_frame_number_; 647 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
548 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) { 648 << *AsValue();
549 DCHECK(expect_immediate_begin_frame_for_main_thread_); 649
650 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
651 // The draw correspons to a readback commit.
652 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
653 // We are blocking commits from the main thread until after this draw, so
654 // we should not have a pending tree.
655 DCHECK(!has_pending_tree_);
656 // We transition to COMMIT_STATE_FRAME_IN_PROGRESS because there is a
657 // pending BeginFrame on the main thread behind the readback request.
550 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 658 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
551 expect_immediate_begin_frame_for_main_thread_ = false; 659 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
552 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) { 660 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
661 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
662 commit_state_ = COMMIT_STATE_IDLE;
663 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
664 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW &&
665 !has_pending_tree_) {
553 commit_state_ = COMMIT_STATE_IDLE; 666 commit_state_ = COMMIT_STATE_IDLE;
554 } 667 }
668
555 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) 669 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
556 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 670 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
557 671
558 needs_redraw_ = false; 672 needs_redraw_ = false;
559 needs_forced_redraw_ = false;
560 draw_if_possible_failed_ = false; 673 draw_if_possible_failed_ = false;
561 active_tree_has_been_drawn_ = true; 674 active_tree_needs_first_draw_ = false;
562 675
563 if (did_swap) 676 if (did_swap) {
564 swap_used_incomplete_tile_ = false; 677 swap_used_incomplete_tile_ = false;
678 last_frame_number_swap_performed_ = current_frame_number_;
679 }
565 } 680 }
566 681
567 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 682 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
568 DCHECK(!main_thread_needs_layer_textures_); 683 DCHECK(!main_thread_needs_layer_textures_);
569 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 684 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
570 main_thread_needs_layer_textures_ = true; 685 main_thread_needs_layer_textures_ = true;
571 } 686 }
572 687
688 // These are the cases where we definitely (or almost definitely) have a
689 // new frame to draw and can draw.
573 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { 690 bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
691 // The output surface is the provider of BeginFrames for the impl thread,
692 // so we are not going to get them even if we ask for them.
693 if (!HasInitializedOutputSurface())
694 return false;
695
574 // If we can't draw, don't tick until we are notified that we can draw again. 696 // If we can't draw, don't tick until we are notified that we can draw again.
575 if (!can_draw_) 697 if (!can_draw_)
576 return false; 698 return false;
577 699
578 if (needs_forced_redraw_) 700 // The forced draw respects our normal draw scheduling, so we need to
701 // request a BeginFrame on the impl thread for it.
702 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
579 return true; 703 return true;
580 704
581 if (visible_ && swap_used_incomplete_tile_) 705 // There's no need to produce frames if we are not visible.
706 if (!visible_)
707 return false;
708
709 // We need to draw a more complete frame than we did the last BeginFrame,
710 // so request another BeginFrame in anticipation that we will have
711 // additional visible tiles.
712 if (swap_used_incomplete_tile_)
582 return true; 713 return true;
583 714
584 return needs_redraw_ && visible_ && HasInitializedOutputSurface(); 715 return needs_redraw_;
585 } 716 }
586 717
718 // These are cases where we are very likely to draw soon, but might not
719 // actually have a new frame to draw when we receive the next BeginFrame.
720 // Proactively requesting the BeginFrame helps hide the round trip latency of
721 // the SetNeedsBeginFrame request that has to go to the Browser.
722 // However, this is bad for the synchronous compositor because we have to
723 // draw when we get the BeginFrame and could end up drawing many duplicate
724 // frames.
587 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { 725 bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
588 // The output surface is the provider of BeginFrames for the impl thread, 726 // The output surface is the provider of BeginFrames for the impl thread,
589 // so we are not going to get them even if we ask for them. 727 // so we are not going to get them even if we ask for them.
590 if (!HasInitializedOutputSurface()) 728 if (!HasInitializedOutputSurface())
591 return false; 729 return false;
592 730
593 // Do not be proactive when invisible. 731 // Do not be proactive when invisible.
594 if (!visible_) 732 if (!visible_)
595 return false; 733 return false;
596 734
597 // We should proactively request a BeginFrame if a commit or a tree activation 735 // We should proactively request a BeginFrame if a commit is pending
598 // is pending. 736 // because we will want to draw if the commit completes quickly.
599 return (needs_commit_ || needs_forced_commit_ || 737 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
600 commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_); 738 return true;
739
740 // If the pending tree activates quickly, we'll want a BeginFrame soon
741 // to draw the new active tree.
742 if (has_pending_tree_)
743 return true;
744
745 return false;
601 } 746 }
602 747
603 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) { 748 void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) {
604 current_frame_number_++; 749 current_frame_number_++;
605 inside_begin_frame_ = true; 750 inside_begin_frame_ = true;
606 last_begin_frame_args_ = args; 751 last_begin_frame_args_ = args;
607 } 752 }
608 753
609 void SchedulerStateMachine::DidLeaveBeginFrame() { 754 void SchedulerStateMachine::DidLeaveBeginFrame() {
610 inside_begin_frame_ = false; 755 inside_begin_frame_ = false;
611 } 756 }
612 757
613 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 758 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
614 759
615 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 760 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
616 761
617 void SchedulerStateMachine::DidSwapUseIncompleteTile() { 762 void SchedulerStateMachine::DidSwapUseIncompleteTile() {
618 swap_used_incomplete_tile_ = true; 763 swap_used_incomplete_tile_ = true;
619 } 764 }
620 765
621 void SchedulerStateMachine::SetNeedsForcedRedraw() {
622 needs_forced_redraw_ = true;
623 }
624
625 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { 766 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
626 draw_if_possible_failed_ = !success; 767 draw_if_possible_failed_ = !success;
627 if (draw_if_possible_failed_) { 768 if (draw_if_possible_failed_) {
628 needs_redraw_ = true; 769 needs_redraw_ = true;
629 needs_commit_ = true; 770 needs_commit_ = true;
630 consecutive_failed_draws_++; 771 consecutive_failed_draws_++;
631 if (settings_.timeout_and_draw_when_animation_checkerboards && 772 if (settings_.timeout_and_draw_when_animation_checkerboards &&
632 consecutive_failed_draws_ >= 773 consecutive_failed_draws_ >=
633 maximum_number_of_failed_draws_before_draw_is_forced_) { 774 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
634 consecutive_failed_draws_ = 0; 775 consecutive_failed_draws_ = 0;
635 // We need to force a draw, but it doesn't make sense to do this until 776 // We need to force a draw, but it doesn't make sense to do this until
enne (OOO) 2013/09/06 22:24:30 This patch doesn't change the status quo, but this
brianderson 2013/09/06 22:45:00 I've opened a separate bug to fix this here: https
636 // we've committed and have new textures. 777 // we've committed and have new textures.
637 needs_forced_redraw_after_next_commit_ = true; 778 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
638 } 779 }
639 } else { 780 } else {
640 consecutive_failed_draws_ = 0; 781 consecutive_failed_draws_ = 0;
641 } 782 }
642 } 783 }
643 784
644 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } 785 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
645 786
646 void SchedulerStateMachine::SetNeedsForcedCommit() { 787 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
647 needs_forced_commit_ = true; 788 // If this is called in READBACK_STATE_IDLE, this is a "first" readback
648 expect_immediate_begin_frame_for_main_thread_ = true; 789 // request.
790 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
791 // is a back-to-back readback request that started before the replacement
792 // commit had a chance to land.
793 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
794 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
795
796 // If there is already a commit in progress when we get the readback request
797 // (we are in COMMIT_STATE_FRAME_IN_PROGRESS), then we don't need to send a
798 // BeginFrame for the replacement commit, since there's already a BeginFrame
799 // behind the readback request. In that case, we can skip
800 // READBACK_STATE_NEEDS_BEGIN_FRAME and go directly to
801 // READBACK_STATE_WAITING_FOR_COMMIT
802 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
803 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
804 else
805 readback_state_ = READBACK_STATE_NEEDS_BEGIN_FRAME;
649 } 806 }
650 807
651 void SchedulerStateMachine::FinishCommit() { 808 void SchedulerStateMachine::FinishCommit() {
652 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || 809 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) << *AsValue();
653 (expect_immediate_begin_frame_for_main_thread_ &&
654 commit_state_ != COMMIT_STATE_IDLE))
655 << *AsValue();
656 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; 810 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
657 } 811 }
658 812
659 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) { 813 void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
660 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS); 814 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
661 if (did_handle) { 815 if (did_handle) {
662 bool commit_was_aborted = true; 816 bool commit_was_aborted = true;
663 UpdateStateOnCommit(commit_was_aborted); 817 UpdateStateOnCommit(commit_was_aborted);
664 } else if (expect_immediate_begin_frame_for_main_thread_) { 818 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
665 expect_immediate_begin_frame_for_main_thread_ = false; 819 readback_state_ = READBACK_STATE_IDLE;
enne (OOO) 2013/09/06 22:24:30 I still wonder if this should just be a DCHECK. I
brianderson 2013/09/06 22:45:00 Sorry I forgot about the comment you made previous
666 } else { 820 } else {
667 commit_state_ = COMMIT_STATE_IDLE; 821 commit_state_ = COMMIT_STATE_IDLE;
668 SetNeedsCommit(); 822 SetNeedsCommit();
669 } 823 }
670 } 824 }
671 825
672 void SchedulerStateMachine::DidLoseOutputSurface() { 826 void SchedulerStateMachine::DidLoseOutputSurface() {
673 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 827 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
674 output_surface_state_ == OUTPUT_SURFACE_CREATING) 828 output_surface_state_ == OUTPUT_SURFACE_CREATING)
675 return; 829 return;
(...skipping 28 matching lines...) Expand all
704 858
705 case OUTPUT_SURFACE_ACTIVE: 859 case OUTPUT_SURFACE_ACTIVE:
706 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 860 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
707 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 861 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
708 return true; 862 return true;
709 } 863 }
710 NOTREACHED(); 864 NOTREACHED();
711 return false; 865 return false;
712 } 866 }
713 867
714 void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(
715 int num_draws) {
716 maximum_number_of_failed_draws_before_draw_is_forced_ = num_draws;
717 }
718
719 } // namespace cc 868 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler_state_machine.h ('k') | cc/scheduler/scheduler_state_machine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698