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/memory/ptr_util.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "base/trace_event/trace_event_argument.h" | 16 #include "base/trace_event/trace_event_argument.h" |
| 17 #include "cc/scheduler/delay_based_time_source.h" | |
| 18 #include "cc/scheduler/scheduler.h" | 17 #include "cc/scheduler/scheduler.h" |
| 19 | 18 |
| 20 namespace cc { | 19 namespace cc { |
| 21 | 20 |
| 22 namespace { | 21 namespace { |
| 23 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too | 22 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too |
| 24 // often to an observer. | 23 // often to an observer. |
| 25 static const double kDoubleTickDivisor = 2.0; | 24 static const double kDoubleTickDivisor = 2.0; |
| 26 } | 25 } |
| 27 | 26 |
| 28 // BeginFrameObserverBase ----------------------------------------------- | 27 // BeginFrameObserverBase ----------------------------------------------- |
| 29 BeginFrameObserverBase::BeginFrameObserverBase() | 28 BeginFrameObserverBase::BeginFrameObserverBase() |
| 30 : last_begin_frame_args_(), dropped_begin_frame_args_(0) { | 29 : last_begin_frame_args_(), dropped_begin_frame_args_(0) {} |
| 31 } | |
| 32 | 30 |
| 33 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { | 31 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { |
| 34 return last_begin_frame_args_; | 32 return last_begin_frame_args_; |
| 35 } | 33 } |
| 36 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { | 34 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { |
| 37 DCHECK(args.IsValid()); | 35 DCHECK(args.IsValid()); |
| 38 DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); | 36 DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); |
| 39 bool used = OnBeginFrameDerivedImpl(args); | 37 bool used = OnBeginFrameDerivedImpl(args); |
| 40 if (used) { | 38 if (used) { |
| 41 last_begin_frame_args_ = args; | 39 last_begin_frame_args_ = args; |
| 42 } else { | 40 } else { |
| 43 ++dropped_begin_frame_args_; | 41 ++dropped_begin_frame_args_; |
| 44 } | 42 } |
| 45 } | 43 } |
| 46 | 44 |
| 47 // SyntheticBeginFrameSource --------------------------------------------- | 45 // SyntheticBeginFrameSource --------------------------------------------- |
| 48 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; | 46 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
| 49 | 47 |
| 50 // BackToBackBeginFrameSource -------------------------------------------- | 48 // BackToBackBeginFrameSource -------------------------------------------- |
| 51 BackToBackBeginFrameSource::BackToBackBeginFrameSource( | 49 BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| 52 std::unique_ptr<DelayBasedTimeSource> time_source) | 50 base::SingleThreadTaskRunner* task_runner) |
| 53 : time_source_(std::move(time_source)), weak_factory_(this) { | 51 : BackToBackBeginFrameSource(task_runner, nullptr) {} |
| 54 time_source_->SetClient(this); | 52 |
| 55 // The time_source_ ticks immediately, so we SetActive(true) for a single | 53 BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| 56 // tick when we need it, and keep it as SetActive(false) otherwise. | 54 base::SingleThreadTaskRunner* task_runner, |
| 57 time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta()); | 55 base::TickClock* clock) |
| 58 } | 56 : task_runner_(task_runner), clock_(clock), weak_factory_(this) {} |
| 59 | 57 |
| 60 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; | 58 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; |
| 61 | 59 |
| 62 void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 60 void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| 63 DCHECK(obs); | 61 DCHECK(obs); |
| 64 DCHECK(observers_.find(obs) == observers_.end()); | 62 DCHECK(observers_.find(obs) == observers_.end()); |
| 65 observers_.insert(obs); | 63 observers_.insert(obs); |
| 66 pending_begin_frame_observers_.insert(obs); | 64 if (pending_observers_.empty()) { |
| 65 DCHECK(begin_frame_callback_.IsCancelled()); | |
| 66 begin_frame_callback_.Reset( | |
| 67 base::Bind(&BackToBackBeginFrameSource::SendBeginFrame, | |
| 68 weak_factory_.GetWeakPtr())); | |
| 69 task_runner_->PostTask(FROM_HERE, begin_frame_callback_.callback()); | |
| 70 } | |
| 71 pending_observers_.insert(obs); | |
| 67 obs->OnBeginFrameSourcePausedChanged(false); | 72 obs->OnBeginFrameSourcePausedChanged(false); |
| 68 time_source_->SetActive(true); | |
| 69 } | 73 } |
| 70 | 74 |
| 71 void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 75 void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| 72 DCHECK(obs); | 76 DCHECK(obs); |
| 73 DCHECK(observers_.find(obs) != observers_.end()); | 77 DCHECK(observers_.find(obs) != observers_.end()); |
| 74 observers_.erase(obs); | 78 observers_.erase(obs); |
| 75 pending_begin_frame_observers_.erase(obs); | 79 pending_observers_.erase(obs); |
| 76 if (observers_.empty()) | 80 if (pending_observers_.empty()) |
| 77 time_source_->SetActive(false); | 81 begin_frame_callback_.Cancel(); |
| 78 } | 82 } |
| 79 | 83 |
| 80 void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | 84 void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, |
| 81 size_t remaining_frames) { | 85 size_t remaining_frames) { |
| 82 if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) { | 86 if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) { |
| 83 pending_begin_frame_observers_.insert(obs); | 87 if (pending_observers_.empty()) { |
| 84 time_source_->SetActive(true); | 88 DCHECK(begin_frame_callback_.IsCancelled()); |
| 89 begin_frame_callback_.Reset( | |
| 90 base::Bind(&BackToBackBeginFrameSource::SendBeginFrame, | |
| 91 weak_factory_.GetWeakPtr())); | |
| 92 task_runner_->PostTask(FROM_HERE, begin_frame_callback_.callback()); | |
| 93 } | |
| 94 pending_observers_.insert(obs); | |
| 85 } | 95 } |
| 86 } | 96 } |
| 87 | 97 |
| 88 void BackToBackBeginFrameSource::OnTimerTick() { | 98 void BackToBackBeginFrameSource::SendBeginFrame() { |
| 89 base::TimeTicks frame_time = time_source_->LastTickTime(); | 99 DCHECK(!pending_observers_.empty()); |
| 100 begin_frame_callback_.Cancel(); | |
| 101 std::unordered_set<BeginFrameObserver*> pending_observers; | |
| 102 pending_observers.swap(pending_observers_); | |
| 103 | |
| 104 base::TimeTicks frame_time = | |
| 105 clock_ ? clock_->NowTicks() : base::TimeTicks::Now(); | |
|
brianderson
2016/07/13 21:14:49
Maybe use a base::DefaultTickClock instead of chec
sunnyps
2016/07/13 21:24:53
I tried that but then DelayBasedTimeSource ended u
| |
| 90 base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); | 106 base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); |
| 91 BeginFrameArgs args = BeginFrameArgs::Create( | 107 BeginFrameArgs args = BeginFrameArgs::Create( |
| 92 BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval, | 108 BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval, |
| 93 default_interval, BeginFrameArgs::NORMAL); | 109 default_interval, BeginFrameArgs::NORMAL); |
| 94 | 110 |
| 95 // This must happen after getting the LastTickTime() from the time source. | |
| 96 time_source_->SetActive(false); | |
| 97 | |
| 98 std::unordered_set<BeginFrameObserver*> pending_observers; | |
| 99 pending_observers.swap(pending_begin_frame_observers_); | |
| 100 for (BeginFrameObserver* obs : pending_observers) | 111 for (BeginFrameObserver* obs : pending_observers) |
| 101 obs->OnBeginFrame(args); | 112 obs->OnBeginFrame(args); |
| 102 } | 113 } |
| 103 | 114 |
| 104 // DelayBasedBeginFrameSource --------------------------------------------- | 115 // DelayBasedBeginFrameSource --------------------------------------------- |
| 105 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( | 116 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( |
| 106 std::unique_ptr<DelayBasedTimeSource> time_source) | 117 base::SingleThreadTaskRunner* task_runner) |
| 107 : time_source_(std::move(time_source)) { | 118 : DelayBasedBeginFrameSource(task_runner, nullptr) {} |
| 119 | |
| 120 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( | |
| 121 base::SingleThreadTaskRunner* task_runner, | |
| 122 base::TickClock* clock) | |
| 123 : time_source_(new DelayBasedTimeSource(task_runner, clock)), | |
| 124 task_runner_(task_runner), | |
| 125 weak_factory_(this) { | |
| 108 time_source_->SetClient(this); | 126 time_source_->SetClient(this); |
| 109 } | 127 } |
| 110 | 128 |
| 111 DelayBasedBeginFrameSource::~DelayBasedBeginFrameSource() = default; | 129 DelayBasedBeginFrameSource::~DelayBasedBeginFrameSource() = default; |
| 112 | 130 |
| 113 void DelayBasedBeginFrameSource::OnUpdateVSyncParameters( | 131 void DelayBasedBeginFrameSource::OnUpdateVSyncParameters( |
| 114 base::TimeTicks timebase, | 132 base::TimeTicks timebase, |
| 115 base::TimeDelta interval) { | 133 base::TimeDelta interval) { |
| 116 if (!authoritative_interval_.is_zero()) { | 134 if (!authoritative_interval_.is_zero()) { |
| 117 interval = authoritative_interval_; | 135 interval = authoritative_interval_; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 138 time_source_->Interval(), type); | 156 time_source_->Interval(), type); |
| 139 } | 157 } |
| 140 | 158 |
| 141 void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 159 void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| 142 DCHECK(obs); | 160 DCHECK(obs); |
| 143 DCHECK(observers_.find(obs) == observers_.end()); | 161 DCHECK(observers_.find(obs) == observers_.end()); |
| 144 | 162 |
| 145 observers_.insert(obs); | 163 observers_.insert(obs); |
| 146 obs->OnBeginFrameSourcePausedChanged(false); | 164 obs->OnBeginFrameSourcePausedChanged(false); |
| 147 time_source_->SetActive(true); | 165 time_source_->SetActive(true); |
| 148 BeginFrameArgs args = CreateBeginFrameArgs( | 166 |
| 149 time_source_->NextTickTime() - time_source_->Interval(), | 167 if (missed_frame_observers_.empty()) { |
| 150 BeginFrameArgs::MISSED); | 168 DCHECK(missed_frame_callback_.IsCancelled()); |
| 151 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 169 missed_frame_callback_.Reset( |
| 152 if (!last_args.IsValid() || | 170 base::Bind(&DelayBasedBeginFrameSource::SendMissedBeginFrame, |
| 153 (args.frame_time > | 171 weak_factory_.GetWeakPtr())); |
| 154 last_args.frame_time + args.interval / kDoubleTickDivisor)) { | 172 task_runner_->PostTask(FROM_HERE, missed_frame_callback_.callback()); |
| 155 obs->OnBeginFrame(args); | |
| 156 } | 173 } |
| 174 missed_frame_observers_.insert(obs); | |
| 157 } | 175 } |
| 158 | 176 |
| 159 void DelayBasedBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 177 void DelayBasedBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| 160 DCHECK(obs); | 178 DCHECK(obs); |
| 161 DCHECK(observers_.find(obs) != observers_.end()); | 179 DCHECK(observers_.find(obs) != observers_.end()); |
| 162 | 180 missed_frame_observers_.erase(obs); |
| 181 if (missed_frame_observers_.empty()) | |
| 182 missed_frame_callback_.Cancel(); | |
| 163 observers_.erase(obs); | 183 observers_.erase(obs); |
| 164 if (observers_.empty()) | 184 if (observers_.empty()) |
| 165 time_source_->SetActive(false); | 185 time_source_->SetActive(false); |
| 166 } | 186 } |
| 167 | 187 |
| 168 void DelayBasedBeginFrameSource::OnTimerTick() { | 188 void DelayBasedBeginFrameSource::OnTimerTick() { |
| 189 missed_frame_callback_.Cancel(); | |
| 190 missed_frame_observers_.clear(); | |
| 169 BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), | 191 BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), |
| 170 BeginFrameArgs::NORMAL); | 192 BeginFrameArgs::NORMAL); |
| 171 std::unordered_set<BeginFrameObserver*> observers(observers_); | 193 std::unordered_set<BeginFrameObserver*> observers(observers_); |
| 172 for (auto& obs : observers) { | 194 for (auto& obs : observers) { |
| 173 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 195 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
| 174 if (!last_args.IsValid() || | 196 if (!last_args.IsValid() || |
| 175 (args.frame_time > | 197 (args.frame_time > |
| 176 last_args.frame_time + args.interval / kDoubleTickDivisor)) | 198 last_args.frame_time + args.interval / kDoubleTickDivisor)) |
| 177 obs->OnBeginFrame(args); | 199 obs->OnBeginFrame(args); |
| 178 } | 200 } |
| 179 } | 201 } |
| 180 | 202 |
| 203 void DelayBasedBeginFrameSource::SendMissedBeginFrame() { | |
| 204 DCHECK(!missed_frame_observers_.empty()); | |
| 205 missed_frame_callback_.Cancel(); | |
| 206 std::unordered_set<BeginFrameObserver*> missed_frame_observers; | |
| 207 missed_frame_observers.swap(missed_frame_observers_); | |
| 208 | |
| 209 BeginFrameArgs args = CreateBeginFrameArgs( | |
| 210 time_source_->NextTickTime() - time_source_->Interval(), | |
| 211 BeginFrameArgs::MISSED); | |
| 212 | |
| 213 for (BeginFrameObserver* obs : missed_frame_observers) { | |
| 214 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | |
| 215 if (!last_args.IsValid() || | |
| 216 (args.frame_time > | |
| 217 last_args.frame_time + args.interval / kDoubleTickDivisor)) { | |
| 218 obs->OnBeginFrame(args); | |
| 219 } | |
| 220 } | |
| 221 } | |
| 222 | |
| 181 } // namespace cc | 223 } // namespace cc |
| OLD | NEW |