summaryrefslogtreecommitdiffstats
path: root/cc/scheduler/scheduler_state_machine.h
blob: 55e54b546794f4fde88969e915169c0bd16b02d9 (plain)
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
// 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 "base/time/time.h"
#include "cc/base/cc_export.h"
#include "cc/output/begin_frame_args.h"
#include "cc/scheduler/scheduler_settings.h"

namespace base {
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: BeginFrameState will always cycle through all the states in order.
  // Whether or not it actually waits or draws, it will at least try to wait in
  // BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
  // BEGIN_FRAME_STATE_INSIDE_DEADLINE
  enum BeginFrameState {
    BEGIN_FRAME_STATE_IDLE,
    BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
    BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
    BEGIN_FRAME_STATE_INSIDE_DEADLINE,
  };
  static const char* BeginFrameStateToString(BeginFrameState state);

  enum CommitState {
    COMMIT_STATE_IDLE,
    COMMIT_STATE_FRAME_IN_PROGRESS,
    COMMIT_STATE_READY_TO_COMMIT,
    COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
  };
  static const char* CommitStateToString(CommitState state);

  enum TextureState {
    LAYER_TEXTURE_STATE_UNLOCKED,
    LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD,
    LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD,
  };
  static const char* TextureStateToString(TextureState state);

  enum SynchronousReadbackState {
    READBACK_STATE_IDLE,
    READBACK_STATE_NEEDS_BEGIN_FRAME,
    READBACK_STATE_WAITING_FOR_COMMIT,
    READBACK_STATE_WAITING_FOR_ACTIVATION,
    READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK,
    READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT,
    READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
  };
  static const char* SynchronousReadbackStateToString(
      SynchronousReadbackState 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_FRAME_IN_PROGRESS ||
           commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
  }

  bool RedrawPending() const { return needs_redraw_; }
  bool ManageTilesPending() const { return needs_manage_tiles_; }

  enum Action {
    ACTION_NONE,
    ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    ACTION_COMMIT,
    ACTION_UPDATE_VISIBLE_TILES,
    ACTION_ACTIVATE_PENDING_TREE,
    ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
    ACTION_DRAW_AND_SWAP_FORCED,
    ACTION_DRAW_AND_SWAP_ABORT,
    ACTION_DRAW_AND_READBACK,
    ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
    ACTION_MANAGE_TILES,
  };
  static const char* ActionToString(Action action);

  scoped_ptr<base::Value> AsValue() const;

  Action NextAction() const;
  void UpdateState(Action action);

  void CheckInvariants();

  // Indicates whether the main thread needs a begin frame callback in order to
  // make progress.
  bool BeginFrameNeededByImplThread() const;

  // Idicates that we need to independently poll for new state and actions
  // because we can't expect a BeginFrame. This is mostly used to avoid
  // drawing repeat frames with the synchronous compositor without dropping
  // necessary actions on the floor.
  bool ShouldPollForAnticipatedDrawTriggers() const;

  // Indicates that the system has entered and left a BeginFrame callback.
  // The scheduler will not draw more than once in a given BeginFrame
  // callback nor send more than one BeginFrame message.
  void OnBeginFrame(const BeginFrameArgs& args);
  void OnBeginFrameDeadlinePending();
  void OnBeginFrameDeadline();
  void OnBeginFrameIdle();
  bool ShouldTriggerBeginFrameDeadlineEarly() const;
  BeginFrameState begin_frame_state() const {
    return begin_frame_state_;
  }

  // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
  // avoid requesting BeginImplFrames when we won't actually draw but still
  // need to advance our state at vsync intervals.
  void DidEnterPollForAnticipatedDrawTriggers();
  void DidLeavePollForAnticipatedDrawTriggers();
  bool inside_poll_for_anticipated_draw_triggers() const {
    return inside_poll_for_anticipated_draw_triggers_;
  }

  // Indicates whether the LayerTreeHostImpl is visible.
  void SetVisible(bool 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_; }

  // Indicates that manage-tiles is required. This guarantees another
  // ManageTiles will occur shortly (even if no redraw is required).
  void SetNeedsManageTiles();

