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

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

Powered by Google App Engine
This is Rietveld 408576698