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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 |
| OLD | NEW |