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

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

Issue 2061273002: cc: Make BackToBackBeginFrameSource a SyntheticBeginFrameSource. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: syntheticbeginframesource: onemorenit Created 4 years, 6 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/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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698