summaryrefslogtreecommitdiffstats
path: root/cc/scheduler/begin_frame_source.h
blob: 085088458cb6a3ea7ad2b1af2bee4f547bf96b5c (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
293
294
295
296
297
298
299
300
301
302
303
304
305
// Copyright 2014 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_BEGIN_FRAME_SOURCE_H_
#define CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_

#include <stddef.h>
#include <stdint.h>

#include <set>
#include <string>

#include "base/logging.h"
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "cc/output/begin_frame_args.h"
#include "cc/scheduler/delay_based_time_source.h"

#ifdef NDEBUG
#define DEBUG_FRAMES(...)
#else
#define DEBUG_FRAMES(name, arg1_name, arg1_val, arg2_name, arg2_val)         \
  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), name, \
               arg1_name, arg1_val, arg2_name, arg2_val);
#endif

namespace cc {

// (Pure) Interface for observing BeginFrame messages from BeginFrameSource
// objects.
class CC_EXPORT BeginFrameObserver {
 public:
  virtual ~BeginFrameObserver() {}

  // The |args| given to OnBeginFrame is guaranteed to have
  // |args|.IsValid()==true and have |args|.frame_time
  // field be strictly greater than the previous call.
  //
  // Side effects: This function can (and most of the time *will*) change the
  // return value of the LastUsedBeginFrameArgs method. See the documentation
  // on that method for more information.
  virtual void OnBeginFrame(const BeginFrameArgs& args) = 0;

  // Returns the last BeginFrameArgs used by the observer. This method's return
  // value is affected by the OnBeginFrame method!
  //
  //  - Before the first call of OnBeginFrame, this method should return a
  //    BeginFrameArgs on which IsValid() returns false.
  //
  //  - If the |args| passed to OnBeginFrame is (or *will be*) used, then
  //    LastUsedBeginFrameArgs return value should become the |args| given to
  //    OnBeginFrame.
  //
  //  - If the |args| passed to OnBeginFrame is dropped, then
  //    LastUsedBeginFrameArgs return value should *not* change.
  //
  // These requirements are designed to allow chaining and nesting of
  // BeginFrameObservers which filter the incoming BeginFrame messages while
  // preventing "double dropping" and other bad side effects.
  virtual const BeginFrameArgs& LastUsedBeginFrameArgs() const = 0;

  virtual void OnBeginFrameSourcePausedChanged(bool paused) = 0;

  // Tracing support
  virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0;
};

// Simple base class which implements a BeginFrameObserver which checks the
// incoming values meet the BeginFrameObserver requirements and implements the
// required LastUsedBeginFrameArgs behaviour.
//
// Users of this class should;
//  - Implement the OnBeginFrameDerivedImpl function.
//  - Recommended (but not required) to call
//    BeginFrameObserverBase::OnValueInto in their overridden OnValueInto
//    function.
class CC_EXPORT BeginFrameObserverBase : public BeginFrameObserver {
 public:
  BeginFrameObserverBase();

  // BeginFrameObserver

  // Traces |args| and DCHECK |args| satisfies pre-conditions then calls
  // OnBeginFrameDerivedImpl and updates the last_begin_frame_args_ value on
  // true.
  void OnBeginFrame(const BeginFrameArgs& args) override;
  const BeginFrameArgs& LastUsedBeginFrameArgs() const override;

  // Outputs last_begin_frame_args_
  void AsValueInto(base::trace_event::TracedValue* dict) const override;

 protected:
  // Subclasses should override this method!
  // Return true if the given argument is (or will be) used.
  virtual bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) = 0;

  BeginFrameArgs last_begin_frame_args_;
  int64_t dropped_begin_frame_args_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BeginFrameObserverBase);
};

// Interface for a class which produces BeginFrame calls to a
// BeginFrameObserver.
//
// BeginFrame calls *normally* occur just after a vsync interrupt when input
// processing has been finished and provide information about the time values
// of the vsync times. *However*, these values can be heavily modified or even
// plain made up (when no vsync signal is available or vsync throttling is
// turned off). See the BeginFrameObserver for information about the guarantees
// all BeginFrameSources *must* provide.
class CC_EXPORT BeginFrameSource {
 public:
  virtual ~BeginFrameSource() {}

  // DidFinishFrame provides back pressure to a frame source about frame
  // processing (rather than toggling SetNeedsBeginFrames every frame). It is
  // used by systems like the BackToBackFrameSource to make sure only one frame
  // is pending at a time.
  virtual void DidFinishFrame(size_t remaining_frames) = 0;

  // Add/Remove an observer from the source. When no observers are added the BFS
  // should shut down its timers, disable vsync, etc.
  virtual void AddObserver(BeginFrameObserver* obs) = 0;
  virtual void RemoveObserver(BeginFrameObserver* obs) = 0;

  // Tells the Source that client is ready to handle BeginFrames messages.
  virtual void SetClientReady() = 0;

  // Tracing support - Recommend (but not required) to call this implementation
  // in any override.
  virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0;
};

// Simple base class which implements a BeginFrameSource.
// Implementation classes should:
//  - Implement the pure virtual (Set)NeedsBeginFrames methods from
//    BeginFrameSource.
//  - Use the CallOnBeginFrame method to call to the observer(s).
//  - Recommended (but not required) to call BeginFrameSourceBase::AsValueInto
//    in their own AsValueInto implementation.
class CC_EXPORT BeginFrameSourceBase : public BeginFrameSource {
 public:
  ~BeginFrameSourceBase() override;

