Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/scheduler/begin_frame_source.h" | 5 #include "cc/scheduler/begin_frame_source.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ptr_util.h" | |
| 12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 14 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 15 #include "base/trace_event/trace_event_argument.h" | 16 #include "base/trace_event/trace_event_argument.h" |
| 16 #include "cc/scheduler/delay_based_time_source.h" | 17 #include "cc/scheduler/delay_based_time_source.h" |
| 17 #include "cc/scheduler/scheduler.h" | 18 #include "cc/scheduler/scheduler.h" |
| 18 | 19 |
| 19 namespace cc { | 20 namespace cc { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 return; | 91 return; |
| 91 paused_ = paused; | 92 paused_ = paused; |
| 92 std::set<BeginFrameObserver*> observers(observers_); | 93 std::set<BeginFrameObserver*> observers(observers_); |
| 93 for (BeginFrameObserver* obs : observers) | 94 for (BeginFrameObserver* obs : observers) |
| 94 obs->OnBeginFrameSourcePausedChanged(paused_); | 95 obs->OnBeginFrameSourcePausedChanged(paused_); |
| 95 } | 96 } |
| 96 | 97 |
| 97 // BackToBackBeginFrameSource -------------------------------------------- | 98 // BackToBackBeginFrameSource -------------------------------------------- |
| 98 BackToBackBeginFrameSource::BackToBackBeginFrameSource( | 99 BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| 99 base::SingleThreadTaskRunner* task_runner) | 100 base::SingleThreadTaskRunner* task_runner) |
| 100 : BeginFrameSourceBase(), task_runner_(task_runner), weak_factory_(this) { | 101 : SyntheticBeginFrameSource( |
| 101 DCHECK(task_runner); | 102 base::MakeUnique<DelayBasedTimeSource>(task_runner)) { |
| 103 SetUnthrottled(true); | |
| 102 } | 104 } |
| 103 | 105 |
| 104 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() { | 106 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; |
| 105 } | |
| 106 | |
| 107 base::TimeTicks BackToBackBeginFrameSource::Now() { | |
| 108 return base::TimeTicks::Now(); | |
| 109 } | |
| 110 | |
| 111 // BeginFrameSourceBase support | |
| 112 void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | |
| 113 BeginFrameSourceBase::AddObserver(obs); | |
| 114 pending_begin_frame_observers_.insert(obs); | |
| 115 PostPendingBeginFramesTask(); | |
| 116 } | |
| 117 | |
| 118 void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | |
| 119 BeginFrameSourceBase::RemoveObserver(obs); | |
| 120 pending_begin_frame_observers_.erase(obs); | |
| 121 if (pending_begin_frame_observers_.empty()) | |
| 122 begin_frame_task_.Cancel(); | |
| 123 } | |
| 124 | |
| 125 void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | |
| 126 size_t remaining_frames) { | |
| 127 BeginFrameSourceBase::DidFinishFrame(obs, remaining_frames); | |
| 128 if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) { | |
| 129 pending_begin_frame_observers_.insert(obs); | |
| 130 PostPendingBeginFramesTask(); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 void BackToBackBeginFrameSource::PostPendingBeginFramesTask() { | |
| 135 DCHECK(needs_begin_frames()); | |
| 136 DCHECK(!pending_begin_frame_observers_.empty()); | |
| 137 if (begin_frame_task_.IsCancelled()) { | |
| 138 begin_frame_task_.Reset( | |
| 139 base::Bind(&BackToBackBeginFrameSource::SendPendingBeginFrames, | |
| 140 weak_factory_.GetWeakPtr())); | |
| 141 task_runner_->PostTask(FROM_HERE, begin_frame_task_.callback()); | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 void BackToBackBeginFrameSource::SendPendingBeginFrames() { | |
| 146 DCHECK(needs_begin_frames()); | |
| 147 DCHECK(!begin_frame_task_.IsCancelled()); | |
| 148 begin_frame_task_.Cancel(); | |
| 149 | |
| 150 base::TimeTicks now = Now(); | |
| 151 BeginFrameArgs args = BeginFrameArgs::Create( | |
| 152 BEGINFRAME_FROM_HERE, now, now + BeginFrameArgs::DefaultInterval(), | |
| 153 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL); | |
| 154 | |
| 155 std::set<BeginFrameObserver*> pending_observers; | |
| 156 pending_observers.swap(pending_begin_frame_observers_); | |
| 157 for (BeginFrameObserver* obs : pending_observers) | |
| 158 obs->OnBeginFrame(args); | |
| 159 } | |
| 160 | 107 |
| 161 // SyntheticBeginFrameSource --------------------------------------------- | 108 // SyntheticBeginFrameSource --------------------------------------------- |
| 162 SyntheticBeginFrameSource::SyntheticBeginFrameSource( | 109 SyntheticBeginFrameSource::SyntheticBeginFrameSource( |
| 163 base::SingleThreadTaskRunner* task_runner, | 110 std::unique_ptr<DelayBasedTimeSource> time_source) |
| 164 base::TimeDelta initial_vsync_interval) | 111 : time_source_(std::move(time_source)), |
| 165 : time_source_( | 112 last_interval_(time_source_->Interval()) { |
| 166 DelayBasedTimeSource::Create(initial_vsync_interval, task_runner)) { | |
| 167 time_source_->SetClient(this); | 113 time_source_->SetClient(this); |
| 168 } | 114 } |
| 169 | 115 |
| 170 SyntheticBeginFrameSource::SyntheticBeginFrameSource( | 116 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
| 171 std::unique_ptr<DelayBasedTimeSource> time_source) | |
| 172 : time_source_(std::move(time_source)) { | |
| 173 time_source_->SetClient(this); | |
| 174 } | |
| 175 | |
| 176 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {} | |
| 177 | 117 |
| 178 void SyntheticBeginFrameSource::OnUpdateVSyncParameters( | 118 void SyntheticBeginFrameSource::OnUpdateVSyncParameters( |
| 179 base::TimeTicks timebase, | 119 base::TimeTicks timebase, |
| 180 base::TimeDelta interval) { | 120 base::TimeDelta interval) { |
| 181 if (!authoritative_interval_.is_zero()) | 121 if (!authoritative_interval_.is_zero()) { |
| 182 interval = authoritative_interval_; | 122 interval = authoritative_interval_; |
| 123 } else if (interval.is_zero()) { | |
| 124 // TODO(brianderson): We should not be receiving 0 intervals. | |
|
enne (OOO)
2016/06/14 21:25:17
I love how this comment has proliferated.
brianderson
2016/06/14 21:59:48
I have so many fewer TODO's now! =)
| |
| 125 interval = BeginFrameArgs::DefaultInterval(); | |
| 126 } | |
| 183 | 127 |
| 184 last_timebase_ = timebase; | 128 last_timebase_ = timebase; |
| 185 time_source_->SetTimebaseAndInterval(timebase, interval); | 129 last_interval_ = interval; |
| 130 if (!unthrottled_) | |
| 131 time_source_->SetTimebaseAndInterval(timebase, interval); | |
| 186 } | 132 } |
| 187 | 133 |
| 188 void SyntheticBeginFrameSource::SetAuthoritativeVSyncInterval( | 134 void SyntheticBeginFrameSource::SetAuthoritativeVSyncInterval( |
| 189 base::TimeDelta interval) { | 135 base::TimeDelta interval) { |
| 190 authoritative_interval_ = interval; | 136 authoritative_interval_ = interval; |
| 191 OnUpdateVSyncParameters(last_timebase_, interval); | 137 OnUpdateVSyncParameters(last_timebase_, interval); |
| 192 } | 138 } |
| 193 | 139 |
| 140 void SyntheticBeginFrameSource::SetUnthrottled(bool unthrottled) { | |
| 141 if (unthrottled) | |
| 142 time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta()); | |
| 143 else | |
| 144 time_source_->SetTimebaseAndInterval(last_timebase_, last_interval_); | |
| 145 unthrottled_ = unthrottled; | |
| 146 } | |
| 147 | |
| 194 BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs( | 148 BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs( |
| 195 base::TimeTicks frame_time, | 149 base::TimeTicks frame_time, |
| 196 BeginFrameArgs::BeginFrameArgsType type) { | 150 BeginFrameArgs::BeginFrameArgsType type) { |
| 151 if (unthrottled_) { | |
| 152 // When unthrottled, the NextTickTime is not meaningful, so just use the | |
| 153 // current interval as the deadline. | |
| 154 return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, | |
| 155 frame_time + last_interval_, last_interval_, | |
| 156 type); | |
| 157 } | |
| 197 return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, | 158 return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, |
| 198 time_source_->NextTickTime(), | 159 time_source_->NextTickTime(), last_interval_, |
| 199 time_source_->Interval(), type); | 160 type); |
| 200 } | 161 } |
| 201 | 162 |
| 202 // BeginFrameSource support | 163 // BeginFrameSource support |
| 203 void SyntheticBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 164 void SyntheticBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| 204 BeginFrameSourceBase::AddObserver(obs); | 165 BeginFrameSourceBase::AddObserver(obs); |
| 166 | |
| 167 if (unthrottled_) { | |
| 168 // When unthrottled, ensure the time source is ticking for the first frame | |
| 169 // this observer sees (since it only ticks when an observer is ready), and | |
| 170 // don't post a MISSED frame since unthrottled just goes as fast as it can. | |
| 171 time_source_->SetActive(true); | |
| 172 frame_finished_observers_.insert(obs); | |
| 173 return; | |
| 174 } | |
| 175 | |
| 205 BeginFrameArgs args = CreateBeginFrameArgs( | 176 BeginFrameArgs args = CreateBeginFrameArgs( |
| 206 time_source_->NextTickTime() - time_source_->Interval(), | 177 time_source_->NextTickTime() - last_interval_, BeginFrameArgs::MISSED); |
| 207 BeginFrameArgs::MISSED); | |
| 208 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 178 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
| 209 if (!last_args.IsValid() || | 179 if (!last_args.IsValid() || |
| 210 (args.frame_time > | 180 (args.frame_time > |
| 211 last_args.frame_time + args.interval / kDoubleTickDivisor)) { | 181 last_args.frame_time + args.interval / kDoubleTickDivisor)) { |
| 212 obs->OnBeginFrame(args); | 182 obs->OnBeginFrame(args); |
| 213 } | 183 } |
| 214 } | 184 } |
| 215 | 185 |
| 186 void SyntheticBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | |
| 187 BeginFrameSourceBase::RemoveObserver(obs); | |
| 188 frame_finished_observers_.erase(obs); | |
| 189 } | |
| 190 | |
| 216 void SyntheticBeginFrameSource::OnNeedsBeginFramesChanged( | 191 void SyntheticBeginFrameSource::OnNeedsBeginFramesChanged( |
| 217 bool needs_begin_frames) { | 192 bool needs_begin_frames) { |
| 218 time_source_->SetActive(needs_begin_frames); | 193 time_source_->SetActive(needs_begin_frames); |
| 219 } | 194 } |
| 220 | 195 |
| 221 // DelayBasedTimeSourceClient support | 196 void SyntheticBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, |
| 222 void SyntheticBeginFrameSource::OnTimerTick() { | 197 size_t remaining_frames) { |
| 223 BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), | 198 if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) { |
| 224 BeginFrameArgs::NORMAL); | 199 frame_finished_observers_.insert(obs); |
| 225 std::set<BeginFrameObserver*> observers(observers_); | 200 time_source_->SetActive(true); |
| 226 for (auto& it : observers) { | |
| 227 BeginFrameArgs last_args = it->LastUsedBeginFrameArgs(); | |
| 228 if (!last_args.IsValid() || | |
| 229 (args.frame_time > | |
| 230 last_args.frame_time + args.interval / kDoubleTickDivisor)) { | |
| 231 it->OnBeginFrame(args); | |
| 232 } | |
| 233 } | 201 } |
| 234 } | 202 } |
| 235 | 203 |
| 204 // DelayBasedTimeSourceClient support | |
| 205 void SyntheticBeginFrameSource::OnTimerTick() { | |
| 206 // This must be captured before calling SetActive(false) on the time_source_. | |
| 207 base::TimeTicks now = time_source_->LastTickTime(); | |
| 208 | |
| 209 if (unthrottled_) { | |
| 210 // When unthrottled, we only want to tick when an observer finishes a frame, | |
| 211 // so stop and wait for that. | |
| 212 time_source_->SetActive(false); | |
| 213 } | |
| 214 | |
| 215 BeginFrameArgs args = CreateBeginFrameArgs(now, BeginFrameArgs::NORMAL); | |
| 216 std::set<BeginFrameObserver*> observers(observers_); | |
| 217 for (auto& obs : observers) { | |
| 218 bool on_begin_frame = false; | |
| 219 if (unthrottled_) { | |
| 220 // When unthrottled, we only want to generate a new begin frame for each | |
| 221 // observer when its previous one finished. | |
| 222 on_begin_frame = frame_finished_observers_.count(obs) > 0; | |
| 223 } else { | |
| 224 // When ticking at a throttled rate we want to generate a new begin frame | |
| 225 // regularly, but not too often. | |
| 226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | |
| 227 on_begin_frame = | |
| 228 !last_args.IsValid() || | |
| 229 (args.frame_time > | |
| 230 last_args.frame_time + args.interval / kDoubleTickDivisor); | |
| 231 } | |
| 232 frame_finished_observers_.erase(obs); | |
| 233 if (on_begin_frame) | |
| 234 obs->OnBeginFrame(args); | |
| 235 } | |
| 236 } | |
| 237 | |
| 236 } // namespace cc | 238 } // namespace cc |
| OLD | NEW |