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

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

Issue 2150533004: cc: Send all begin frames using a PostTask. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@scheduler_unittest_no_deadline
Patch Set: Created 4 years, 5 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
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698