Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / cc / scheduler / scheduler_state_machine.h
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
3 // found in the LICENSE file.
4
5 #ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
6 #define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
7
8 #include <string>
9
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/time/time.h"
13 #include "cc/base/cc_export.h"
14 #include "cc/output/begin_frame_args.h"
15 #include "cc/scheduler/draw_result.h"
16 #include "cc/scheduler/scheduler_settings.h"
17
18 namespace base {
19 class Value;
20 }
21
22 namespace cc {
23
24 // The SchedulerStateMachine decides how to coordinate main thread activites
25 // like painting/running javascript with rendering and input activities on the
26 // impl thread.
27 //
28 // The state machine tracks internal state but is also influenced by external
29 // state.  Internal state includes things like whether a frame has been
30 // requested, while external state includes things like the current time being
31 // near to the vblank time.
32 //
33 // The scheduler seperates "what to do next" from the updating of its internal
34 // state to make testing cleaner.
35 class CC_EXPORT SchedulerStateMachine {
36  public:
37   // settings must be valid for the lifetime of this class.
38   explicit SchedulerStateMachine(const SchedulerSettings& settings);
39
40   enum OutputSurfaceState {
41     OUTPUT_SURFACE_ACTIVE,
42     OUTPUT_SURFACE_LOST,
43     OUTPUT_SURFACE_CREATING,
44     OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
45     OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
46   };
47   static const char* OutputSurfaceStateToString(OutputSurfaceState state);
48
49   // Note: BeginImplFrameState will always cycle through all the states in
50   // order. Whether or not it actually waits or draws, it will at least try to
51   // wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
52   // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
53   enum BeginImplFrameState {
54     BEGIN_IMPL_FRAME_STATE_IDLE,
55     BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
56     BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
57     BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
58   };
59   static const char* BeginImplFrameStateToString(BeginImplFrameState state);
60
61   enum CommitState {
62     COMMIT_STATE_IDLE,
63     COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
64     COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
65     COMMIT_STATE_READY_TO_COMMIT,
66     COMMIT_STATE_WAITING_FOR_ACTIVATION,
67     COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
68   };
69   static const char* CommitStateToString(CommitState state);
70
71   enum ForcedRedrawOnTimeoutState {
72     FORCED_REDRAW_STATE_IDLE,
73     FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,
74     FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
75     FORCED_REDRAW_STATE_WAITING_FOR_DRAW,
76   };
77   static const char* ForcedRedrawOnTimeoutStateToString(
78       ForcedRedrawOnTimeoutState state);
79
80   bool CommitPending() const {
81     return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
82            commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
83            commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
84   }
85   CommitState commit_state() const { return commit_state_; }
86
87   bool RedrawPending() const { return needs_redraw_; }
88   bool ManageTilesPending() const { return needs_manage_tiles_; }
89
90   enum Action {
91     ACTION_NONE,
92     ACTION_ANIMATE,
93     ACTION_SEND_BEGIN_MAIN_FRAME,
94     ACTION_COMMIT,
95     ACTION_UPDATE_VISIBLE_TILES,
96     ACTION_ACTIVATE_PENDING_TREE,
97     ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
98     ACTION_DRAW_AND_SWAP_FORCED,
99     ACTION_DRAW_AND_SWAP_ABORT,
100     ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
101     ACTION_MANAGE_TILES,
102   };
103   static const char* ActionToString(Action action);
104
105   scoped_ptr<base::Value> AsValue() const;
106
107   Action NextAction() const;
108   void UpdateState(Action action);
109
110   // Indicates whether the impl thread needs a BeginImplFrame callback in order
111   // to make progress.
112   bool BeginFrameNeeded() const;
113
114   // Indicates that we need to independently poll for new state and actions
115   // because we can't expect a BeginImplFrame. This is mostly used to avoid
116   // drawing repeat frames with the synchronous compositor without dropping
117   // necessary actions on the floor.
118   bool ShouldPollForAnticipatedDrawTriggers() const;
119
120   // Indicates that the system has entered and left a BeginImplFrame callback.
121   // The scheduler will not draw more than once in a given BeginImplFrame
122   // callback nor send more than one BeginMainFrame message.
123   void OnBeginImplFrame(const BeginFrameArgs& args);
124   void OnBeginImplFrameDeadlinePending();
125   void OnBeginImplFrameDeadline();
126   void OnBeginImplFrameIdle();
127   bool ShouldTriggerBeginImplFrameDeadlineEarly() const;
128   BeginImplFrameState begin_impl_frame_state() const {
129     return begin_impl_frame_state_;
130   }
131
132   // If the main thread didn't manage to produce a new frame in time for the
133   // impl thread to draw, it is in a high latency mode.
134   bool MainThreadIsInHighLatencyMode() const;
135
136   // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
137   // avoid requesting BeginImplFrames when we won't actually draw but still
138   // need to advance our state at vsync intervals.
139   void DidEnterPollForAnticipatedDrawTriggers();
140   void DidLeavePollForAnticipatedDrawTriggers();
141   bool inside_poll_for_anticipated_draw_triggers() const {
142     return inside_poll_for_anticipated_draw_triggers_;
143   }
144
145   // Indicates whether the LayerTreeHostImpl is visible.
146   void SetVisible(bool visible);
147
148   // Indicates that a redraw is required, either due to the impl tree changing
149   // or the screen being damaged and simply needing redisplay.
150   void SetNeedsRedraw();
151   bool needs_redraw() const { return needs_redraw_; }
152
153   void SetNeedsAnimate();
154   bool needs_animate() const { return needs_animate_; }
155
156   // Indicates that manage-tiles is required. This guarantees another
157   // ManageTiles will occur shortly (even if no redraw is required).
158   void SetNeedsManageTiles();
159
160   // Sets how many swaps can be pending to the OutputSurface.
161   void SetMaxSwapsPending(int max);
162
163   // If the scheduler attempted to draw and swap, this provides feedback
164   // regarding whether or not the swap actually occured. We might skip the
165   // swap when there is not damage, for example.
166   void DidSwapBuffers();
167
168   // Indicates whether a redraw is required because we are currently rendering
169   // with a low resolution or checkerboarded tile.
170   void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
171
172   // Notification from the OutputSurface that a swap has been consumed.
173   void DidSwapBuffersComplete();
174
175   // Indicates whether to prioritize animation smoothness over new content
176   // activation.
177   void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
178   bool smoothness_takes_priority() const { return smoothness_takes_priority_; }
179
180   // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
181   void DidDrawIfPossibleCompleted(DrawResult result);
182
183   // Indicates that a new commit flow needs to be performed, either to pull
184   // updates from the main thread to the impl, or to push deltas from the impl
185   // thread to main.
186   void SetNeedsCommit();
187
188   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
189   // from NextAction.
190   // Indicates that all painting is complete.
191   void NotifyReadyToCommit();
192
193   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
194   // from NextAction if the client rejects the BeginMainFrame message.
195   // If did_handle is false, then another commit will be retried soon.
196   void BeginMainFrameAborted(bool did_handle);
197
198   // Set that we can create the first OutputSurface and start the scheduler.
199   void SetCanStart() { can_start_ = true; }
200
201   void SetSkipNextBeginMainFrameToReduceLatency();
202
203   // Indicates whether drawing would, at this time, make sense.
204   // CanDraw can be used to suppress flashes or checkerboarding
205   // when such behavior would be undesirable.
206   void SetCanDraw(bool can);
207
208   // Indicates that scheduled BeginMainFrame is started.
209   void NotifyBeginMainFrameStarted();
210
211   // Indicates that the pending tree is ready for activation.
212   void NotifyReadyToActivate();
213
214   bool has_pending_tree() const { return has_pending_tree_; }
215   bool active_tree_needs_first_draw() const {
216     return active_tree_needs_first_draw_;
217   }
218
219   void DidManageTiles();
220   void DidLoseOutputSurface();
221   void DidCreateAndInitializeOutputSurface();
222   bool HasInitializedOutputSurface() const;
223
224   // True if we need to abort draws to make forward progress.
225   bool PendingDrawsShouldBeAborted() const;
226
227   bool SupportsProactiveBeginFrame() const;
228
229   void SetContinuousPainting(bool continuous_painting) {
230     continuous_painting_ = continuous_painting;
231   }
232
233  protected:
234   bool BeginFrameNeededToAnimateOrDraw() const;
235   bool ProactiveBeginFrameWanted() const;
236
237   // True if we need to force activations to make forward progress.
238   bool PendingActivationsShouldBeForced() const;
239
240   bool ShouldAnimate() const;
241   bool ShouldBeginOutputSurfaceCreation() const;
242   bool ShouldDrawForced() const;
243   bool ShouldDraw() const;
244   bool ShouldActivatePendingTree() const;
245   bool ShouldUpdateVisibleTiles() const;
246   bool ShouldSendBeginMainFrame() const;
247   bool ShouldCommit() const;
248   bool ShouldManageTiles() const;
249
250   void AdvanceCurrentFrameNumber();
251   bool HasSentBeginMainFrameThisFrame() const;
252   bool HasUpdatedVisibleTilesThisFrame() const;
253   bool HasRequestedSwapThisFrame() const;
254   bool HasSwappedThisFrame() const;
255
256   void UpdateStateOnCommit(bool commit_was_aborted);
257   void UpdateStateOnActivation();
258   void UpdateStateOnDraw(bool did_request_swap);
259   void UpdateStateOnManageTiles();
260
261   const SchedulerSettings settings_;
262
263   OutputSurfaceState output_surface_state_;
264   BeginImplFrameState begin_impl_frame_state_;
265   CommitState commit_state_;
266   ForcedRedrawOnTimeoutState forced_redraw_state_;
267
268   BeginFrameArgs begin_impl_frame_args_;
269
270   int commit_count_;
271   int current_frame_number_;
272   int last_frame_number_animate_performed_;
273   int last_frame_number_swap_performed_;
274   int last_frame_number_swap_requested_;
275   int last_frame_number_begin_main_frame_sent_;
276   int last_frame_number_update_visible_tiles_was_called_;
277
278   // manage_tiles_funnel_ is "filled" each time ManageTiles is called
279   // and "drained" on each BeginImplFrame. If the funnel gets too full,
280   // we start throttling ACTION_MANAGE_TILES such that we average one
281   // ManageTile per BeginImplFrame.
282   int manage_tiles_funnel_;
283   int consecutive_checkerboard_animations_;
284   int max_pending_swaps_;
285   int pending_swaps_;
286   bool needs_redraw_;
287   bool needs_animate_;
288   bool needs_manage_tiles_;
289   bool swap_used_incomplete_tile_;
290   bool needs_commit_;
291   bool inside_poll_for_anticipated_draw_triggers_;
292   bool visible_;
293   bool can_start_;
294   bool can_draw_;
295   bool has_pending_tree_;
296   bool pending_tree_is_ready_for_activation_;
297   bool active_tree_needs_first_draw_;
298   bool did_create_and_initialize_first_output_surface_;
299   bool smoothness_takes_priority_;
300   bool skip_next_begin_main_frame_to_reduce_latency_;
301   bool skip_begin_main_frame_to_reduce_latency_;
302   bool continuous_painting_;
303
304  private:
305   DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
306 };
307
308 }  // namespace cc
309
310 #endif  // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_