Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 #include "cc/scheduler/scheduler.h" | |
| 6 | |
| 7 #include "base/debug/trace_event.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "cc/scheduler/delay_based_time_source.h" | |
| 10 #include "ui/gfx/frame_time.h" | |
| 11 | |
| 12 namespace cc { | |
| 13 | |
| 14 class FrameSink { | |
| 15 public: | |
| 16 virtual void BeginFrame(BeginFrameArgs* args) = 0; | |
| 17 }; | |
| 18 | |
| 19 class FrameSource { | |
| 20 public: | |
| 21 FrameSource(FrameSink* sink) : sink_(sink) {} | |
| 22 virtual ~FrameSource() {} | |
| 23 | |
| 24 virtual void SetSink(FrameSink* sink) { sink_ = sink; } | |
| 25 | |
| 26 virtual void SendBeginFrame(BeginFrameArgs* args) { | |
| 27 DCHECK(sink_); | |
| 28 DCHECK(args); | |
| 29 sink_->BeginFrame(args); | |
| 30 } | |
| 31 | |
| 32 virtual void SetNeedsBeginFrame(bool needs_begin_frame) = 0; | |
| 33 | |
| 34 virtual void UpdateFrameSource(base::TimeTicks timebase, | |
| 35 base::TimeDelta interval) { | |
| 36 if (!interval.is_null()) | |
| 37 interval_ = interval; | |
| 38 } | |
| 39 | |
| 40 virtual scoped_ptr<base::Value> AsValue() const { | |
| 41 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | |
| 42 state->SetString("type", GetType()); | |
| 43 state->SetInteger("frame_source", this); | |
| 44 state->SetInteger("interval_us", interval_.InMicroseconds()); | |
| 45 return state.PassAs<base::Value>(); | |
| 46 } | |
| 47 | |
| 48 protected: | |
| 49 virtual std::string GetType() const = 0; | |
| 50 | |
| 51 base::TimeDelta interval_; | |
| 52 FrameSink* sink_; | |
| 53 }; | |
| 54 | |
| 55 /** | |
| 56 * A frame source which proxies BeginFrame from an external OutputSurface such | |
| 57 * as on Android. | |
| 58 */ | |
| 59 class ExternalFrameSource : public FrameSource { | |
| 60 public: | |
| 61 ExternalFrameSource(FrameSink* sink, SchedulerClient* client) | |
| 62 : client_(client), FrameSource(sink) { | |
| 63 DCHECK(client_); | |
| 64 } | |
| 65 virtual ~ExternalFrameSource() {} | |
| 66 | |
| 67 virtual void BeginFrame(BeginFrameArgs* args) { sink_->BeginFrame(args); } | |
| 68 | |
| 69 virtual void SetNeedsBeginFrame(bool needs_begin_frame) OVERRIDE { | |
| 70 DCHECK(client_); | |
| 71 client_->SetNeedsBeginFrame(needs_begin_frame); | |
| 72 } | |
| 73 | |
| 74 virtual scoped_ptr<base::Value> AsValue() const OVERRIDE { | |
| 75 scoped_ptr<base::DictionaryValue> state = FrameSource::AsValue(); | |
| 76 state->SetInteger("client", client_); | |
| 77 return state.PassAs<base::Value>(); | |
| 78 } | |
| 79 | |
| 80 protected: | |
| 81 virtual std::string GetType() const OVERRIDE { return "ExternalFrameSource"; } | |
| 82 | |
| 83 private: | |
| 84 SchedulerClient* client_; | |
| 85 }; | |
| 86 | |
| 87 /** | |
| 88 * A frame source which throttles down another begin frame source. | |
| 89 */ | |
| 90 class ThrottledFrameSource : public FrameSource, FrameSink { | |
|
brianderson
2014/05/05 16:50:05
In what cases would this class be used? Is this to
mithro-old
2014/05/05 17:10:53
Yes, examples I can think of are;
* Throttle an E
brianderson
2014/05/05 17:37:49
Cool. What would the interface look like to change
| |
| 91 public: | |
| 92 ThrottledFrameSource(FrameSink* sink, | |
| 93 const scoped_refptr<FrameSource>& source, | |
| 94 base::TimeDelta interval) | |
| 95 : source_(source), | |
| 96 interval_(interval), | |
| 97 last_frame_args_(), | |
| 98 FrameSource(sink) { | |
| 99 source_->SetSink(this); | |
| 100 } | |
| 101 virtual ~ThrottledFrameSource() {} | |
| 102 | |
| 103 virtual void BeginFrame(BeginFrameArgs* args) OVERRIDE { | |
| 104 if (last_frame_args_.frame_time + interval_ > args.frame_time) | |
| 105 return; | |
| 106 source_->SendBeginFrame(sink, args); | |
| 107 } | |
| 108 | |
| 109 virtual void SetNeedsBeginFrame(bool needs_begin_frame) OVERRIDE { | |
| 110 source_->SetNeedsBeginFrame(needs_begin_frame); | |
| 111 } | |
| 112 | |
| 113 virtual scoped_ptr<base::Value> AsValue() const OVERRIDE { | |
| 114 scoped_ptr<base::DictionaryValue> state = FrameSource::AsValue(); | |
| 115 state->SetValue("source", source_->AsValue().release()); | |
| 116 return state.PassAs<base::Value>(); | |
| 117 } | |
| 118 | |
| 119 protected: | |
| 120 virtual std::string GetType() const OVERRIDE { | |
| 121 return "ThrottledFrameSource"; | |
| 122 } | |
| 123 | |
| 124 private: | |
| 125 BeginFrameArgs last_frame_args_; | |
| 126 scoped_refptr<base::FrameSource> source_; | |
| 127 }; | |
| 128 | |
| 129 /** | |
| 130 * Frame source which needs a task runner object. | |
| 131 */ | |
| 132 class TaskRunnerFrameSource : public FrameSource { | |
| 133 public: | |
| 134 TaskRunnerFrameSource(FrameSink* sink, | |
| 135 base::SingleThreadTaskRunner* task_runner) | |
| 136 : task_runner_(task_runner), FrameSource(sink) { | |
| 137 DCHECK(task_runner); | |
| 138 } | |
| 139 virtual ~TaskRunnerFrameSource() {} | |
| 140 | |
| 141 protected: | |
| 142 base::SingleThreadTaskRunner task_runner_; | |
| 143 }; | |
| 144 | |
| 145 /** | |
| 146 * A frame source which sends a BeginFrame as soon as SetNeedsBeginFrame is | |
| 147 * requested. | |
| 148 */ | |
| 149 class BackToBackFrameSource : public TaskRunnerFrameSource { | |
|
brianderson
2014/05/05 16:50:05
Would this be used as the "vsync disabled" BeginFr
mithro-old
2014/05/05 17:10:53
Is there any reason we want to keep it level trigg
brianderson
2014/05/05 17:37:49
It is level triggered at the interface between the
| |
| 150 public: | |
| 151 virtual void SetNeedsBeginFrame(bool needs_begin_frame) OVERRIDE { | |
| 152 if (needs_begin_frame) { | |
| 153 task_runner_->PostDelayedTask( | |
| 154 FROM_HERE, | |
| 155 base::Bind(&BackToBackFrameSource::PostBeginFrame, | |
| 156 weak_factory_.GetWeakPtr())); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 void PostBeginFrame() { | |
| 161 base::TimeTicks now = gfx::FrameTime::Now(); | |
| 162 BeginFrameArgs begin_frame_args = | |
| 163 BeginFrameArgs::Create(now, base::TimeTicks(), base::TimeDelta()); | |
| 164 FrameSource::SendBeginFrame(args); | |
| 165 } | |
| 166 | |
| 167 protected: | |
| 168 virtual std::string GetType() const OVERRIDE { | |
| 169 return "BackToBackFrameSource"; | |
| 170 } | |
| 171 }; | |
| 172 | |
| 173 /** | |
| 174 * A frame source which is locked an external vsync source and generates | |
| 175 * BeginFrameArgs for it. | |
| 176 */ | |
| 177 class SyntheticFrameSource : public TaskRunnerFrameSource, | |
| 178 public TimeSourceClient { | |
| 179 public: | |
| 180 SyntheticFrameSource(FrameSink* sink, | |
| 181 base::SingleThreadTaskRunner* task_runner) | |
| 182 : TaskRunnerFrameSource(sink, task_runner) { | |
| 183 if (gfx::FrameTime::TimestampsAreHighRes()) { | |
| 184 time_source_ = DelayBasedTimeSourceHighRes::Create(sink_->VSyncInterval(), | |
| 185 task_runner); | |
| 186 } else { | |
| 187 time_source_ = | |
| 188 DelayBasedTimeSource::Create(sink_->VSyncInterval(), task_runner); | |
| 189 } | |
| 190 time_source_->SetClient(this); | |
| 191 } | |
| 192 virtual ~SyntheticFrameSource() {} | |
| 193 | |
| 194 // Activates future BeginFrames and, if activating, pushes the most | |
| 195 // recently missed BeginFrame to the back of a retroactive queue. | |
| 196 void SetNeedsBeginFrame(bool needs_begin_frame) OVERRIDE { | |
| 197 base::TimeTicks missed_tick_time = | |
| 198 time_source_->SetActive(needs_begin_frame); | |
| 199 if (!missed_tick_time.is_null()) { | |
| 200 BaseFrameSource::SendBeginFrame( | |
| 201 CreateSyntheticBeginFrameArgs(missed_tick_time)); | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 // Updates the phase and frequency of the timer. | |
| 206 virtual void UpdateFrameSource(base::TimeTicks timebase, | |
| 207 base::TimeDelta interval) OVERRIDE { | |
| 208 TaskRunnerFrameSource::UpdateFrameSource(timebase, interval); | |
| 209 time_source_->SetTimebaseAndInterval(timebase, interval); | |
| 210 } | |
| 211 | |
| 212 virtual scoped_ptr<base::Value> AsValue() const OVERRIDE { | |
| 213 scoped_ptr<base::DictionaryValue> state = FrameSource::AsValue(); | |
| 214 state->SetValue("source", source_->AsValue().release()); | |
| 215 return state.PassAs<base::Value>(); | |
| 216 } | |
| 217 | |
| 218 // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame. | |
| 219 virtual void OnTimerTick() OVERRIDE { | |
| 220 BeginFrameArgs begin_frame_args( | |
| 221 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); | |
| 222 SendBeginFrame(begin_frame_args); | |
| 223 } | |
| 224 | |
| 225 protected: | |
| 226 virtual std::string GetType() const OVERRIDE { | |
| 227 return "SyntheticFrameSource"; | |
| 228 } | |
| 229 | |
| 230 private: | |
| 231 FrameSink* sink_; | |
| 232 scoped_refptr<TimeSource> time_source_; | |
| 233 | |
| 234 BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time) { | |
| 235 base::TimeTicks deadline = | |
| 236 time_source_->NextTickTime() - sink_->EstimatedParentDrawTime(); | |
| 237 return BeginFrameArgs::Create(frame_time, deadline, interval_); | |
| 238 } | |
| 239 }; | |
| 240 | |
| 241 /** | |
| 242 * A virtual frame source which lets you switch between two other frame sources | |
| 243 * (making sure the BeginFrameArgs stays monotonic). | |
| 244 */ | |
| 245 class DualFrameSource : public FrameSource, public FrameSink { | |
|
brianderson
2014/05/05 16:50:05
Is this going to be used to switch between backgro
mithro-old
2014/05/05 17:10:53
Yeah. The thought here was to allow switching betw
| |
| 246 public: | |
| 247 DualFrameSource(FrameSink* sink, | |
| 248 const scoped_refptr<FrameSource>& source_primary, | |
| 249 const scoped_refptr<FrameSource>& source_secondary) | |
| 250 : source_primary_(source_primary), | |
| 251 source_secondary_(source_secondary), | |
| 252 needs_begin_frame_(false), | |
| 253 last_frame_args_() { | |
| 254 source_primary_->SetSink(this); | |
| 255 source_secondary_->SetSink(this); | |
| 256 SwitchSource(SourcePrimary()); | |
| 257 } | |
| 258 | |
| 259 virtual void BeginFrame(BeginFrameArgs* args) OVERRIDE { | |
| 260 // When switching clock sources you can get a BeginFrameArgs with a | |
| 261 // frame_time before the last value. | |
| 262 if (last_frame_args_.frame_time > args.frame_time) | |
| 263 args.frame_time = last_frame_args_.frame_time; | |
| 264 | |
| 265 FrameSource::SendBeginFrame(args); | |
| 266 last_frame_args_ = args; | |
| 267 } | |
| 268 | |
| 269 virtual void SetNeedsBeginFrame(bool needs_begin_frame) OVERRIDE { | |
| 270 DCHECK(active_source_); | |
| 271 needs_begin_frame_ = needs_begin_frame; | |
| 272 active_source_->SetNeedsBeginFrame(needs_begin_frame); | |
| 273 } | |
| 274 | |
| 275 virtual scoped_ptr<base::Value> AsValue() const OVERRIDE { | |
| 276 scoped_ptr<base::DictionaryValue> state = FrameSource::AsValue(); | |
| 277 if (active_source_ == SourcePrimary()) | |
| 278 state->SetString("active", "primary"); | |
| 279 if (active_source_ == SourceSecondary()) | |
| 280 state->SetString("active", "secondary"); | |
| 281 state->SetValue("primary", source_primary_->AsValue().release()); | |
| 282 state->SetValue("secondary", source_secondary_->AsValue().release()); | |
| 283 state->SetValue("last_frame_args", last_frame_args_->AsValue().release()); | |
| 284 return state.PassAs<base::Value>(); | |
| 285 } | |
| 286 | |
| 287 // --------------------------------------------------------------------- | |
| 288 | |
| 289 void SwitchSource(base::FrameSource* new_source) { | |
| 290 DCHECK(new_source == SourcePrimary() || new_source == SourceSecondary()); | |
| 291 | |
| 292 if (needs_begin_frame_) | |
| 293 active_source_.SetNeedsBeginFrame(false); | |
| 294 | |
| 295 active_source_ = new_source; | |
| 296 | |
| 297 if (needs_begin_frame_) | |
| 298 active_source_.SetNeedsBeginFrame(true); | |
| 299 } | |
| 300 | |
| 301 base::FrameSource* SourcePrimary() { return source_primary_.get(); } | |
| 302 | |
| 303 base::FrameSource* SourceSecondary() { return source_secondary_.get(); } | |
| 304 | |
| 305 protected: | |
| 306 virtual std::string GetType() const OVERRIDE { | |
| 307 return std::string("DualFrameSource"); | |
| 308 } | |
| 309 | |
| 310 private: | |
| 311 bool needs_begin_frame_; | |
| 312 BeginFrameArgs last_frame_args_; | |
| 313 base::FrameSource* active_source_; | |
| 314 scoped_refptr<base::FrameSource> source_primary_; | |
| 315 scoped_refptr<base::FrameSource> source_secondary_; | |
| 316 }; | |
| 317 | |
| 318 } // namespace cc | |
| OLD | NEW |