1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
|
// Copyright 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
#define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/output/begin_frame_args.h"
#include "cc/scheduler/commit_earlyout_reason.h"
#include "cc/scheduler/draw_result.h"
#include "cc/scheduler/scheduler_settings.h"
namespace base {
namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
class Value;
}
namespace cc {
// The SchedulerStateMachine decides how to coordinate main thread activites
// like painting/running javascript with rendering and input activities on the
// impl thread.
//
// The state machine tracks internal state but is also influenced by external
// state. Internal state includes things like whether a frame has been
// requested, while external state includes things like the current time being
// near to the vblank time.
//
// The scheduler seperates "what to do next" from the updating of its internal
// state to make testing cleaner.
class CC_EXPORT SchedulerStateMachine {
public:
// settings must be valid for the lifetime of this class.
explicit SchedulerStateMachine(const SchedulerSettings& settings);
enum OutputSurfaceState {
OUTPUT_SURFACE_ACTIVE,
OUTPUT_SURFACE_LOST,
OUTPUT_SURFACE_CREATING,
OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
};
static const char* OutputSurfaceStateToString(OutputSurfaceState state);
// Note: BeginImplFrameState does not cycle through these states in a fixed
// order on all platforms. It's up to the scheduler to set these correctly.
// TODO(sunnyps): Rename the states to IDLE, ANIMATE, WAITING_FOR_DEADLINE and
// DRAW.
enum BeginImplFrameState {
BEGIN_IMPL_FRAME_STATE_IDLE,
BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
};
static const char* BeginImplFrameStateToString(BeginImplFrameState state);
enum BeginImplFrameDeadlineMode {
BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE,
BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE,
BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR,
BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE,
BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW,
};
static const char* BeginImplFrameDeadlineModeToString(
BeginImplFrameDeadlineMode mode);
enum CommitState {
COMMIT_STATE_IDLE,
COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
COMMIT_STATE_READY_TO_COMMIT,
COMMIT_STATE_WAITING_FOR_ACTIVATION,
COMMIT_STATE_WAITING_FOR_DRAW,
};
static const char* CommitStateToString(CommitState state);
enum ForcedRedrawOnTimeoutState {
FORCED_REDRAW_STATE_IDLE,
FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,
FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
FORCED_REDRAW_STATE_WAITING_FOR_DRAW,
};
static const char* ForcedRedrawOnTimeoutStateToString(
ForcedRedrawOnTimeoutState state);
bool CommitPending() const {
return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
}
CommitState commit_state() const { return commit_state_; }
bool RedrawPending() const { return needs_redraw_; }
bool PrepareTilesPending() const { return needs_prepare_tiles_; }
enum Action {
ACTION_NONE,
ACTION_ANIMATE,
ACTION_SEND_BEGIN_MAIN_FRAME,
ACTION_COMMIT,
ACTION_ACTIVATE_SYNC_TREE,
ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
ACTION_DRAW_AND_SWAP_FORCED,
ACTION_DRAW_AND_SWAP_ABORT,
ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
ACTION_PREPARE_TILES,
ACTION_INVALIDATE_OUTPUT_SURFACE,
};
static const char* ActionToString(Action action);
scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
void AsValueInto(base::trace_event::TracedValue* dict) const;
Action NextAction() const;
void UpdateState(Action action);
// Indicates whether the impl thread needs a BeginImplFrame callback in order
// to make progress.
bool BeginFrameNeeded() const;
// Indicates that the system has entered and left a BeginImplFrame callback.
// The scheduler will not draw more than once in a given BeginImplFrame
// callback nor send more than one BeginMainFrame message.
void OnBeginImplFrame();
void OnBeginImplFrameDeadlinePending();
// Indicates that the scheduler has entered the draw phase. The scheduler
// will not draw more than once in a single draw phase.
// TODO(sunnyps): Rename OnBeginImplFrameDeadline to OnDraw or similar.
void OnBeginImplFrameDeadline();
void OnBeginImplFrameIdle();
BeginImplFrameState begin_impl_frame_state() const {
return begin_impl_frame_state_;
}
BeginImplFrameDeadlineMode CurrentBeginImplFrameDeadlineMode() const;
// If the main thread didn't manage to produce a new frame in time for the
// impl thread to draw, it is in a high latency mode.
bool MainThreadIsInHighLatencyMode() const;
bool SwapThrottled() const;
// Indicates whether the LayerTreeHostImpl is visible.
void SetVisible(bool visible);
bool visible() const { return visible_; }
// Indicates that a redraw is required, either due to the impl tree changing
// or the screen being damaged and simply needing redisplay.
void SetNeedsRedraw();
bool needs_redraw() const { return needs_redraw_; }
void SetNeedsAnimate();
bool needs_animate() const { return needs_animate_; }
bool OnlyImplSideUpdatesExpected() const;
// Indicates that prepare-tiles is required. This guarantees another
// PrepareTiles will occur shortly (even if no redraw is required).
void SetNeedsPrepareTiles();
// Make deadline wait for ReadyToDraw signal.
void SetWaitForReadyToDraw();
// Sets how many swaps can be pending to the OutputSurface.
void SetMaxSwapsPending(int max);
// If the scheduler attempted to draw and swap, this provides feedback
// regarding whether or not the swap actually occured. We might skip the
// swap when there is not damage, for example.
void DidSwapBuffers();
// Indicates whether a redraw is required because we are currently rendering
// with a low resolution or checkerboarded tile.
void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
// Notification from the OutputSurface that a swap has been consumed.
void DidSwapBuffersComplete();
int pending_swaps() const { return pending_swaps_; }
// Indicates whether to prioritize impl thread latency (i.e., animation
// smoothness) over new content activation.
void SetImplLatencyTakesPriority(bool impl_latency_takes_priority);
bool impl_latency_takes_priority() const {
return impl_latency_takes_priority_;
}
// Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
void DidDrawIfPossibleCompleted(DrawResult result);
// Indicates that a new commit flow needs to be performed, either to pull
// updates from the main thread to the impl, or to push deltas from the impl
// thread to main.
void SetNeedsCommit();
bool needs_commit() const { return needs_commit_; }
// Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
// from NextAction.
// Indicates that all painting is complete.
void NotifyReadyToCommit();
// Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
// from NextAction if the client rejects the BeginMainFrame message.
void BeginMainFrameAborted(CommitEarlyOutReason reason);
// Set that we can create the first OutputSurface and start the scheduler.
void SetCanStart() { can_start_ = true; }
// Allow access of the can_start_ state in tests.
bool CanStartForTesting() const { return can_start_; }
// Indicates production should be skipped to recover latency.
void SetSkipNextBeginMainFrameToReduceLatency();
// Indicates whether drawing would, at this time, make sense.
// CanDraw can be used to suppress flashes or checkerboarding
// when such behavior would be undesirable.
void SetCanDraw(bool can);
// Indicates that scheduled BeginMainFrame is started.
void NotifyBeginMainFrameStarted();
// Indicates that the pending tree is ready for activation.
void NotifyReadyToActivate();
// Indicates the active tree's visible tiles are ready to be drawn.
void NotifyReadyToDraw();
bool has_pending_tree() const { return has_pending_tree_; }
bool active_tree_needs_first_draw() const {
return active_tree_needs_first_draw_;
}
void DidPrepareTiles();
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
bool HasInitializedOutputSurface() const;
// True if we need to abort draws to make forward progress.
bool PendingDrawsShouldBeAborted() const;
void SetContinuousPainting(bool continuous_painting) {
continuous_painting_ = continuous_painting;
}
bool CouldSendBeginMainFrame() const;
void SetDeferCommits(bool defer_commits);
void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
bool children_need_begin_frames() const {
return children_need_begin_frames_;
}
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
bool video_needs_begin_frames() const { return video_needs_begin_frames_; }
protected:
bool BeginFrameRequiredForAction() const;
bool BeginFrameRequiredForChildren() const;
bool BeginFrameNeededForVideo() const;
bool ProactiveBeginFrameWanted() const;
bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
// True if we need to force activations to make forward progress.
bool PendingActivationsShouldBeForced() const;
// TODO(brianderson): Remove this once NPAPI support is removed.
bool SendingBeginMainFrameMightCauseDeadlock() const;
bool ShouldAnimate() const;
bool ShouldBeginOutputSurfaceCreation() const;
bool ShouldDraw() const;
bool ShouldActivatePendingTree() const;
bool ShouldSendBeginMainFrame() const;
bool ShouldCommit() const;
bool ShouldPrepareTiles() const;
bool ShouldInvalidateOutputSurface() const;
void UpdateStateOnAnimate();
void UpdateStateOnSendBeginMainFrame();
void UpdateStateOnCommit(bool commit_had_no_updates);
void UpdateStateOnActivation();
void UpdateStateOnDraw(bool did_request_swap);
void UpdateStateOnBeginOutputSurfaceCreation();
void UpdateStateOnPrepareTiles();
void UpdateStateOnInvalidateOutputSurface();
const SchedulerSettings settings_;
OutputSurfaceState output_surface_state_;
BeginImplFrameState begin_impl_frame_state_;
CommitState commit_state_;
ForcedRedrawOnTimeoutState forced_redraw_state_;
// These are used for tracing only.
int commit_count_;
int current_frame_number_;
int last_frame_number_animate_performed_;
int last_frame_number_swap_performed_;
int last_frame_number_swap_requested_;
int last_frame_number_begin_main_frame_sent_;
int last_frame_number_invalidate_output_surface_performed_;
// These are used to ensure that an action only happens once per frame,
// deadline, etc.
bool animate_funnel_;
bool request_swap_funnel_;
bool send_begin_main_frame_funnel_;
bool invalidate_output_surface_funnel_;
// prepare_tiles_funnel_ is "filled" each time PrepareTiles is called
// and "drained" on each BeginImplFrame. If the funnel gets too full,
// we start throttling ACTION_PREPARE_TILES such that we average one
// PrepareTiles per BeginImplFrame.
int prepare_tiles_funnel_;
int consecutive_checkerboard_animations_;
int max_pending_swaps_;
int pending_swaps_;
int swaps_with_current_output_surface_;
bool needs_redraw_;
bool needs_animate_;
bool needs_prepare_tiles_;
bool needs_commit_;
bool visible_;
bool can_start_;
bool can_draw_;
bool has_pending_tree_;
bool pending_tree_is_ready_for_activation_;
bool active_tree_needs_first_draw_;
bool did_create_and_initialize_first_output_surface_;
bool impl_latency_takes_priority_;
bool skip_next_begin_main_frame_to_reduce_latency_;
bool continuous_painting_;
bool children_need_begin_frames_;
bool defer_commits_;
bool video_needs_begin_frames_;
bool last_commit_had_no_updates_;
bool wait_for_active_tree_ready_to_draw_;
bool did_request_swap_in_last_frame_;
bool did_perform_swap_in_last_draw_;
private:
DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
};
} // namespace cc
#endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
|