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

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

Issue 2691453002: [cc] Track observer status in ExternalBeginFrameSource. (Closed)
Patch Set: Fix android compile errors. Created 3 years, 10 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/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); 226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
227 if (!last_args.IsValid() || 227 if (!last_args.IsValid() ||
228 (current_begin_frame_args_.frame_time > 228 (current_begin_frame_args_.frame_time >
229 last_args.frame_time + 229 last_args.frame_time +
230 current_begin_frame_args_.interval / kDoubleTickDivisor)) { 230 current_begin_frame_args_.interval / kDoubleTickDivisor)) {
231 obs->OnBeginFrame(current_begin_frame_args_); 231 obs->OnBeginFrame(current_begin_frame_args_);
232 } 232 }
233 } 233 }
234 } 234 }
235 235
236 // BeginFrameObserverAckTracker -------------------------------------------
237 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker()
238 : current_source_id_(0),
239 current_sequence_number_(BeginFrameArgs::kStartingFrameNumber),
240 observers_had_damage_(false) {}
241
242 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() {}
243
244 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) {
245 if (current_source_id_ != args.source_id)
246 SourceChanged(args);
247
248 DCHECK_GE(args.sequence_number, current_sequence_number_);
249 // Reset for new BeginFrame.
250 current_sequence_number_ = args.sequence_number;
251 finished_observers_.clear();
252 observers_had_damage_ = false;
253 }
254
255 void BeginFrameObserverAckTracker::OnObserverBeginFrame(
256 BeginFrameObserver* obs,
257 const BeginFrameArgs& args) {
258 if (current_source_id_ != args.source_id)
259 SourceChanged(args);
260
261 DCHECK_EQ(args.sequence_number, current_sequence_number_);
262 // Observer may choose to drop the BeginFrame. In this case, it has finished,
263 // but is not considered up-to-date.
264 if (obs->LastUsedBeginFrameArgs().sequence_number != current_sequence_number_)
brianderson 2017/02/15 20:50:47 Why is this != instead of ==?
Eric Seckler 2017/02/17 19:10:01 This checks if the observer actually uses the Begi
brianderson 2017/02/17 20:49:54 Ah, I see. Instead of doing this, can we require O
Eric Seckler 2017/02/17 22:49:35 I think I'll make those changes and send out anoth
Eric Seckler 2017/02/21 12:10:57 Turns out it doesn't require much changes at this
265 finished_observers_.insert(obs);
266 }
267
268 void BeginFrameObserverAckTracker::SourceChanged(const BeginFrameArgs& args) {
269 current_source_id_ = args.source_id;
270 current_sequence_number_ = args.sequence_number;
271
272 // Mark all observers invalid: We report an invalid frame until every observer
273 // has confirmed the frame.
274 for (auto& entry : latest_confirmed_sequence_numbers_)
275 entry.second = BeginFrameArgs::kInvalidFrameNumber;
276 }
277
278 void BeginFrameObserverAckTracker::OnObserverFinishedFrame(
279 BeginFrameObserver* obs,
280 const BeginFrameAck& ack) {
281 if (ack.source_id != current_source_id_)
282 return;
283
284 DCHECK_LE(ack.sequence_number, current_sequence_number_);
285 if (ack.sequence_number != current_sequence_number_)
286 return;
287
288 finished_observers_.insert(obs);
289 observers_had_damage_ |= ack.has_damage;
290
291 // We max() with the current value in |latest_confirmed_sequence_numbers_| to
292 // handle situations where an observer just started observing (again) and may
293 // acknowledge with an ancient latest_confirmed_sequence_number.
294 latest_confirmed_sequence_numbers_[obs] =
295 std::max(ack.latest_confirmed_sequence_number,
296 latest_confirmed_sequence_numbers_[obs]);
297 }
298
299 void BeginFrameObserverAckTracker::OnObserverAdded(BeginFrameObserver* obs) {
300 observers_.insert(obs);
301
302 // Since the observer didn't want BeginFrames before, we consider it
303 // up-to-date up to the last BeginFrame, except if it already handled the
304 // current BeginFrame. In which case, we consider it up-to-date up to the
305 // current one.
306 DCHECK_LT(BeginFrameArgs::kInvalidFrameNumber, current_sequence_number_);
307 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
308 if (last_args.IsValid() &&
309 last_args.sequence_number == current_sequence_number_ &&
310 last_args.source_id == current_source_id_) {
311 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_;
312 finished_observers_.insert(obs);
313 } else {
314 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_ - 1;
315 }
316 }
317
318 void BeginFrameObserverAckTracker::OnObserverRemoved(BeginFrameObserver* obs) {
319 observers_.erase(obs);
320 finished_observers_.erase(obs);
321 latest_confirmed_sequence_numbers_.erase(obs);
322 }
323
324 bool BeginFrameObserverAckTracker::AllObserversFinishedFrame() const {
325 return base::STLIncludes(finished_observers_, observers_);
brianderson 2017/02/15 20:50:48 It looks like STLIncludes depends on std::includes
Eric Seckler 2017/02/17 19:10:01 Added the early out. I don't think we can guarante
326 }
327
328 bool BeginFrameObserverAckTracker::AnyObserversHadDamage() const {
329 return observers_had_damage_;
330 }
331
332 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const {
333 uint64_t latest_confirmed_sequence_number = current_sequence_number_;
334 for (const auto& entry : latest_confirmed_sequence_numbers_) {
335 latest_confirmed_sequence_number =
336 std::min(latest_confirmed_sequence_number, entry.second);
337 }
338 return latest_confirmed_sequence_number;
339 }
340
236 // ExternalBeginFrameSource ----------------------------------------------- 341 // ExternalBeginFrameSource -----------------------------------------------
237 ExternalBeginFrameSource::ExternalBeginFrameSource( 342 ExternalBeginFrameSource::ExternalBeginFrameSource(
238 ExternalBeginFrameSourceClient* client) 343 ExternalBeginFrameSourceClient* client)
239 : client_(client) { 344 : client_(client) {
240 DCHECK(client_); 345 DCHECK(client_);
241 } 346 }
242 347
243 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; 348 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default;
244 349
245 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { 350 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
246 DCHECK(obs); 351 DCHECK(obs);
247 DCHECK(observers_.find(obs) == observers_.end()); 352 DCHECK(observers_.find(obs) == observers_.end());
248 353
249 bool observers_was_empty = observers_.empty(); 354 bool observers_was_empty = observers_.empty();
250 observers_.insert(obs); 355 observers_.insert(obs);
356 ack_tracker_.OnObserverAdded(obs);
251 obs->OnBeginFrameSourcePausedChanged(paused_); 357 obs->OnBeginFrameSourcePausedChanged(paused_);
252 if (observers_was_empty) 358 if (observers_was_empty)
253 client_->OnNeedsBeginFrames(true); 359 client_->OnNeedsBeginFrames(true);
254 360
255 // Send a MISSED begin frame if necessary. 361 // Send a MISSED begin frame if necessary.
256 if (missed_begin_frame_args_.IsValid()) { 362 if (missed_begin_frame_args_.IsValid()) {
257 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); 363 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
258 if (!last_args.IsValid() || 364 if (!last_args.IsValid() ||
259 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { 365 (missed_begin_frame_args_.frame_time > last_args.frame_time)) {
260 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || 366 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) ||
261 (missed_begin_frame_args_.sequence_number > 367 (missed_begin_frame_args_.sequence_number >
262 last_args.sequence_number)); 368 last_args.sequence_number));
263 obs->OnBeginFrame(missed_begin_frame_args_); 369 obs->OnBeginFrame(missed_begin_frame_args_);
370 ack_tracker_.OnObserverBeginFrame(obs, missed_begin_frame_args_);
264 } 371 }
265 } 372 }
266 } 373 }
267 374
268 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { 375 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) {
269 DCHECK(obs); 376 DCHECK(obs);
270 DCHECK(observers_.find(obs) != observers_.end()); 377 DCHECK(observers_.find(obs) != observers_.end());
271 378
272 observers_.erase(obs); 379 observers_.erase(obs);
380 ack_tracker_.OnObserverRemoved(obs);
381 MaybeFinishFrame();
273 if (observers_.empty()) { 382 if (observers_.empty()) {
274 missed_begin_frame_args_ = BeginFrameArgs(); 383 missed_begin_frame_args_ = BeginFrameArgs();
275 client_->OnNeedsBeginFrames(false); 384 client_->OnNeedsBeginFrames(false);
276 } 385 }
277 } 386 }
278 387
388 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs,
389 const BeginFrameAck& ack) {
390 ack_tracker_.OnObserverFinishedFrame(obs, ack);
391 MaybeFinishFrame();
392 }
393
279 bool ExternalBeginFrameSource::IsThrottled() const { 394 bool ExternalBeginFrameSource::IsThrottled() const {
280 return true; 395 return true;
281 } 396 }
282 397
283 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { 398 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) {
284 if (paused_ == paused) 399 if (paused_ == paused)
285 return; 400 return;
286 paused_ = paused; 401 paused_ = paused;
287 std::unordered_set<BeginFrameObserver*> observers(observers_); 402 std::unordered_set<BeginFrameObserver*> observers(observers_);
288 for (auto* obs : observers) 403 for (auto* obs : observers)
289 obs->OnBeginFrameSourcePausedChanged(paused_); 404 obs->OnBeginFrameSourcePausedChanged(paused_);
290 } 405 }
291 406
292 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { 407 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) {
408 if (frame_active_)
409 FinishFrame();
410
411 frame_active_ = true;
293 missed_begin_frame_args_ = args; 412 missed_begin_frame_args_ = args;
294 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; 413 missed_begin_frame_args_.type = BeginFrameArgs::MISSED;
414 ack_tracker_.OnBeginFrame(args);
295 std::unordered_set<BeginFrameObserver*> observers(observers_); 415 std::unordered_set<BeginFrameObserver*> observers(observers_);
296 for (auto* obs : observers) 416 for (auto* obs : observers) {
297 obs->OnBeginFrame(args); 417 obs->OnBeginFrame(args);
418 ack_tracker_.OnObserverBeginFrame(obs, args);
419 }
420 MaybeFinishFrame();
421 }
422
423 void ExternalBeginFrameSource::MaybeFinishFrame() {
424 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame())
425 return;
426 FinishFrame();
427 }
428
429 void ExternalBeginFrameSource::FinishFrame() {
430 frame_active_ = false;
431
432 BeginFrameAck ack(missed_begin_frame_args_.source_id,
433 missed_begin_frame_args_.sequence_number,
434 ack_tracker_.LatestConfirmedSequenceNumber(), 0,
435 ack_tracker_.AnyObserversHadDamage());
436 client_->OnDidFinishFrame(ack);
298 } 437 }
299 438
300 } // namespace cc 439 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698