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