  // Indicates whether a redraw is required because we are currently rendering
  // with a low resolution or checkerboarded tile.
  void SetSwapUsedIncompleteTile(bool used_incomplete_tile);

  // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
  void DidDrawIfPossibleCompleted(bool success);

  // 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();

  // As SetNeedsCommit(), but ensures the begin frame will be sent to the main
  // thread even if we are not visible.  After this call we expect to go through
  // the forced commit flow and then return to waiting for a non-forced
  // begin frame to finish.
  void SetNeedsForcedCommitForReadback();

  // Call this only in response to receiving an
  // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction.
  // Indicates that all painting is complete.
  void FinishCommit();

  // Call this only in response to receiving an
  // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction if the client
  // rejects the begin frame message.  If did_handle is false, then
  // another commit will be retried soon.
  void BeginFrameAbortedByMainThread(bool did_handle);

  // Request exclusive access to the textures that back single buffered
  // layers on behalf of the main thread. Upon acquisition,
  // ACTION_DRAW_AND_SWAP_IF_POSSIBLE will not draw until the main thread
  // releases the
  // textures to the impl thread by committing the layers.
  void SetMainThreadNeedsLayerTextures();

  // Set that we can create the first OutputSurface and start the scheduler.
  void SetCanStart() { can_start_ = true; }

  // Indicates whether drawing would, at this time, make sense.
  // CanDraw can be used to supress flashes or checkerboarding
  // when such behavior would be undesirable.
  void SetCanDraw(bool can);

  // Indicates that the pending tree is ready for activation.
  void NotifyReadyToActivate();

  bool has_pending_tree() const { return has_pending_tree_; }

  void DidLoseOutputSurface();
  void DidCreateAndInitializeOutputSurface();
  bool HasInitializedOutputSurface() const;

  // True if we need to abort draws to make forward progress.
  bool PendingDrawsShouldBeAborted() const;

 protected:
  bool BeginFrameNeededToDrawByImplThread() const;
  bool ProactiveBeginFrameWantedByImplThread() const;

  // True if we need to force activations to make forward progress.
  bool PendingActivationsShouldBeForced() const;

  bool ShouldBeginOutputSurfaceCreation() const;
  bool ShouldDrawForced() const;
  bool ShouldDraw() const;
  bool ShouldActivatePendingTree() const;
  bool ShouldAcquireLayerTexturesForMainThread() const;
  bool ShouldUpdateVisibleTiles() const;
  bool ShouldSendBeginFrameToMainThread() const;
  bool ShouldCommit() const;
  bool ShouldManageTiles() const;

  bool HasSentBeginFrameToMainThreadThisFrame() const;
  bool HasScheduledManageTilesThisFrame() const;
  bool HasUpdatedVisibleTilesThisFrame() const;
  bool HasSwappedThisFrame() const;

  void UpdateStateOnCommit(bool commit_was_aborted);
  void UpdateStateOnActivation();
  void UpdateStateOnDraw(bool did_swap);
  void UpdateStateOnManageTiles();

  const SchedulerSettings settings_;

  OutputSurfaceState output_surface_state_;
  BeginFrameState begin_frame_state_;
  CommitState commit_state_;
  TextureState texture_state_;
  ForcedRedrawOnTimeoutState forced_redraw_state_;
  SynchronousReadbackState readback_state_;

  BeginFrameArgs last_begin_frame_args_;

  int commit_count_;
  int current_frame_number_;
  int last_frame_number_swap_performed_;
  int last_frame_number_begin_frame_sent_to_main_thread_;
  int last_frame_number_update_visible_tiles_was_called_;

  int consecutive_failed_draws_;
  bool needs_redraw_;
  bool needs_manage_tiles_;
  bool swap_used_incomplete_tile_;
  bool needs_commit_;
  bool main_thread_needs_layer_textures_;
  bool inside_poll_for_anticipated_draw_triggers_;
  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 draw_if_possible_failed_;
  bool did_create_and_initialize_first_output_surface_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
};

}  // namespace cc

#endif  // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_