forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscheduler_state_machine.h
353 lines (286 loc) · 12.3 KB
/
scheduler_state_machine.h
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
// 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 <memory>
#include <string>
#include "base/macros.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"
#include "cc/tiles/tile_priority.h"
namespace base {
namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
}
namespace cc {
enum class ScrollHandlerState {
SCROLL_AFFECTS_SCROLL_HANDLER,
SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
};
const char* ScrollHandlerStateToString(ScrollHandlerState state);
// 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 CompositorFrameSinkState {
COMPOSITOR_FRAME_SINK_NONE,
COMPOSITOR_FRAME_SINK_ACTIVE,
COMPOSITOR_FRAME_SINK_CREATING,
COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT,
COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION,
};
static const char* CompositorFrameSinkStateToString(
CompositorFrameSinkState 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.
enum BeginImplFrameState {
BEGIN_IMPL_FRAME_STATE_IDLE,
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 BeginMainFrameState {
BEGIN_MAIN_FRAME_STATE_IDLE,
BEGIN_MAIN_FRAME_STATE_SENT,
BEGIN_MAIN_FRAME_STATE_STARTED,
BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT,
};
static const char* BeginMainFrameStateToString(BeginMainFrameState 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);
BeginMainFrameState begin_main_frame_state() const {
return begin_main_frame_state_;
}
bool CommitPending() const {
return begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_SENT ||
begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED ||
begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT;
}
bool NewActiveTreeLikely() const {
return needs_begin_main_frame_ || CommitPending() || has_pending_tree_;
}
bool RedrawPending() const { return needs_redraw_; }
bool PrepareTilesPending() const { return needs_prepare_tiles_; }
enum Action {
ACTION_NONE,
ACTION_SEND_BEGIN_MAIN_FRAME,
ACTION_COMMIT,
ACTION_ACTIVATE_SYNC_TREE,
ACTION_DRAW_IF_POSSIBLE,
ACTION_DRAW_FORCED,
ACTION_DRAW_ABORT,
ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION,
ACTION_PREPARE_TILES,
ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK,
};
static const char* ActionToString(Action action);
std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
void AsValueInto(base::trace_event::TracedValue* dict) const;
Action NextAction() const;
void WillSendBeginMainFrame();
void WillCommit(bool commit_had_no_updates);
void WillActivate();
void WillDraw();
void WillBeginCompositorFrameSinkCreation();
void WillPrepareTiles();
void WillInvalidateCompositorFrameSink();
void DidDraw(DrawResult draw_result);
void AbortDraw();
// 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();
// 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();
int current_frame_number() const { return current_frame_number_; }
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 main_thread_missed_last_deadline() const {
return main_thread_missed_last_deadline_;
}
bool IsDrawThrottled() const;
// Indicates whether the LayerTreeHostImpl is visible.
void SetVisible(bool visible);
bool visible() const { return visible_; }
void SetBeginFrameSourcePaused(bool paused);
bool begin_frame_source_paused() const { return begin_frame_source_paused_; }
// 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_; }
bool OnlyImplSideUpdatesExpected() const;
// Indicates that prepare-tiles is required. This guarantees another
// PrepareTiles will occur shortly (even if no redraw is required).
void SetNeedsPrepareTiles();
// If the scheduler attempted to draw, this provides feedback regarding
// whether or not a CompositorFrame was actually submitted. We might skip the
// submitting anything when there is not damage, for example.
void DidSubmitCompositorFrame();
// Notification from the CompositorFrameSink that a submitted frame has been
// consumed and it is ready for the next one.
void DidReceiveCompositorFrameAck();
int pending_submit_frames() const { return pending_submit_frames_; }
// Indicates whether to prioritize impl thread latency (i.e., animation
// smoothness) over new content activation.
void SetTreePrioritiesAndScrollState(TreePriority tree_priority,
ScrollHandlerState scroll_handler_state);
// Indicates if the main thread will likely respond within 1 vsync.
void SetCriticalBeginMainFrameToActivateIsFast(bool is_fast);
// A function of SetTreePrioritiesAndScrollState and
// SetCriticalBeginMainFrameToActivateIsFast.
bool ImplLatencyTakesPriority() const;
// Indicates that a new begin main frame 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 SetNeedsBeginMainFrame();
bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
// Requests a single impl frame (after the current frame if there is one
// active).
void SetNeedsOneBeginImplFrame();
// 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);
// Indicates production should be skipped to recover latency.
void SetSkipNextBeginMainFrameToReduceLatency();
// Resourceless software draws are allowed even when invisible.
void SetResourcelessSoftwareDraw(bool resourceless_draw);
// 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 DidLoseCompositorFrameSink();
void DidCreateAndInitializeCompositorFrameSink();
bool HasInitializedCompositorFrameSink() const;
// True if we need to abort draws to make forward progress.
bool PendingDrawsShouldBeAborted() const;
bool CouldSendBeginMainFrame() const;
void SetDeferCommits(bool defer_commits);
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
bool video_needs_begin_frames() const { return video_needs_begin_frames_; }
protected:
bool BeginFrameRequiredForAction() const;
bool BeginFrameNeededForVideo() const;
bool ProactiveBeginFrameWanted() const;
bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
// True if we need to force activations to make forward progress.
// TODO(sunnyps): Rename this to ShouldAbortCurrentFrame or similar.
bool PendingActivationsShouldBeForced() const;
bool ShouldBeginCompositorFrameSinkCreation() const;
bool ShouldDraw() const;
bool ShouldActivatePendingTree() const;
bool ShouldSendBeginMainFrame() const;
bool ShouldCommit() const;
bool ShouldPrepareTiles() const;
bool ShouldInvalidateCompositorFrameSink() const;
void WillDrawInternal();
void DidDrawInternal(DrawResult draw_result);
const SchedulerSettings settings_;
CompositorFrameSinkState compositor_frame_sink_state_;
BeginImplFrameState begin_impl_frame_state_;
BeginMainFrameState begin_main_frame_state_;
ForcedRedrawOnTimeoutState forced_redraw_state_;
// These are used for tracing only.
int commit_count_;
int current_frame_number_;
int last_frame_number_submit_performed_;
int last_frame_number_draw_performed_;
int last_frame_number_begin_main_frame_sent_;
int last_frame_number_invalidate_compositor_frame_sink_performed_;
// These are used to ensure that an action only happens once per frame,
// deadline, etc.
bool draw_funnel_;
bool send_begin_main_frame_funnel_;
bool invalidate_compositor_frame_sink_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 pending_submit_frames_;
int submit_frames_with_current_compositor_frame_sink_;
bool needs_redraw_;
bool needs_prepare_tiles_;
bool needs_begin_main_frame_;
bool needs_one_begin_impl_frame_;
bool visible_;
bool begin_frame_source_paused_;
bool resourceless_draw_;
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_compositor_frame_sink_;
TreePriority tree_priority_;
ScrollHandlerState scroll_handler_state_;
bool critical_begin_main_frame_to_activate_is_fast_;
bool main_thread_missed_last_deadline_;
bool skip_next_begin_main_frame_to_reduce_latency_;
bool defer_commits_;
bool video_needs_begin_frames_;
bool last_commit_had_no_updates_;
bool wait_for_ready_to_draw_;
bool did_draw_in_last_frame_;
bool did_submit_in_last_frame_;
private:
DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
};
} // namespace cc
#endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_