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_H_
6#define CC_SCHEDULER_SCHEDULER_H_
7
8#include <deque>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/cancelable_callback.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/time/time.h"
15#include "cc/base/cc_export.h"
16#include "cc/output/begin_frame_args.h"
17#include "cc/scheduler/delay_based_time_source.h"
18#include "cc/scheduler/draw_result.h"
19#include "cc/scheduler/scheduler_settings.h"
20#include "cc/scheduler/scheduler_state_machine.h"
21
22namespace base {
23namespace debug {
24class ConvertableToTraceFormat;
25}
26class SingleThreadTaskRunner;
27}
28
29namespace cc {
30
31class SchedulerClient {
32 public:
33  virtual void SetNeedsBeginFrame(bool enable) = 0;
34  virtual void WillBeginImplFrame(const BeginFrameArgs& args) = 0;
35  virtual void ScheduledActionSendBeginMainFrame() = 0;
36  virtual DrawResult ScheduledActionDrawAndSwapIfPossible() = 0;
37  virtual DrawResult ScheduledActionDrawAndSwapForced() = 0;
38  virtual void ScheduledActionAnimate() = 0;
39  virtual void ScheduledActionCommit() = 0;
40  virtual void ScheduledActionUpdateVisibleTiles() = 0;
41  virtual void ScheduledActionActivateSyncTree() = 0;
42  virtual void ScheduledActionBeginOutputSurfaceCreation() = 0;
43  virtual void ScheduledActionManageTiles() = 0;
44  virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) = 0;
45  virtual base::TimeDelta DrawDurationEstimate() = 0;
46  virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() = 0;
47  virtual base::TimeDelta CommitToActivateDurationEstimate() = 0;
48  virtual void DidBeginImplFrameDeadline() = 0;
49
50 protected:
51  virtual ~SchedulerClient() {}
52};
53
54class CC_EXPORT Scheduler {
55 public:
56  static scoped_ptr<Scheduler> Create(
57      SchedulerClient* client,
58      const SchedulerSettings& scheduler_settings,
59      int layer_tree_host_id,
60      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
61    return make_scoped_ptr(new Scheduler(
62        client, scheduler_settings, layer_tree_host_id, task_runner));
63  }
64
65  virtual ~Scheduler();
66
67  const SchedulerSettings& settings() const { return settings_; }
68
69  void CommitVSyncParameters(base::TimeTicks timebase,
70                             base::TimeDelta interval);
71  void SetEstimatedParentDrawTime(base::TimeDelta draw_time);
72
73  void SetCanStart();
74
75  void SetVisible(bool visible);
76  void SetCanDraw(bool can_draw);
77  void NotifyReadyToActivate();
78
79  void SetNeedsCommit();
80
81  void SetNeedsRedraw();
82
83  void SetNeedsAnimate();
84
85  void SetNeedsManageTiles();
86
87  void SetMaxSwapsPending(int max);
88  void DidSwapBuffers();
89  void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
90  void DidSwapBuffersComplete();
91
92  void SetImplLatencyTakesPriority(bool impl_latency_takes_priority);
93
94  void NotifyReadyToCommit();
95  void BeginMainFrameAborted(bool did_handle);
96
97  void DidManageTiles();
98  void DidLoseOutputSurface();
99  void DidCreateAndInitializeOutputSurface();
100
101  // Tests do not want to shut down until all possible BeginMainFrames have
102  // occured to prevent flakiness.
103  bool MainFrameForTestingWillHappen() const {
104    return state_machine_.CommitPending() ||
105           state_machine_.CouldSendBeginMainFrame();
106  }
107
108  bool CommitPending() const { return state_machine_.CommitPending(); }
109  bool RedrawPending() const { return state_machine_.RedrawPending(); }
110  bool ManageTilesPending() const {
111    return state_machine_.ManageTilesPending();
112  }
113  bool MainThreadIsInHighLatencyMode() const {
114    return state_machine_.MainThreadIsInHighLatencyMode();
115  }
116  bool BeginImplFrameDeadlinePending() const {
117    return !begin_impl_frame_deadline_task_.IsCancelled();
118  }
119
120  bool WillDrawIfNeeded() const;
121
122  base::TimeTicks AnticipatedDrawTime() const;
123
124  void NotifyBeginMainFrameStarted();
125
126  base::TimeTicks LastBeginImplFrameTime();
127
128  void BeginFrame(const BeginFrameArgs& args);
129
130  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
131  void AsValueInto(base::debug::TracedValue* state) const;
132
133  void SetContinuousPainting(bool continuous_painting) {
134    state_machine_.SetContinuousPainting(continuous_painting);
135  }
136
137 protected:
138  class CC_EXPORT SyntheticBeginFrameSource : public TimeSourceClient {
139   public:
140    SyntheticBeginFrameSource(Scheduler* scheduler,
141                              scoped_refptr<DelayBasedTimeSource> time_source);
142    virtual ~SyntheticBeginFrameSource();
143
144    // Updates the phase and frequency of the timer.
145    void CommitVSyncParameters(base::TimeTicks timebase,
146                               base::TimeDelta interval);
147
148    // Activates future BeginFrames and, if activating, pushes the most
149    // recently missed BeginFrame to the back of a retroactive queue.
150    void SetNeedsBeginFrame(bool needs_begin_frame,
151                            std::deque<BeginFrameArgs>* begin_retro_frame_args);
152
153    bool IsActive() const;
154
155    // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame.
156    virtual void OnTimerTick() OVERRIDE;
157
158    void AsValueInto(base::debug::TracedValue* dict) const;
159
160   private:
161    BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time);
162
163    Scheduler* scheduler_;
164    scoped_refptr<DelayBasedTimeSource> time_source_;
165  };
166
167  Scheduler(SchedulerClient* client,
168            const SchedulerSettings& scheduler_settings,
169            int layer_tree_host_id,
170            const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
171
172  virtual base::TimeTicks Now() const;
173
174  const SchedulerSettings settings_;
175  SchedulerClient* client_;
176  int layer_tree_host_id_;
177  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
178
179  base::TimeDelta vsync_interval_;
180  base::TimeDelta estimated_parent_draw_time_;
181
182  bool last_set_needs_begin_frame_;
183  bool begin_unthrottled_frame_posted_;
184  bool begin_retro_frame_posted_;
185  std::deque<BeginFrameArgs> begin_retro_frame_args_;
186  BeginFrameArgs begin_impl_frame_args_;
187
188  scoped_ptr<SyntheticBeginFrameSource> synthetic_begin_frame_source_;
189
190  base::Closure begin_retro_frame_closure_;
191  base::Closure begin_unthrottled_frame_closure_;
192
193  base::Closure begin_impl_frame_deadline_closure_;
194  base::Closure poll_for_draw_triggers_closure_;
195  base::Closure advance_commit_state_closure_;
196  base::CancelableClosure begin_impl_frame_deadline_task_;
197  base::CancelableClosure poll_for_draw_triggers_task_;
198  base::CancelableClosure advance_commit_state_task_;
199
200  SchedulerStateMachine state_machine_;
201  bool inside_process_scheduled_actions_;
202  SchedulerStateMachine::Action inside_action_;
203
204  base::TimeDelta VSyncInterval() { return vsync_interval_; }
205
206 private:
207  base::TimeTicks AdjustedBeginImplFrameDeadline(
208      const BeginFrameArgs& args,
209      base::TimeDelta draw_duration_estimate) const;
210  void ScheduleBeginImplFrameDeadline(base::TimeTicks deadline);
211  void SetupNextBeginFrameIfNeeded();
212  void PostBeginRetroFrameIfNeeded();
213  void SetupNextBeginFrameWhenVSyncThrottlingEnabled(bool needs_begin_frame);
214  void SetupNextBeginFrameWhenVSyncThrottlingDisabled(bool needs_begin_frame);
215  void SetupPollingMechanisms(bool needs_begin_frame);
216  void DrawAndSwapIfPossible();
217  void ProcessScheduledActions();
218  bool CanCommitAndActivateBeforeDeadline() const;
219  void AdvanceCommitStateIfPossible();
220  bool IsBeginMainFrameSentOrStarted() const;
221  void SetupSyntheticBeginFrames();
222  void BeginRetroFrame();
223  void BeginUnthrottledFrame();
224  void BeginImplFrame(const BeginFrameArgs& args);
225  void OnBeginImplFrameDeadline();
226  void PollForAnticipatedDrawTriggers();
227  void PollToAdvanceCommitState();
228
229  base::TimeDelta EstimatedParentDrawTime() {
230    return estimated_parent_draw_time_;
231  }
232
233  bool IsInsideAction(SchedulerStateMachine::Action action) {
234    return inside_action_ == action;
235  }
236
237  base::WeakPtrFactory<Scheduler> weak_factory_;
238
239  DISALLOW_COPY_AND_ASSIGN(Scheduler);
240};
241
242}  // namespace cc
243
244#endif  // CC_SCHEDULER_SCHEDULER_H_
245