blob: aa153c6bddcaee0bceb6af5c0656ad33d0f81a1a [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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"
Etienne Membrives175837a2014-12-19 15:45:38 +010015#include "cc/scheduler/commit_earlyout_reason.h"
James Robinson646469d2014-10-03 15:33:28 -070016#include "cc/scheduler/draw_result.h"
17#include "cc/scheduler/scheduler_settings.h"
18
19namespace base {
20namespace debug {
21class ConvertableToTraceFormat;
22class TracedValue;
23}
24class Value;
25}
26
27namespace cc {
28
29// The SchedulerStateMachine decides how to coordinate main thread activites
30// like painting/running javascript with rendering and input activities on the
31// impl thread.
32//
33// The state machine tracks internal state but is also influenced by external
34// state. Internal state includes things like whether a frame has been
35// requested, while external state includes things like the current time being
36// near to the vblank time.
37//
38// The scheduler seperates "what to do next" from the updating of its internal
39// state to make testing cleaner.
40class CC_EXPORT SchedulerStateMachine {
41 public:
42 // settings must be valid for the lifetime of this class.
43 explicit SchedulerStateMachine(const SchedulerSettings& settings);
44
45 enum OutputSurfaceState {
46 OUTPUT_SURFACE_ACTIVE,
47 OUTPUT_SURFACE_LOST,
48 OUTPUT_SURFACE_CREATING,
49 OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
50 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
51 };
52 static const char* OutputSurfaceStateToString(OutputSurfaceState state);
53
54 // Note: BeginImplFrameState will always cycle through all the states in
55 // order. Whether or not it actually waits or draws, it will at least try to
56 // wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
57 // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
58 enum BeginImplFrameState {
59 BEGIN_IMPL_FRAME_STATE_IDLE,
60 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
61 BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
62 BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
63 };
64 static const char* BeginImplFrameStateToString(BeginImplFrameState state);
65
James Robinsond2015d92014-12-08 13:45:40 -080066 enum BeginImplFrameDeadlineMode {
67 BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE,
68 BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR,
69 BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE,
70 };
71 static const char* BeginImplFrameDeadlineModeToString(
72 BeginImplFrameDeadlineMode mode);
73
James Robinson646469d2014-10-03 15:33:28 -070074 enum CommitState {
75 COMMIT_STATE_IDLE,
76 COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
77 COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
78 COMMIT_STATE_READY_TO_COMMIT,
79 COMMIT_STATE_WAITING_FOR_ACTIVATION,
James Robinson6a64b812014-12-03 13:38:42 -080080 COMMIT_STATE_WAITING_FOR_DRAW,
James Robinson646469d2014-10-03 15:33:28 -070081 };
82 static const char* CommitStateToString(CommitState state);
83
84 enum ForcedRedrawOnTimeoutState {
85 FORCED_REDRAW_STATE_IDLE,
86 FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,
87 FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
88 FORCED_REDRAW_STATE_WAITING_FOR_DRAW,
89 };
90 static const char* ForcedRedrawOnTimeoutStateToString(
91 ForcedRedrawOnTimeoutState state);
92
93 bool CommitPending() const {
94 return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
95 commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
96 commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
97 }
98 CommitState commit_state() const { return commit_state_; }
99
100 bool RedrawPending() const { return needs_redraw_; }
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100101 bool PrepareTilesPending() const { return needs_prepare_tiles_; }
James Robinson646469d2014-10-03 15:33:28 -0700102
103 enum Action {
104 ACTION_NONE,
105 ACTION_ANIMATE,
106 ACTION_SEND_BEGIN_MAIN_FRAME,
107 ACTION_COMMIT,
James Robinson646469d2014-10-03 15:33:28 -0700108 ACTION_ACTIVATE_SYNC_TREE,
109 ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
110 ACTION_DRAW_AND_SWAP_FORCED,
111 ACTION_DRAW_AND_SWAP_ABORT,
112 ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100113 ACTION_PREPARE_TILES,
James Robinson646469d2014-10-03 15:33:28 -0700114 };
115 static const char* ActionToString(Action action);
116
117 scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
118 void AsValueInto(base::debug::TracedValue* dict, base::TimeTicks now) const;
119
120 Action NextAction() const;
121 void UpdateState(Action action);
122
123 // Indicates whether the impl thread needs a BeginImplFrame callback in order
124 // to make progress.
125 bool BeginFrameNeeded() const;
126
Nick Bray27a3f6e2015-01-08 16:39:35 -0800127 // Indicates whether the scheduler should call
128 // SetNeedsBeginFrames(BeginFrameNeeded()) on the frame source.
129 bool ShouldSetNeedsBeginFrames(bool frame_source_needs_begin_frames) const;
130
James Robinson646469d2014-10-03 15:33:28 -0700131 // Indicates that we need to independently poll for new state and actions
132 // because we can't expect a BeginImplFrame. This is mostly used to avoid
133 // drawing repeat frames with the synchronous compositor without dropping
134 // necessary actions on the floor.
135 bool ShouldPollForAnticipatedDrawTriggers() const;
136
137 // Indicates that the system has entered and left a BeginImplFrame callback.
138 // The scheduler will not draw more than once in a given BeginImplFrame
139 // callback nor send more than one BeginMainFrame message.
140 void OnBeginImplFrame(const BeginFrameArgs& args);
141 void OnBeginImplFrameDeadlinePending();
142 void OnBeginImplFrameDeadline();
143 void OnBeginImplFrameIdle();
James Robinson646469d2014-10-03 15:33:28 -0700144 BeginImplFrameState begin_impl_frame_state() const {
145 return begin_impl_frame_state_;
146 }
James Robinsond2015d92014-12-08 13:45:40 -0800147 BeginImplFrameDeadlineMode CurrentBeginImplFrameDeadlineMode() const;
James Robinson646469d2014-10-03 15:33:28 -0700148
149 // If the main thread didn't manage to produce a new frame in time for the
150 // impl thread to draw, it is in a high latency mode.
151 bool MainThreadIsInHighLatencyMode() const;
152
153 // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
154 // avoid requesting BeginImplFrames when we won't actually draw but still
155 // need to advance our state at vsync intervals.
156 void DidEnterPollForAnticipatedDrawTriggers();
157 void DidLeavePollForAnticipatedDrawTriggers();
158 bool inside_poll_for_anticipated_draw_triggers() const {
159 return inside_poll_for_anticipated_draw_triggers_;
160 }
161
162 // Indicates whether the LayerTreeHostImpl is visible.
163 void SetVisible(bool visible);
Nick Bray27a3f6e2015-01-08 16:39:35 -0800164 bool visible() const { return visible_; }
James Robinson646469d2014-10-03 15:33:28 -0700165
166 // Indicates that a redraw is required, either due to the impl tree changing
167 // or the screen being damaged and simply needing redisplay.
168 void SetNeedsRedraw();
169 bool needs_redraw() const { return needs_redraw_; }
170
171 void SetNeedsAnimate();
172 bool needs_animate() const { return needs_animate_; }
173
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100174 // Indicates that prepare-tiles is required. This guarantees another
175 // PrepareTiles will occur shortly (even if no redraw is required).
176 void SetNeedsPrepareTiles();
James Robinson646469d2014-10-03 15:33:28 -0700177
178 // Sets how many swaps can be pending to the OutputSurface.
179 void SetMaxSwapsPending(int max);
180
181 // If the scheduler attempted to draw and swap, this provides feedback
182 // regarding whether or not the swap actually occured. We might skip the
183 // swap when there is not damage, for example.
184 void DidSwapBuffers();
185
186 // Indicates whether a redraw is required because we are currently rendering
187 // with a low resolution or checkerboarded tile.
188 void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
189
190 // Notification from the OutputSurface that a swap has been consumed.
191 void DidSwapBuffersComplete();
192
193 // Indicates whether to prioritize impl thread latency (i.e., animation
194 // smoothness) over new content activation.
195 void SetImplLatencyTakesPriority(bool impl_latency_takes_priority);
196 bool impl_latency_takes_priority() const {
197 return impl_latency_takes_priority_;
198 }
199
200 // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
201 void DidDrawIfPossibleCompleted(DrawResult result);
202
203 // Indicates that a new commit flow needs to be performed, either to pull
204 // updates from the main thread to the impl, or to push deltas from the impl
205 // thread to main.
206 void SetNeedsCommit();
207
208 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
209 // from NextAction.
210 // Indicates that all painting is complete.
211 void NotifyReadyToCommit();
212
213 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
214 // from NextAction if the client rejects the BeginMainFrame message.
Etienne Membrives175837a2014-12-19 15:45:38 +0100215 void BeginMainFrameAborted(CommitEarlyOutReason reason);
James Robinson646469d2014-10-03 15:33:28 -0700216
217 // Set that we can create the first OutputSurface and start the scheduler.
218 void SetCanStart() { can_start_ = true; }
Etienne Membrives175837a2014-12-19 15:45:38 +0100219 // Allow access of the can_start_ state in tests.
220 bool CanStartForTesting() const { return can_start_; }
James Robinson646469d2014-10-03 15:33:28 -0700221
222 void SetSkipNextBeginMainFrameToReduceLatency();
223
224 // Indicates whether drawing would, at this time, make sense.
225 // CanDraw can be used to suppress flashes or checkerboarding
226 // when such behavior would be undesirable.
227 void SetCanDraw(bool can);
228
229 // Indicates that scheduled BeginMainFrame is started.
230 void NotifyBeginMainFrameStarted();
231
232 // Indicates that the pending tree is ready for activation.
233 void NotifyReadyToActivate();
234
235 bool has_pending_tree() const { return has_pending_tree_; }
236 bool active_tree_needs_first_draw() const {
237 return active_tree_needs_first_draw_;
238 }
239
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100240 void DidPrepareTiles();
James Robinson646469d2014-10-03 15:33:28 -0700241 void DidLoseOutputSurface();
242 void DidCreateAndInitializeOutputSurface();
243 bool HasInitializedOutputSurface() const;
244
245 // True if we need to abort draws to make forward progress.
246 bool PendingDrawsShouldBeAborted() const;
247
248 bool SupportsProactiveBeginFrame() const;
249
250 void SetContinuousPainting(bool continuous_painting) {
251 continuous_painting_ = continuous_painting;
252 }
253
254 bool CouldSendBeginMainFrame() const;
255
James Robinson80d418c2014-10-16 16:00:02 -0700256 void SetImplLatencyTakesPriorityOnBattery(
257 bool impl_latency_takes_priority_on_battery) {
258 impl_latency_takes_priority_on_battery_ =
259 impl_latency_takes_priority_on_battery;
260 }
261
Benjamin Lermancdfc88d2015-02-03 14:35:12 +0100262 void SetDeferCommits(bool defer_commits);
263
James Robinson646469d2014-10-03 15:33:28 -0700264 // TODO(zmo): This is temporary for debugging crbug.com/393331.
265 // We should remove it afterwards.
266 std::string GetStatesForDebugging() const;
267
James Robinsonc4c1c592014-11-21 18:27:04 -0800268 void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
269 bool children_need_begin_frames() const {
270 return children_need_begin_frames_;
271 }
272
James Robinson646469d2014-10-03 15:33:28 -0700273 protected:
274 bool BeginFrameNeededToAnimateOrDraw() const;
James Robinsonc4c1c592014-11-21 18:27:04 -0800275 bool BeginFrameNeededForChildren() const;
James Robinson646469d2014-10-03 15:33:28 -0700276 bool ProactiveBeginFrameWanted() const;
277
James Robinsond2015d92014-12-08 13:45:40 -0800278 bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
279
James Robinson646469d2014-10-03 15:33:28 -0700280 // True if we need to force activations to make forward progress.
281 bool PendingActivationsShouldBeForced() const;
282
283 bool ShouldAnimate() const;
284 bool ShouldBeginOutputSurfaceCreation() const;
285 bool ShouldDrawForced() const;
286 bool ShouldDraw() const;
287 bool ShouldActivatePendingTree() const;
James Robinson646469d2014-10-03 15:33:28 -0700288 bool ShouldSendBeginMainFrame() const;
289 bool ShouldCommit() const;
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100290 bool ShouldPrepareTiles() const;
James Robinson646469d2014-10-03 15:33:28 -0700291
292 void AdvanceCurrentFrameNumber();
James Robinson53b77582014-10-28 17:00:48 -0700293 bool HasAnimatedThisFrame() const;
James Robinson646469d2014-10-03 15:33:28 -0700294 bool HasSentBeginMainFrameThisFrame() const;
James Robinson646469d2014-10-03 15:33:28 -0700295 bool HasRequestedSwapThisFrame() const;
296 bool HasSwappedThisFrame() const;
297
Etienne Membrives175837a2014-12-19 15:45:38 +0100298 void UpdateStateOnCommit(bool commit_had_no_updates);
James Robinson646469d2014-10-03 15:33:28 -0700299 void UpdateStateOnActivation();
300 void UpdateStateOnDraw(bool did_request_swap);
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100301 void UpdateStateOnPrepareTiles();
James Robinson646469d2014-10-03 15:33:28 -0700302
303 const SchedulerSettings settings_;
304
305 OutputSurfaceState output_surface_state_;
306 BeginImplFrameState begin_impl_frame_state_;
307 CommitState commit_state_;
308 ForcedRedrawOnTimeoutState forced_redraw_state_;
309
310 BeginFrameArgs begin_impl_frame_args_;
311
312 int commit_count_;
313 int current_frame_number_;
314 int last_frame_number_animate_performed_;
315 int last_frame_number_swap_performed_;
316 int last_frame_number_swap_requested_;
317 int last_frame_number_begin_main_frame_sent_;
James Robinson646469d2014-10-03 15:33:28 -0700318
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100319 // prepare_tiles_funnel_ is "filled" each time PrepareTiles is called
James Robinson646469d2014-10-03 15:33:28 -0700320 // and "drained" on each BeginImplFrame. If the funnel gets too full,
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100321 // we start throttling ACTION_PREPARE_TILES such that we average one
322 // PrepareTiles per BeginImplFrame.
323 int prepare_tiles_funnel_;
James Robinson646469d2014-10-03 15:33:28 -0700324 int consecutive_checkerboard_animations_;
325 int max_pending_swaps_;
326 int pending_swaps_;
327 bool needs_redraw_;
328 bool needs_animate_;
Przemyslaw Pietrzkiewiczea77f0b2014-12-10 15:35:08 +0100329 bool needs_prepare_tiles_;
James Robinson646469d2014-10-03 15:33:28 -0700330 bool needs_commit_;
331 bool inside_poll_for_anticipated_draw_triggers_;
332 bool visible_;
333 bool can_start_;
334 bool can_draw_;
335 bool has_pending_tree_;
336 bool pending_tree_is_ready_for_activation_;
337 bool active_tree_needs_first_draw_;
James Robinson53b77582014-10-28 17:00:48 -0700338 bool did_commit_after_animating_;
James Robinson646469d2014-10-03 15:33:28 -0700339 bool did_create_and_initialize_first_output_surface_;
340 bool impl_latency_takes_priority_;
341 bool skip_next_begin_main_frame_to_reduce_latency_;
342 bool skip_begin_main_frame_to_reduce_latency_;
343 bool continuous_painting_;
James Robinson80d418c2014-10-16 16:00:02 -0700344 bool impl_latency_takes_priority_on_battery_;
James Robinsonc4c1c592014-11-21 18:27:04 -0800345 bool children_need_begin_frames_;
Benjamin Lermancdfc88d2015-02-03 14:35:12 +0100346 bool defer_commits_;
James Robinson646469d2014-10-03 15:33:28 -0700347
348 private:
349 DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
350};
351
352} // namespace cc
353
354#endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_