  // BeginFrameSource
  void DidFinishFrame(size_t remaining_frames) override {}
  void AddObserver(BeginFrameObserver* obs) override;
  void RemoveObserver(BeginFrameObserver* obs) override;
  void SetClientReady() override {}

  // Tracing support - Recommend (but not required) to call this implementation
  // in any override.
  void AsValueInto(base::trace_event::TracedValue* dict) const override;

 protected:
  BeginFrameSourceBase();

  // These methods should be used by subclasses to make the call to the
  // observers.
  void CallOnBeginFrame(const BeginFrameArgs& args);
  void SetBeginFrameSourcePaused(bool paused);

  // This notifies that the subclass that it must turn on or off its mechnanism
  // for producing BeginFrames.
  virtual void OnNeedsBeginFramesChanged(bool needs_begin_frames) {}

  bool needs_begin_frames() const { return !observers_.empty(); }

  std::set<BeginFrameObserver*> observers_;
  bool paused_;

 private:
  bool inside_as_value_into_;

  DISALLOW_COPY_AND_ASSIGN(BeginFrameSourceBase);
};

// A frame source which calls BeginFrame (at the next possible time) as soon as
// remaining frames reaches zero.
class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceBase {
 public:
  static scoped_ptr<BackToBackBeginFrameSource> Create(
      base::SingleThreadTaskRunner* task_runner);
  ~BackToBackBeginFrameSource() override;

  // BeginFrameSource
  void DidFinishFrame(size_t remaining_frames) override;

  // BeginFrameSourceBase
  void AddObserver(BeginFrameObserver* obs) override;
  void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;

  // Tracing
  void AsValueInto(base::trace_event::TracedValue* dict) const override;

 protected:
  explicit BackToBackBeginFrameSource(
      base::SingleThreadTaskRunner* task_runner);
  virtual base::TimeTicks Now();  // Now overridable for testing

  base::SingleThreadTaskRunner* task_runner_;
  base::CancelableClosure begin_frame_task_;

  void PostBeginFrame();
  void BeginFrame();

 private:
  base::WeakPtrFactory<BackToBackBeginFrameSource> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(BackToBackBeginFrameSource);
};

// A frame source which is locked to an external parameters provides from a
// vsync source and generates BeginFrameArgs for it.
class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSourceBase,
                                            public DelayBasedTimeSourceClient {
 public:
  static scoped_ptr<SyntheticBeginFrameSource> Create(
      base::SingleThreadTaskRunner* task_runner,
      base::TimeDelta initial_vsync_interval);
  ~SyntheticBeginFrameSource() override;

  void OnUpdateVSyncParameters(base::TimeTicks new_vsync_timebase,
                               base::TimeDelta new_vsync_interval);

  // BeginFrameSourceBase
  void AddObserver(BeginFrameObserver* obs) override;
  void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;

  // Tracing
  void AsValueInto(base::trace_event::TracedValue* dict) const override;

  // DelayBasedTimeSourceClient
  void OnTimerTick() override;

 protected:
  explicit SyntheticBeginFrameSource(
      scoped_ptr<DelayBasedTimeSource> time_source);

  BeginFrameArgs CreateBeginFrameArgs(base::TimeTicks frame_time,
                                      BeginFrameArgs::BeginFrameArgsType type);

  scoped_ptr<DelayBasedTimeSource> time_source_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SyntheticBeginFrameSource);
};

// A "virtual" frame source which lets you switch between multiple other frame
// sources while making sure the BeginFrameArgs stays increasing (possibly
// enforcing minimum boundry between BeginFrameArgs messages).
class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceBase,
                                              public BeginFrameObserver {
 public:
  static scoped_ptr<BeginFrameSourceMultiplexer> Create();
  ~BeginFrameSourceMultiplexer() override;

  void SetMinimumInterval(base::TimeDelta new_minimum_interval);

  void AddSource(BeginFrameSource* new_source);
  void RemoveSource(BeginFrameSource* existing_source);
  void SetActiveSource(BeginFrameSource* new_source);
  const BeginFrameSource* ActiveSource();

  // BeginFrameObserver
  // The mux is an BeginFrameObserver as it needs to proxy the OnBeginFrame
  // calls to preserve the monotonicity of the BeginFrameArgs when switching
  // sources.
  void OnBeginFrame(const BeginFrameArgs& args) override;
  const BeginFrameArgs& LastUsedBeginFrameArgs() const override;
  void OnBeginFrameSourcePausedChanged(bool paused) override;

  // BeginFrameSourceBase
  void DidFinishFrame(size_t remaining_frames) override;
  void AddObserver(BeginFrameObserver* obs) override;
  void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;

  // Tracing
  void AsValueInto(base::trace_event::TracedValue* dict) const override;

 protected:
  BeginFrameSourceMultiplexer();
  explicit BeginFrameSourceMultiplexer(base::TimeDelta minimum_interval);

  bool HasSource(BeginFrameSource* source);
  bool IsIncreasing(const BeginFrameArgs& args);

  base::TimeDelta minimum_interval_;

  BeginFrameSource* active_source_;
  std::set<BeginFrameSource*> source_list_;

  BeginFrameArgs last_begin_frame_args_;
  bool inside_add_observer_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BeginFrameSourceMultiplexer);
};

}  // namespace cc

#endif  // CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_