net cleanup: Remove unnecessary namespace prefixes.
[chromium-blink-merge.git] / cc / scheduler / begin_frame_source.cc
blob48d834359f43d41fd25b572ce387964f49ee9121
1 // Copyright 2014 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.
5 #include "cc/scheduler/begin_frame_source.h"
7 #include "base/auto_reset.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/trace_event/trace_event.h"
12 #include "base/trace_event/trace_event_argument.h"
13 #include "cc/scheduler/delay_based_time_source.h"
14 #include "cc/scheduler/scheduler.h"
15 #include "ui/gfx/frame_time.h"
17 #ifdef NDEBUG
18 #define DEBUG_FRAMES(...)
19 #else
20 #define DEBUG_FRAMES(name, arg1_name, arg1_val, arg2_name, arg2_val) \
21 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), \
22 name, \
23 arg1_name, \
24 arg1_val, \
25 arg2_name, \
26 arg2_val);
27 #endif
29 namespace cc {
31 // BeginFrameObserverMixIn -----------------------------------------------
32 BeginFrameObserverMixIn::BeginFrameObserverMixIn()
33 : last_begin_frame_args_(), dropped_begin_frame_args_(0) {
36 const BeginFrameArgs BeginFrameObserverMixIn::LastUsedBeginFrameArgs() const {
37 return last_begin_frame_args_;
39 void BeginFrameObserverMixIn::OnBeginFrame(const BeginFrameArgs& args) {
40 DEBUG_FRAMES("BeginFrameObserverMixIn::OnBeginFrame",
41 "last args",
42 last_begin_frame_args_.AsValue(),
43 "new args",
44 args.AsValue());
45 DCHECK(args.IsValid());
46 DCHECK(args.frame_time >= last_begin_frame_args_.frame_time);
47 bool used = OnBeginFrameMixInDelegate(args);
48 if (used) {
49 last_begin_frame_args_ = args;
50 } else {
51 ++dropped_begin_frame_args_;
55 void BeginFrameObserverMixIn::AsValueInto(
56 base::trace_event::TracedValue* dict) const {
57 dict->BeginDictionary("last_begin_frame_args_");
58 last_begin_frame_args_.AsValueInto(dict);
59 dict->EndDictionary();
60 dict->SetInteger("dropped_begin_frame_args_", dropped_begin_frame_args_);
63 // BeginFrameSourceMixIn ------------------------------------------------------
64 BeginFrameSourceMixIn::BeginFrameSourceMixIn()
65 : observer_(NULL),
66 needs_begin_frames_(false),
67 inside_as_value_into_(false) {
68 DCHECK(!observer_);
69 DCHECK_EQ(inside_as_value_into_, false);
72 bool BeginFrameSourceMixIn::NeedsBeginFrames() const {
73 return needs_begin_frames_;
76 void BeginFrameSourceMixIn::SetNeedsBeginFrames(bool needs_begin_frames) {
77 DEBUG_FRAMES("BeginFrameSourceMixIn::SetNeedsBeginFrames",
78 "current state",
79 needs_begin_frames_,
80 "new state",
81 needs_begin_frames);
82 if (needs_begin_frames_ != needs_begin_frames) {
83 needs_begin_frames_ = needs_begin_frames;
84 OnNeedsBeginFramesChange(needs_begin_frames);
88 void BeginFrameSourceMixIn::AddObserver(BeginFrameObserver* obs) {
89 DEBUG_FRAMES("BeginFrameSourceMixIn::AddObserver",
90 "current observer",
91 observer_,
92 "to add observer",
93 obs);
94 DCHECK(!observer_);
95 observer_ = obs;
98 void BeginFrameSourceMixIn::RemoveObserver(BeginFrameObserver* obs) {
99 DEBUG_FRAMES("BeginFrameSourceMixIn::RemoveObserver",
100 "current observer",
101 observer_,
102 "to remove observer",
103 obs);
104 DCHECK_EQ(observer_, obs);
105 observer_ = NULL;
108 void BeginFrameSourceMixIn::CallOnBeginFrame(const BeginFrameArgs& args) {
109 DEBUG_FRAMES("BeginFrameSourceMixIn::CallOnBeginFrame",
110 "current observer",
111 observer_,
112 "args",
113 args.AsValue());
114 if (observer_) {
115 return observer_->OnBeginFrame(args);
119 // Tracing support
120 void BeginFrameSourceMixIn::AsValueInto(
121 base::trace_event::TracedValue* dict) const {
122 // As the observer might try to trace the source, prevent an infinte loop
123 // from occuring.
124 if (inside_as_value_into_) {
125 dict->SetString("observer", "<loop detected>");
126 return;
129 if (observer_) {
130 base::AutoReset<bool> prevent_loops(
131 const_cast<bool*>(&inside_as_value_into_), true);
132 dict->BeginDictionary("observer");
133 observer_->AsValueInto(dict);
134 dict->EndDictionary();
135 } else {
136 dict->SetString("observer", "NULL");
138 dict->SetBoolean("needs_begin_frames", NeedsBeginFrames());
141 // BackToBackBeginFrameSourceMixIn --------------------------------------------
142 scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create(
143 base::SingleThreadTaskRunner* task_runner) {
144 return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner));
147 BackToBackBeginFrameSource::BackToBackBeginFrameSource(
148 base::SingleThreadTaskRunner* task_runner)
149 : BeginFrameSourceMixIn(),
150 task_runner_(task_runner),
151 send_begin_frame_posted_(false),
152 weak_factory_(this) {
153 DCHECK(task_runner);
154 DCHECK_EQ(needs_begin_frames_, false);
155 DCHECK_EQ(send_begin_frame_posted_, false);
158 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() {
161 base::TimeTicks BackToBackBeginFrameSource::Now() {
162 return gfx::FrameTime::Now();
165 void BackToBackBeginFrameSource::OnNeedsBeginFramesChange(
166 bool needs_begin_frames) {
167 if (!needs_begin_frames)
168 return;
170 if (send_begin_frame_posted_)
171 return;
173 send_begin_frame_posted_ = true;
174 task_runner_->PostTask(FROM_HERE,
175 base::Bind(&BackToBackBeginFrameSource::BeginFrame,
176 weak_factory_.GetWeakPtr()));
179 void BackToBackBeginFrameSource::BeginFrame() {
180 send_begin_frame_posted_ = false;
182 if (!needs_begin_frames_)
183 return;
185 base::TimeTicks now = Now();
186 BeginFrameArgs args = BeginFrameArgs::Create(
187 BEGINFRAME_FROM_HERE, now, now + BeginFrameArgs::DefaultInterval(),
188 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
189 CallOnBeginFrame(args);
192 // BeginFrameSource support
194 void BackToBackBeginFrameSource::DidFinishFrame(size_t remaining_frames) {
195 if (remaining_frames == 0) {
196 OnNeedsBeginFramesChange(NeedsBeginFrames());
200 // Tracing support
201 void BackToBackBeginFrameSource::AsValueInto(
202 base::trace_event::TracedValue* dict) const {
203 dict->SetString("type", "BackToBackBeginFrameSource");
204 BeginFrameSourceMixIn::AsValueInto(dict);
205 dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_);
208 // SyntheticBeginFrameSource ---------------------------------------------
209 scoped_ptr<SyntheticBeginFrameSource> SyntheticBeginFrameSource::Create(
210 base::SingleThreadTaskRunner* task_runner,
211 base::TimeTicks initial_vsync_timebase,
212 base::TimeDelta initial_vsync_interval) {
213 scoped_refptr<DelayBasedTimeSource> time_source;
214 if (gfx::FrameTime::TimestampsAreHighRes()) {
215 time_source = DelayBasedTimeSourceHighRes::Create(initial_vsync_interval,
216 task_runner);
217 } else {
218 time_source =
219 DelayBasedTimeSource::Create(initial_vsync_interval, task_runner);
222 return make_scoped_ptr(new SyntheticBeginFrameSource(time_source));
225 SyntheticBeginFrameSource::SyntheticBeginFrameSource(
226 scoped_refptr<DelayBasedTimeSource> time_source)
227 : BeginFrameSourceMixIn(), time_source_(time_source) {
228 time_source_->SetActive(false);
229 time_source_->SetClient(this);
232 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
233 if (NeedsBeginFrames())
234 time_source_->SetActive(false);
237 void SyntheticBeginFrameSource::OnUpdateVSyncParameters(
238 base::TimeTicks new_vsync_timebase,
239 base::TimeDelta new_vsync_interval) {
240 time_source_->SetTimebaseAndInterval(new_vsync_timebase, new_vsync_interval);
243 BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs(
244 base::TimeTicks frame_time,
245 BeginFrameArgs::BeginFrameArgsType type) {
246 base::TimeTicks deadline = time_source_->NextTickTime();
247 return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
248 time_source_->Interval(), type);
251 // TimeSourceClient support
252 void SyntheticBeginFrameSource::OnTimerTick() {
253 CallOnBeginFrame(CreateBeginFrameArgs(time_source_->LastTickTime(),
254 BeginFrameArgs::NORMAL));
257 // BeginFrameSourceMixIn support
258 void SyntheticBeginFrameSource::OnNeedsBeginFramesChange(
259 bool needs_begin_frames) {
260 base::TimeTicks missed_tick_time =
261 time_source_->SetActive(needs_begin_frames);
262 if (!missed_tick_time.is_null()) {
263 CallOnBeginFrame(
264 CreateBeginFrameArgs(missed_tick_time, BeginFrameArgs::MISSED));
268 // Tracing support
269 void SyntheticBeginFrameSource::AsValueInto(
270 base::trace_event::TracedValue* dict) const {
271 dict->SetString("type", "SyntheticBeginFrameSource");
272 BeginFrameSourceMixIn::AsValueInto(dict);
274 dict->BeginDictionary("time_source");
275 time_source_->AsValueInto(dict);
276 dict->EndDictionary();
279 // BeginFrameSourceMultiplexer -------------------------------------------
280 scoped_ptr<BeginFrameSourceMultiplexer> BeginFrameSourceMultiplexer::Create() {
281 return make_scoped_ptr(new BeginFrameSourceMultiplexer());
284 BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer()
285 : BeginFrameSourceMixIn(),
286 minimum_interval_(base::TimeDelta()),
287 active_source_(NULL),
288 source_list_() {
291 BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer(
292 base::TimeDelta minimum_interval)
293 : BeginFrameSourceMixIn(),
294 minimum_interval_(minimum_interval),
295 active_source_(NULL),
296 source_list_() {
299 BeginFrameSourceMultiplexer::~BeginFrameSourceMultiplexer() {
300 if (active_source_) {
301 active_source_->SetNeedsBeginFrames(false);
302 active_source_->RemoveObserver(this);
306 void BeginFrameSourceMultiplexer::SetMinimumInterval(
307 base::TimeDelta new_minimum_interval) {
308 DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetMinimumInterval",
309 "current minimum (us)",
310 minimum_interval_.InMicroseconds(),
311 "new minimum (us)",
312 new_minimum_interval.InMicroseconds());
313 DCHECK_GE(new_minimum_interval.ToInternalValue(), 0);
314 minimum_interval_ = new_minimum_interval;
317 void BeginFrameSourceMultiplexer::AddSource(BeginFrameSource* new_source) {
318 DEBUG_FRAMES("BeginFrameSourceMultiplexer::AddSource", "current active",
319 active_source_, "source to be added", new_source);
320 DCHECK(new_source);
321 DCHECK(!HasSource(new_source));
323 source_list_.insert(new_source);
325 // If there is no active source, set the new one as the active one.
326 if (!active_source_)
327 SetActiveSource(new_source);
330 void BeginFrameSourceMultiplexer::RemoveSource(
331 BeginFrameSource* existing_source) {
332 DEBUG_FRAMES("BeginFrameSourceMultiplexer::RemoveSource", "current active",
333 active_source_, "source to be removed", existing_source);
334 DCHECK(existing_source);
335 DCHECK(HasSource(existing_source));
336 DCHECK_NE(existing_source, active_source_);
337 source_list_.erase(existing_source);
340 void BeginFrameSourceMultiplexer::SetActiveSource(
341 BeginFrameSource* new_source) {
342 DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetActiveSource",
343 "current active",
344 active_source_,
345 "to become active",
346 new_source);
348 DCHECK(HasSource(new_source) || new_source == NULL);
350 bool needs_begin_frames = NeedsBeginFrames();
351 if (active_source_) {
352 if (needs_begin_frames)
353 SetNeedsBeginFrames(false);
355 // Technically we shouldn't need to remove observation, but this prevents
356 // the case where SetNeedsBeginFrames message gets to the source after a
357 // message has already been sent.
358 active_source_->RemoveObserver(this);
359 active_source_ = NULL;
361 DCHECK(!active_source_);
362 active_source_ = new_source;
364 if (active_source_) {
365 active_source_->AddObserver(this);
367 if (needs_begin_frames) {
368 SetNeedsBeginFrames(true);
373 const BeginFrameSource* BeginFrameSourceMultiplexer::ActiveSource() {
374 return active_source_;
377 // BeginFrameObserver support
378 void BeginFrameSourceMultiplexer::OnBeginFrame(const BeginFrameArgs& args) {
379 if (!IsIncreasing(args)) {
380 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame",
381 "action",
382 "discarding",
383 "new args",
384 args.AsValue());
385 return;
387 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame",
388 "action",
389 "using",
390 "new args",
391 args.AsValue());
392 CallOnBeginFrame(args);
395 const BeginFrameArgs BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs()
396 const {
397 if (observer_)
398 return observer_->LastUsedBeginFrameArgs();
399 else
400 return BeginFrameArgs();
403 // BeginFrameSource support
404 void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange(
405 bool needs_begin_frames) {
406 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange",
407 "active_source", active_source_, "needs_begin_frames",
408 needs_begin_frames);
409 if (active_source_) {
410 active_source_->SetNeedsBeginFrames(needs_begin_frames);
411 } else {
412 DCHECK(!needs_begin_frames);
416 void BeginFrameSourceMultiplexer::DidFinishFrame(size_t remaining_frames) {
417 DEBUG_FRAMES("BeginFrameSourceMultiplexer::DidFinishFrame",
418 "active_source",
419 active_source_,
420 "remaining_frames",
421 remaining_frames);
422 if (active_source_) {
423 active_source_->DidFinishFrame(remaining_frames);
427 // Tracing support
428 void BeginFrameSourceMultiplexer::AsValueInto(
429 base::trace_event::TracedValue* dict) const {
430 dict->SetString("type", "BeginFrameSourceMultiplexer");
432 dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds());
433 if (observer_) {
434 dict->BeginDictionary("last_begin_frame_args");
435 observer_->LastUsedBeginFrameArgs().AsValueInto(dict);
436 dict->EndDictionary();
439 if (active_source_) {
440 dict->BeginDictionary("active_source");
441 active_source_->AsValueInto(dict);
442 dict->EndDictionary();
443 } else {
444 dict->SetString("active_source", "NULL");
447 dict->BeginArray("sources");
448 for (std::set<BeginFrameSource*>::const_iterator it = source_list_.begin();
449 it != source_list_.end();
450 ++it) {
451 dict->BeginDictionary();
452 (*it)->AsValueInto(dict);
453 dict->EndDictionary();
455 dict->EndArray();
458 // protected methods
459 bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) {
460 return (source_list_.find(source) != source_list_.end());
463 bool BeginFrameSourceMultiplexer::IsIncreasing(const BeginFrameArgs& args) {
464 DCHECK(args.IsValid());
465 if (!observer_)
466 return false;
468 // If the last begin frame is invalid, then any new begin frame is valid.
469 if (!observer_->LastUsedBeginFrameArgs().IsValid())
470 return true;
472 // Only allow new args have a *strictly bigger* frame_time value and statisfy
473 // minimum interval requirement.
474 return (args.frame_time >=
475 observer_->LastUsedBeginFrameArgs().frame_time + minimum_interval_);
478 } // namespace cc