Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: cc/scheduler/frame_source.cc

Issue 267783004: Refactoring the way begin frame sources inside scheduler work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing as per Brian's comments. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "cc/scheduler/frame_source.h"
6
7 #include "base/auto_reset.h"
8 #include "base/debug/trace_event.h"
9 #include "base/debug/trace_event_argument.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "cc/scheduler/delay_based_time_source.h"
13 #include "cc/scheduler/scheduler.h"
14 #include "ui/gfx/frame_time.h"
15
16 namespace cc {
17
18 BeginFrameSource::BeginFrameSource()
19 : observer_(NULL), inside_as_value_into_(false) {
20 DCHECK(!observer_);
21 DCHECK_EQ(inside_as_value_into_, false);
22 }
23
24 void BeginFrameSource::AddObserver(BeginFrameObserver* obs) {
25 DCHECK(!observer_);
26 observer_ = obs;
27 }
28
29 void BeginFrameSource::RemoveObserver(BeginFrameObserver* obs) {
30 DCHECK_EQ(observer_, obs);
31 observer_ = NULL;
32 }
33
34 void BeginFrameSource::CallOnBeginFrame(const BeginFrameArgs& args) {
35 if (observer_) {
36 observer_->OnBeginFrame(args);
37 }
38 }
39
40 // Tracing support
41 void BeginFrameSource::AsValueInto(base::debug::TracedValue* dict) const {
42 // As the observer might try to trace the source, prevent an infinte loop
43 // from occuring.
44 if (inside_as_value_into_) {
45 dict->SetString("observer", "<loop detected>");
46 return;
47 }
48
49 if (observer_) {
50 base::AutoReset<bool> prevent_loops(
51 const_cast<bool*>(&inside_as_value_into_), true);
52 dict->BeginDictionary("observer");
53 observer_->AsValueInto(dict);
54 dict->EndDictionary();
55 } else {
56 dict->SetString("observer", "NULL");
57 }
58 }
59
60 /*************************************************************************/
61 scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create(
62 base::SingleThreadTaskRunner* task_runner) {
63 return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner));
64 }
65
66 BackToBackBeginFrameSource::BackToBackBeginFrameSource(
67 base::SingleThreadTaskRunner* task_runner)
68 : BeginFrameSource(),
69 weak_factory_(this),
70 task_runner_(task_runner),
71 needs_begin_frames_(false),
72 send_begin_frame_posted_(false) {
73 DCHECK(task_runner);
74 DCHECK_EQ(needs_begin_frames_, false);
75 DCHECK_EQ(send_begin_frame_posted_, false);
76 }
77
78 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() {
79 }
80
81 base::TimeTicks BackToBackBeginFrameSource::Now() {
82 return gfx::FrameTime::Now();
83 }
84
85 void BackToBackBeginFrameSource::ScheduleBeginFrame() {
86 if (!needs_begin_frames_)
87 return;
88
89 if (send_begin_frame_posted_)
90 return;
91
92 send_begin_frame_posted_ = true;
93 task_runner_->PostTask(FROM_HERE,
94 base::Bind(&BackToBackBeginFrameSource::BeginFrame,
95 weak_factory_.GetWeakPtr()));
96 }
97
98 void BackToBackBeginFrameSource::BeginFrame() {
99 send_begin_frame_posted_ = false;
100
101 if (!needs_begin_frames_) {
102 return;
103 }
104
105 base::TimeTicks now = Now();
106 BeginFrameArgs args =
107 BeginFrameArgs::Create(now,
108 now + BeginFrameArgs::DefaultInterval(),
109 BeginFrameArgs::DefaultInterval());
110 CallOnBeginFrame(args);
111 }
112
113 // BeginFrameSource ------------------------------------------------------
114 bool BackToBackBeginFrameSource::NeedsBeginFrames() const {
115 return needs_begin_frames_;
116 }
117
118 void BackToBackBeginFrameSource::SetNeedsBeginFrames(bool needs_begin_frames) {
119 needs_begin_frames_ = needs_begin_frames;
120 ScheduleBeginFrame();
121 }
122
123 void BackToBackBeginFrameSource::DidFinishFrame(size_t remaining_frames) {
124 if (remaining_frames == 0) {
125 ScheduleBeginFrame();
126 }
127 }
128
129 // Tracing
130 void BackToBackBeginFrameSource::AsValueInto(
131 base::debug::TracedValue* dict) const {
132 dict->SetString("type", "BackToBackBeginFrameSource");
133 BeginFrameSource::AsValueInto(dict);
134 dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_);
135 dict->SetBoolean("needs_begin_frames", needs_begin_frames_);
136 }
137
138 /*************************************************************************/
139
140 scoped_ptr<SyntheticBeginFrameSource> SyntheticBeginFrameSource::Create(
141 base::SingleThreadTaskRunner* task_runner,
142 base::TimeTicks initial_vsync_timebase,
143 base::TimeDelta initial_vsync_interval) {
144 scoped_refptr<DelayBasedTimeSource> time_source;
145 if (gfx::FrameTime::TimestampsAreHighRes()) {
146 time_source = DelayBasedTimeSourceHighRes::Create(initial_vsync_interval,
147 task_runner);
148 } else {
149 time_source =
150 DelayBasedTimeSource::Create(initial_vsync_interval, task_runner);
151 }
152
153 return make_scoped_ptr(new SyntheticBeginFrameSource(time_source));
154 }
155
156 SyntheticBeginFrameSource::SyntheticBeginFrameSource(
157 scoped_refptr<DelayBasedTimeSource> time_source)
158 : BeginFrameSource(), time_source_(time_source) {
159 time_source_->SetActive(false);
160 time_source_->SetClient(this);
161 }
162
163 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
164 if (NeedsBeginFrames())
165 time_source_->SetActive(false);
166 }
167
168 void SyntheticBeginFrameSource::OnUpdateVSyncParameters(
169 base::TimeTicks new_vsync_timebase,
170 base::TimeDelta new_vsync_interval) {
171 time_source_->SetTimebaseAndInterval(new_vsync_timebase, new_vsync_interval);
172 }
173
174 void SyntheticBeginFrameSource::SendBeginFrameFromTick(
175 base::TimeTicks frame_time) {
176 base::TimeTicks deadline = time_source_->NextTickTime();
177 CallOnBeginFrame(
178 BeginFrameArgs::Create(frame_time, deadline, time_source_->Interval()));
179 }
180
181 // TimeSourceClient
182 void SyntheticBeginFrameSource::OnTimerTick() {
183 SendBeginFrameFromTick(time_source_->LastTickTime());
184 }
185
186 // BeginFrameSource
187 void SyntheticBeginFrameSource::SetNeedsBeginFrames(bool needs_begin_frames) {
188 if (needs_begin_frames == NeedsBeginFrames())
189 return;
190
191 base::TimeTicks missed_tick_time =
192 time_source_->SetActive(needs_begin_frames);
193 if (!missed_tick_time.is_null()) {
194 SendBeginFrameFromTick(missed_tick_time);
195 }
196 }
197
198 bool SyntheticBeginFrameSource::NeedsBeginFrames() const {
199 return time_source_->Active();
200 }
201
202 // Tracing
203 void SyntheticBeginFrameSource::AsValueInto(
204 base::debug::TracedValue* dict) const {
205 dict->SetString("type", "SyntheticBeginFrameSource");
206 BeginFrameSource::AsValueInto(dict);
207
208 dict->BeginDictionary("last_frame_args");
209 time_source_->AsValueInto(dict);
210 dict->EndDictionary();
211 }
212
213 /*************************************************************************/
214
215 scoped_ptr<BeginFrameSourceMultiplexer> BeginFrameSourceMultiplexer::Create() {
216 return make_scoped_ptr(new BeginFrameSourceMultiplexer());
217 }
218
219 BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer()
220 : BeginFrameSource(),
221 minimum_interval_(base::TimeDelta()),
222 active_source_(NULL),
223 source_list_() {
224 }
225
226 BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer(
227 base::TimeDelta minimum_interval)
228 : BeginFrameSource(),
229 minimum_interval_(minimum_interval),
230 active_source_(NULL),
231 source_list_() {
232 }
233
234 BeginFrameSourceMultiplexer::~BeginFrameSourceMultiplexer() {
235 }
236
237 void BeginFrameSourceMultiplexer::SetActiveSource(
238 BeginFrameSource* new_source) {
239 DCHECK(HasSource(new_source) || new_source == NULL);
240
241 bool needs_begin_frames = NeedsBeginFrames();
242 if (active_source_) {
243 if (needs_begin_frames)
244 SetNeedsBeginFrames(false);
245
246 // Technically we shouldn't need to remove observation, but this prevents
247 // the case where SetNeedsBeginFrames message gets to the source after a
248 // message has already been sent.
249 active_source_->RemoveObserver(this);
250 active_source_ = NULL;
251 }
252 DCHECK(!active_source_);
253 active_source_ = new_source;
254
255 if (active_source_) {
256 active_source_->AddObserver(this);
257
258 if (needs_begin_frames) {
259 SetNeedsBeginFrames(true);
260 }
261 }
262 }
263
264 const BeginFrameSource* BeginFrameSourceMultiplexer::ActiveSource() {
265 return active_source_;
266 }
267
268 bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) {
269 return (source_list_.find(source) != source_list_.end());
270 }
271
272 // ThrottledBeginFrameSource
273 void BeginFrameSourceMultiplexer::AddSource(BeginFrameSource* new_source) {
274 DCHECK(new_source);
275 DCHECK(!HasSource(new_source));
276
277 source_list_.insert(new_source);
278
279 // If there is no active source, set the new one as the active one.
280 if (!active_source_)
281 SetActiveSource(new_source);
282 }
283
284 void BeginFrameSourceMultiplexer::RemoveSource(
285 BeginFrameSource* existing_source) {
286 DCHECK(existing_source);
287 DCHECK(HasSource(existing_source));
288 DCHECK_NE(existing_source, active_source_);
289 source_list_.erase(existing_source);
290 }
291
292 void BeginFrameSourceMultiplexer::SetMinimumInterval(
293 base::TimeDelta new_minimum_interval) {
294 DCHECK_GE(new_minimum_interval.ToInternalValue(), 0);
295 minimum_interval_ = new_minimum_interval;
296 }
297
298 // BeginFrameObserver
299 void BeginFrameSourceMultiplexer::OnBeginFrame(const BeginFrameArgs& args) {
300 if (!observer_)
301 return;
302
303 if (observer_->LastBeginFrameArgs().IsValid() &&
304 observer_->LastBeginFrameArgs().frame_time + minimum_interval_ >
305 args.frame_time)
306 return;
307 CallOnBeginFrame(args);
308 }
309
310 const BeginFrameArgs& BeginFrameSourceMultiplexer::LastBeginFrameArgs() const {
311 return observer_->LastBeginFrameArgs();
312 }
313
314 // BeginFrameSource
315 bool BeginFrameSourceMultiplexer::NeedsBeginFrames() const {
316 if (active_source_) {
317 return active_source_->NeedsBeginFrames();
318 } else {
319 return false;
320 }
321 }
322
323 void BeginFrameSourceMultiplexer::SetNeedsBeginFrames(bool needs_begin_frames) {
324 if (active_source_) {
325 active_source_->SetNeedsBeginFrames(needs_begin_frames);
326 } else {
327 DCHECK(!needs_begin_frames);
328 }
329 }
330
331 void BeginFrameSourceMultiplexer::DidFinishFrame(size_t remaining_frames) {
332 active_source_->DidFinishFrame(remaining_frames);
333 }
334
335 // Tracing
336 void BeginFrameSourceMultiplexer::AsValueInto(
337 base::debug::TracedValue* dict) const {
338 dict->SetString("type", "BeginFrameSourceMultiplexer");
339
340 dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds());
341 if (observer_) {
342 dict->BeginDictionary("last_begin_frame_args");
343 observer_->LastBeginFrameArgs().AsValueInto(dict);
344 dict->EndDictionary();
345 }
346
347 if (active_source_) {
348 dict->BeginDictionary("active_source");
349 active_source_->AsValueInto(dict);
350 dict->EndDictionary();
351 } else {
352 dict->SetString("active_source", "NULL");
353 }
354
355 for (std::set<BeginFrameSource*>::const_iterator it = source_list_.begin();
356 it != source_list_.end();
357 ++it) {
358 dict->BeginDictionary(
359 base::SizeTToString(std::distance(source_list_.begin(), it)).c_str());
360 (*it)->AsValueInto(dict);
361 dict->EndDictionary();
362 }
363 }
364
365 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698