Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/debug/trace_event.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "cc/scheduler/delay_based_time_source.h" | |
|
simonhong
2014/06/12 13:47:39
All above includes are duplicated with frame_sourc
| |
| 10 #include "cc/scheduler/scheduler.h" | |
|
simonhong
2014/06/12 13:47:39
Scheduler class is not referenced in this file.
Ca
| |
| 11 #include "ui/gfx/frame_time.h" | |
|
simonhong
2014/06/12 13:47:38
ditto.
| |
| 12 | |
| 13 #define FRAMESOURCE_TYPESTRING(x) \ | |
| 14 std::string x::TypeString() const { return #x; } | |
| 15 | |
| 16 namespace cc { | |
| 17 | |
| 18 BaseBeginFrameSource::BaseBeginFrameSource(BeginFrameSink* sink) | |
| 19 : frame_sink_(sink), | |
| 20 generate_frames_(false), | |
| 21 timebase_(), | |
|
simonhong
2014/06/12 13:47:39
can be removed.
| |
| 22 interval_(BeginFrameArgs::DefaultInterval()) { | |
| 23 } | |
| 24 | |
| 25 // BeginFrameSource ------------------------------------------------------ | |
| 26 void BaseBeginFrameSource::SetBeginFrameSink(BeginFrameSink* sink) { | |
| 27 DCHECK(sink); | |
| 28 frame_sink_ = sink; | |
| 29 } | |
| 30 BeginFrameSink* BaseBeginFrameSource::GetBeginFrameSink() const { | |
| 31 DCHECK(frame_sink_); | |
| 32 return frame_sink_; | |
| 33 } | |
| 34 | |
| 35 void BaseBeginFrameSource::SetGenerateFrames(bool generate_frames) { | |
| 36 if (generate_frames_ != generate_frames) { | |
| 37 OnGenerateChange(generate_frames); | |
| 38 generate_frames_ = generate_frames; | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 bool BaseBeginFrameSource::IsGeneratingFrames() const { | |
| 43 return generate_frames_; | |
| 44 } | |
| 45 | |
| 46 void BaseBeginFrameSource::PendingFrames(size_t count) { | |
| 47 OnPendingFrames(count); | |
| 48 } | |
| 49 | |
| 50 void BaseBeginFrameSource::SetTimeBaseAndInterval( | |
| 51 const base::TimeTicks timebase, | |
| 52 const base::TimeDelta interval) { | |
| 53 base::TimeDelta newinterval = interval; | |
| 54 if (newinterval == base::TimeDelta()) | |
| 55 newinterval = BeginFrameArgs::DefaultInterval(); | |
| 56 | |
| 57 OnTimeBaseAndIntervalChange(timebase, newinterval); | |
| 58 | |
| 59 timebase_ = timebase; | |
| 60 interval_ = newinterval; | |
| 61 } | |
| 62 | |
| 63 base::TimeTicks BaseBeginFrameSource::TimeBase() const { | |
| 64 return timebase_; | |
| 65 } | |
| 66 | |
| 67 base::TimeDelta BaseBeginFrameSource::Interval() const { | |
| 68 return interval_; | |
| 69 } | |
| 70 | |
| 71 scoped_ptr<base::Value> BaseBeginFrameSource::BeginFrameSourceAsValue() const { | |
| 72 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | |
| 73 state->SetString("type", TypeString()); | |
| 74 state->SetInteger("frame_source", reinterpret_cast<size_t>(this)); | |
| 75 state->SetBoolean("generate_frames", generate_frames_); | |
| 76 state->SetDouble("timebase_us", timebase_.ToInternalValue()); | |
| 77 state->SetDouble("interval_us", interval_.InMicroseconds()); | |
| 78 | |
| 79 ExtraAsValue(state.get()); | |
| 80 | |
| 81 return state.PassAs<base::Value>(); | |
| 82 } | |
| 83 | |
| 84 /************************************************************************* | |
| 85 * | |
| 86 */ | |
| 87 ProxyBeginFrameSource::ProxyBeginFrameSource(BeginFrameSink* sink, | |
| 88 BeginFrameSource* source) | |
| 89 : BaseBeginFrameSource(sink), source_(source) { | |
| 90 DCHECK(source_); | |
| 91 source_->SetBeginFrameSink(this); | |
| 92 } | |
| 93 | |
| 94 // BeginFrameSink -------------------------------------------------------- | |
| 95 void ProxyBeginFrameSource::BeginFrame(const BeginFrameArgs& args) { | |
| 96 frame_sink_->BeginFrame(args); | |
| 97 } | |
| 98 | |
| 99 // BaseBeginFrameSource --------------------------------------------------- | |
| 100 | |
| 101 FRAMESOURCE_TYPESTRING(ProxyBeginFrameSource); | |
| 102 | |
| 103 void ProxyBeginFrameSource::ExtraAsValue(base::DictionaryValue* state) const { | |
| 104 state->Set("source", source_->BeginFrameSourceAsValue().release()); | |
| 105 } | |
| 106 | |
| 107 void ProxyBeginFrameSource::OnGenerateChange(bool generate_frames) { | |
| 108 DCHECK(source_); | |
|
simonhong
2014/06/12 13:47:39
DCHECK can be removed because we don't erase or ch
| |
| 109 source_->SetGenerateFrames(generate_frames); | |
| 110 } | |
| 111 | |
| 112 void ProxyBeginFrameSource::OnPendingFrames(size_t count) { | |
| 113 DCHECK(source_); | |
|
simonhong
2014/06/12 13:47:39
ditto.
| |
| 114 source_->PendingFrames(count); | |
| 115 } | |
| 116 | |
| 117 void ProxyBeginFrameSource::OnTimeBaseAndIntervalChange( | |
| 118 const base::TimeTicks timebase, | |
| 119 const base::TimeDelta interval) { | |
| 120 DCHECK(source_); | |
|
simonhong
2014/06/12 13:47:39
ditto.
| |
| 121 source_->SetTimeBaseAndInterval(timebase, interval); | |
| 122 } | |
| 123 | |
| 124 /************************************************************************* | |
| 125 * | |
| 126 */ | |
| 127 ThrottledBeginFrameSource::ThrottledBeginFrameSource(BeginFrameSink* sink, | |
| 128 BeginFrameSource* source, | |
| 129 base::TimeDelta interval) | |
| 130 : ProxyBeginFrameSource(sink, source), last_frame_args_() { | |
| 131 interval_ = interval; | |
| 132 } | |
| 133 | |
| 134 // BeginFrameSink -------------------------------------------------------- | |
| 135 void ThrottledBeginFrameSource::BeginFrame(const BeginFrameArgs& args) { | |
| 136 if (last_frame_args_.IsValid() && | |
| 137 last_frame_args_.frame_time + interval_ > args.frame_time) | |
| 138 return; | |
| 139 last_frame_args_ = args; | |
| 140 frame_sink_->BeginFrame(args); | |
| 141 } | |
| 142 | |
| 143 // BeginFrameSource ------------------------------------------------------ | |
| 144 | |
| 145 FRAMESOURCE_TYPESTRING(ThrottledBeginFrameSource) | |
| 146 | |
| 147 void ThrottledBeginFrameSource::ExtraAsValue( | |
| 148 base::DictionaryValue* state) const { | |
| 149 state->Set("source", source_->BeginFrameSourceAsValue().release()); | |
| 150 state->Set("last_frame_args", last_frame_args_.AsValue().release()); | |
| 151 } | |
| 152 | |
| 153 /*************************************************************************/ | |
| 154 BackToBackBeginFrameSource::BackToBackBeginFrameSource( | |
| 155 BeginFrameSink* sink, | |
| 156 base::SingleThreadTaskRunner* task_runner) | |
| 157 : BaseBeginFrameSource(sink), | |
| 158 weak_factory_(this), | |
| 159 task_runner_(task_runner), | |
| 160 send_begin_frame_posted_(false) { | |
| 161 DCHECK(task_runner); | |
| 162 } | |
| 163 | |
| 164 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() { | |
| 165 } | |
| 166 | |
| 167 void BackToBackBeginFrameSource::ScheduleSendBeginFrameArgs() { | |
| 168 if (!generate_frames_) | |
| 169 return; | |
| 170 | |
| 171 if (send_begin_frame_posted_) | |
| 172 return; | |
| 173 | |
| 174 send_begin_frame_posted_ = true; | |
| 175 task_runner_->PostTask( | |
| 176 FROM_HERE, | |
| 177 base::Bind(&BackToBackBeginFrameSource::SendBeginFrameArgs, | |
| 178 weak_factory_.GetWeakPtr())); | |
| 179 } | |
| 180 | |
| 181 void BackToBackBeginFrameSource::SendBeginFrameArgs() { | |
| 182 send_begin_frame_posted_ = false; | |
| 183 | |
| 184 // TODO(mithro): Fix the tests so this can be enabled. The tests currently | |
| 185 // depend on one begin frame firing after generate_frames_ is set false. | |
| 186 // if (!generate_frames_) { | |
| 187 // return; | |
| 188 // } | |
| 189 | |
| 190 base::TimeTicks now = gfx::FrameTime::Now(); | |
| 191 // TODO(mithro): Is a deadline of now+interval_ sane? | |
| 192 BeginFrameArgs args = BeginFrameArgs::Create(now, now + interval_, interval_); | |
| 193 frame_sink_->BeginFrame(args); | |
| 194 } | |
| 195 | |
| 196 // BeginFrameSource ------------------------------------------------------ | |
| 197 | |
| 198 FRAMESOURCE_TYPESTRING(BackToBackBeginFrameSource); | |
| 199 | |
| 200 void BackToBackBeginFrameSource::ExtraAsValue( | |
| 201 base::DictionaryValue* state) const { | |
| 202 state->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_); | |
| 203 } | |
| 204 | |
| 205 void BackToBackBeginFrameSource::OnGenerateChange(bool generate_frames) { | |
| 206 ScheduleSendBeginFrameArgs(); | |
| 207 } | |
| 208 | |
| 209 void BackToBackBeginFrameSource::OnPendingFrames(size_t count) { | |
| 210 if (count == 0) { | |
| 211 ScheduleSendBeginFrameArgs(); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 /*************************************************************************/ | |
| 216 SyntheticBeginFrameSource::SyntheticBeginFrameSource( | |
| 217 BeginFrameSink* sink, | |
| 218 base::SingleThreadTaskRunner* task_runner, | |
| 219 base::TimeDelta interval) | |
| 220 : BaseBeginFrameSource(sink), task_runner_(task_runner) { | |
| 221 DCHECK(task_runner); | |
| 222 interval_ = interval; | |
| 223 if (gfx::FrameTime::TimestampsAreHighRes()) { | |
| 224 time_source_ = DelayBasedTimeSourceHighRes::Create(interval_, task_runner); | |
| 225 } else { | |
| 226 time_source_ = DelayBasedTimeSource::Create(interval_, task_runner); | |
| 227 } | |
| 228 time_source_->SetActive(false); | |
|
simonhong
2014/06/12 13:47:39
time_source_ is set to inactive when it is initial
| |
| 229 time_source_->SetClient(this); | |
| 230 } | |
| 231 | |
| 232 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { | |
| 233 time_source_->SetActive(false); | |
| 234 } | |
| 235 | |
| 236 BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs( | |
| 237 base::TimeTicks frame_time) { | |
| 238 base::TimeTicks deadline = time_source_->NextTickTime(); | |
| 239 return BeginFrameArgs::Create(frame_time, deadline, interval_); | |
| 240 } | |
| 241 | |
| 242 // TimeSourceClient ------------------------------------------------------ | |
| 243 | |
| 244 void SyntheticBeginFrameSource::OnTimerTick() { | |
| 245 frame_sink_->BeginFrame(CreateBeginFrameArgs(time_source_->LastTickTime())); | |
| 246 } | |
| 247 | |
| 248 // BeginFrameSource ------------------------------------------------------ | |
| 249 | |
| 250 FRAMESOURCE_TYPESTRING(SyntheticBeginFrameSource); | |
| 251 | |
| 252 void SyntheticBeginFrameSource::ExtraAsValue( | |
| 253 base::DictionaryValue* state) const { | |
| 254 state->Set("time_source", time_source_->AsValue().release()); | |
| 255 } | |
| 256 | |
| 257 void SyntheticBeginFrameSource::OnGenerateChange(bool generate_frames) { | |
| 258 base::TimeTicks missed_tick_time = time_source_->SetActive(generate_frames); | |
| 259 if (!missed_tick_time.is_null()) { | |
|
simonhong
2014/06/12 13:47:38
Generally, curly braces are not required for singl
| |
| 260 frame_sink_->BeginFrame(CreateBeginFrameArgs(missed_tick_time)); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 void SyntheticBeginFrameSource::OnTimeBaseAndIntervalChange( | |
| 265 const base::TimeTicks timebase, | |
| 266 const base::TimeDelta interval) { | |
| 267 time_source_->SetTimebaseAndInterval(timebase, interval); | |
| 268 } | |
| 269 | |
| 270 /************************************************************************* | |
| 271 * A virtual frame source which lets you switch between two other frame sources | |
| 272 * (making sure the BeginFrameArgs stays monotonic). | |
| 273 */ | |
| 274 DualBeginFrameSource::DualBeginFrameSource( | |
| 275 BeginFrameSink* sink, | |
| 276 scoped_ptr<BeginFrameSource> source_primary, | |
| 277 scoped_ptr<BeginFrameSource> source_secondary) | |
| 278 : BaseBeginFrameSource(sink), | |
| 279 last_frame_args_(), | |
| 280 source_foreground_(source_primary.Pass()), | |
| 281 source_background_(source_secondary.Pass()) { | |
| 282 source_foreground_->SetBeginFrameSink(this); | |
| 283 source_background_->SetBeginFrameSink(this); | |
| 284 SwitchSource(SourceForeground()); | |
| 285 } | |
| 286 | |
| 287 DualBeginFrameSource::~DualBeginFrameSource() { | |
| 288 } | |
| 289 | |
| 290 void DualBeginFrameSource::SwitchSource(const BeginFrameSource* new_source) { | |
| 291 DCHECK(new_source == SourceForeground() || new_source == SourceBackground()); | |
| 292 | |
| 293 if (generate_frames_) | |
| 294 active_source_->SetGenerateFrames(false); | |
| 295 | |
| 296 active_source_ = const_cast<BeginFrameSource*>(new_source); | |
| 297 | |
| 298 if (generate_frames_) | |
| 299 active_source_->SetGenerateFrames(true); | |
| 300 } | |
| 301 | |
| 302 const BeginFrameSource* DualBeginFrameSource::SourceForeground() const { | |
| 303 return source_foreground_.get(); | |
| 304 } | |
| 305 | |
| 306 const BeginFrameSource* DualBeginFrameSource::SourceBackground() const { | |
| 307 return source_background_.get(); | |
| 308 } | |
| 309 | |
| 310 // BeginFrameSink ------------------------------------------------------ | |
| 311 | |
| 312 void DualBeginFrameSource::BeginFrame(const BeginFrameArgs& args) { | |
| 313 // When switching clock sources you can get a BeginFrameArgs with a | |
| 314 // frame_time before the last value. | |
| 315 BeginFrameArgs new_args = args; | |
| 316 if (last_frame_args_.frame_time > new_args.frame_time) | |
| 317 return; | |
| 318 | |
| 319 last_frame_args_ = new_args; | |
| 320 frame_sink_->BeginFrame(new_args); | |
| 321 } | |
| 322 | |
| 323 // BeginFrameSource ---------------------------------------------------- | |
| 324 | |
| 325 FRAMESOURCE_TYPESTRING(DualBeginFrameSource) | |
| 326 | |
| 327 void DualBeginFrameSource::ExtraAsValue(base::DictionaryValue* state) const { | |
| 328 state->Set("last_frame_args", last_frame_args_.AsValue().release()); | |
| 329 if (active_source_ == SourceForeground()) | |
| 330 state->SetString("active", "primary"); | |
| 331 if (active_source_ == SourceBackground()) | |
| 332 state->SetString("active", "secondary"); | |
| 333 state->Set("primary", | |
| 334 source_foreground_->BeginFrameSourceAsValue().release()); | |
| 335 state->Set("secondary", | |
| 336 source_background_->BeginFrameSourceAsValue().release()); | |
| 337 } | |
| 338 | |
| 339 void DualBeginFrameSource::OnPendingFrames(size_t count) { | |
| 340 active_source_->PendingFrames(count); | |
| 341 } | |
| 342 | |
| 343 void DualBeginFrameSource::OnGenerateChange(bool generate_frames) { | |
| 344 DCHECK(active_source_); | |
| 345 active_source_->SetGenerateFrames(generate_frames); | |
| 346 } | |
| 347 | |
| 348 void DualBeginFrameSource::OnTimeBaseAndIntervalChange( | |
| 349 const base::TimeTicks timebase, | |
| 350 const base::TimeDelta interval) { | |
| 351 DCHECK_EQ(active_source_, source_foreground_); // TODO(mithro): Is this okay? | |
| 352 source_foreground_->SetTimeBaseAndInterval(timebase, interval); | |
| 353 } | |
| 354 | |
| 355 } // namespace cc | |
| OLD | NEW |