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/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 |