| 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 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 245 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
| 246 if (!last_args.IsValid() || | 246 if (!last_args.IsValid() || |
| 247 (current_begin_frame_args_.frame_time > | 247 (current_begin_frame_args_.frame_time > |
| 248 last_args.frame_time + | 248 last_args.frame_time + |
| 249 current_begin_frame_args_.interval / kDoubleTickDivisor)) { | 249 current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
| 250 obs->OnBeginFrame(current_begin_frame_args_); | 250 obs->OnBeginFrame(current_begin_frame_args_); |
| 251 } | 251 } |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 | 254 |
| 255 // BeginFrameObserverAckTracker ------------------------------------------- | |
| 256 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker() = default; | |
| 257 | |
| 258 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() = default; | |
| 259 | |
| 260 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) { | |
| 261 if (current_source_id_ != args.source_id) | |
| 262 SourceChanged(args); | |
| 263 | |
| 264 DCHECK_GE(args.sequence_number, current_sequence_number_); | |
| 265 // Reset for new BeginFrame. | |
| 266 current_sequence_number_ = args.sequence_number; | |
| 267 finished_observers_.clear(); | |
| 268 observers_had_damage_ = false; | |
| 269 } | |
| 270 | |
| 271 void BeginFrameObserverAckTracker::SourceChanged(const BeginFrameArgs& args) { | |
| 272 current_source_id_ = args.source_id; | |
| 273 current_sequence_number_ = args.sequence_number; | |
| 274 | |
| 275 // Mark all observers invalid: We report an invalid frame until every observer | |
| 276 // has confirmed the frame. | |
| 277 for (auto& entry : latest_confirmed_sequence_numbers_) | |
| 278 entry.second = BeginFrameArgs::kInvalidFrameNumber; | |
| 279 } | |
| 280 | |
| 281 void BeginFrameObserverAckTracker::OnObserverFinishedFrame( | |
| 282 BeginFrameObserver* obs, | |
| 283 const BeginFrameAck& ack) { | |
| 284 if (ack.source_id != current_source_id_) | |
| 285 return; | |
| 286 | |
| 287 DCHECK_LE(ack.sequence_number, current_sequence_number_); | |
| 288 if (ack.sequence_number != current_sequence_number_) | |
| 289 return; | |
| 290 | |
| 291 finished_observers_.insert(obs); | |
| 292 observers_had_damage_ |= ack.has_damage; | |
| 293 | |
| 294 // We max() with the current value in |latest_confirmed_sequence_numbers_| to | |
| 295 // handle situations where an observer just started observing (again) and may | |
| 296 // acknowledge with an ancient latest_confirmed_sequence_number. | |
| 297 latest_confirmed_sequence_numbers_[obs] = | |
| 298 std::max(ack.latest_confirmed_sequence_number, | |
| 299 latest_confirmed_sequence_numbers_[obs]); | |
| 300 } | |
| 301 | |
| 302 void BeginFrameObserverAckTracker::OnObserverAdded(BeginFrameObserver* obs) { | |
| 303 observers_.insert(obs); | |
| 304 | |
| 305 // Since the observer didn't want BeginFrames before, we consider it | |
| 306 // up-to-date up to the last BeginFrame, except if it already handled the | |
| 307 // current BeginFrame. In which case, we consider it up-to-date up to the | |
| 308 // current one. | |
| 309 DCHECK_LT(BeginFrameArgs::kInvalidFrameNumber, current_sequence_number_); | |
| 310 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | |
| 311 if (last_args.IsValid() && | |
| 312 last_args.sequence_number == current_sequence_number_ && | |
| 313 last_args.source_id == current_source_id_) { | |
| 314 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_; | |
| 315 finished_observers_.insert(obs); | |
| 316 } else { | |
| 317 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_ - 1; | |
| 318 } | |
| 319 } | |
| 320 | |
| 321 void BeginFrameObserverAckTracker::OnObserverRemoved(BeginFrameObserver* obs) { | |
| 322 observers_.erase(obs); | |
| 323 finished_observers_.erase(obs); | |
| 324 latest_confirmed_sequence_numbers_.erase(obs); | |
| 325 } | |
| 326 | |
| 327 bool BeginFrameObserverAckTracker::AllObserversFinishedFrame() const { | |
| 328 if (finished_observers_.size() < observers_.size()) | |
| 329 return false; | |
| 330 return base::STLIncludes(finished_observers_, observers_); | |
| 331 } | |
| 332 | |
| 333 bool BeginFrameObserverAckTracker::AnyObserversHadDamage() const { | |
| 334 return observers_had_damage_; | |
| 335 } | |
| 336 | |
| 337 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const { | |
| 338 uint64_t latest_confirmed_sequence_number = current_sequence_number_; | |
| 339 for (const auto& entry : latest_confirmed_sequence_numbers_) { | |
| 340 latest_confirmed_sequence_number = | |
| 341 std::min(latest_confirmed_sequence_number, entry.second); | |
| 342 } | |
| 343 return latest_confirmed_sequence_number; | |
| 344 } | |
| 345 | |
| 346 void BeginFrameObserverAckTracker::AsValueInto( | |
| 347 base::trace_event::TracedValue* state) const { | |
| 348 state->SetInteger("current_source_id", current_source_id_); | |
| 349 state->SetInteger("current_sequence_number", current_sequence_number_); | |
| 350 state->SetInteger("num_observers", observers_.size()); | |
| 351 state->SetInteger("num_finished_observers", finished_observers_.size()); | |
| 352 state->SetBoolean("observers_had_damage", observers_had_damage_); | |
| 353 | |
| 354 state->BeginArray("latest_confirmed_sequence_numbers"); | |
| 355 for (const auto& kv : latest_confirmed_sequence_numbers_) { | |
| 356 state->AppendInteger(kv.second); | |
| 357 } | |
| 358 state->EndArray(); | |
| 359 } | |
| 360 | |
| 361 // ExternalBeginFrameSource ----------------------------------------------- | 255 // ExternalBeginFrameSource ----------------------------------------------- |
| 362 ExternalBeginFrameSource::ExternalBeginFrameSource( | 256 ExternalBeginFrameSource::ExternalBeginFrameSource( |
| 363 ExternalBeginFrameSourceClient* client) | 257 ExternalBeginFrameSourceClient* client) |
| 364 : client_(client) { | 258 : client_(client) { |
| 365 DCHECK(client_); | 259 DCHECK(client_); |
| 366 } | 260 } |
| 367 | 261 |
| 368 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; | 262 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; |
| 369 | 263 |
| 370 void ExternalBeginFrameSource::AsValueInto( | 264 void ExternalBeginFrameSource::AsValueInto( |
| 371 base::trace_event::TracedValue* state) const { | 265 base::trace_event::TracedValue* state) const { |
| 372 BeginFrameSource::AsValueInto(state); | 266 BeginFrameSource::AsValueInto(state); |
| 373 | 267 |
| 374 state->SetBoolean("paused", paused_); | 268 state->SetBoolean("paused", paused_); |
| 375 state->SetBoolean("frame_active", frame_active_); | |
| 376 state->SetInteger("num_observers", observers_.size()); | 269 state->SetInteger("num_observers", observers_.size()); |
| 377 | 270 |
| 378 state->BeginDictionary("last_begin_frame_args"); | 271 state->BeginDictionary("last_begin_frame_args"); |
| 379 last_begin_frame_args_.AsValueInto(state); | 272 last_begin_frame_args_.AsValueInto(state); |
| 380 state->EndDictionary(); | 273 state->EndDictionary(); |
| 381 | |
| 382 state->BeginDictionary("ack_tracker_state"); | |
| 383 ack_tracker_.AsValueInto(state); | |
| 384 state->EndDictionary(); | |
| 385 } | 274 } |
| 386 | 275 |
| 387 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 276 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| 388 DCHECK(obs); | 277 DCHECK(obs); |
| 389 DCHECK(observers_.find(obs) == observers_.end()); | 278 DCHECK(observers_.find(obs) == observers_.end()); |
| 390 | 279 |
| 391 bool observers_was_empty = observers_.empty(); | 280 bool observers_was_empty = observers_.empty(); |
| 392 observers_.insert(obs); | 281 observers_.insert(obs); |
| 393 ack_tracker_.OnObserverAdded(obs); | |
| 394 obs->OnBeginFrameSourcePausedChanged(paused_); | 282 obs->OnBeginFrameSourcePausedChanged(paused_); |
| 395 if (observers_was_empty) | 283 if (observers_was_empty) |
| 396 client_->OnNeedsBeginFrames(true); | 284 client_->OnNeedsBeginFrames(true); |
| 397 | 285 |
| 398 // Send a MISSED begin frame if necessary. | 286 // Send a MISSED begin frame if necessary. |
| 399 if (last_begin_frame_args_.IsValid()) { | 287 if (last_begin_frame_args_.IsValid()) { |
| 400 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | 288 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); |
| 401 if (!last_args.IsValid() || | 289 if (!last_args.IsValid() || |
| 402 (last_begin_frame_args_.frame_time > last_args.frame_time)) { | 290 (last_begin_frame_args_.frame_time > last_args.frame_time)) { |
| 403 DCHECK( | 291 DCHECK( |
| 404 (last_begin_frame_args_.source_id != last_args.source_id) || | 292 (last_begin_frame_args_.source_id != last_args.source_id) || |
| 405 (last_begin_frame_args_.sequence_number > last_args.sequence_number)) | 293 (last_begin_frame_args_.sequence_number > last_args.sequence_number)) |
| 406 << "current " << last_begin_frame_args_.AsValue()->ToString() | 294 << "current " << last_begin_frame_args_.AsValue()->ToString() |
| 407 << ", last " << last_args.AsValue()->ToString(); | 295 << ", last " << last_args.AsValue()->ToString(); |
| 408 BeginFrameArgs missed_args = last_begin_frame_args_; | 296 BeginFrameArgs missed_args = last_begin_frame_args_; |
| 409 missed_args.type = BeginFrameArgs::MISSED; | 297 missed_args.type = BeginFrameArgs::MISSED; |
| 410 obs->OnBeginFrame(missed_args); | 298 obs->OnBeginFrame(missed_args); |
| 411 } | 299 } |
| 412 } | 300 } |
| 413 } | 301 } |
| 414 | 302 |
| 415 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 303 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| 416 DCHECK(obs); | 304 DCHECK(obs); |
| 417 DCHECK(observers_.find(obs) != observers_.end()); | 305 DCHECK(observers_.find(obs) != observers_.end()); |
| 418 | 306 |
| 419 observers_.erase(obs); | 307 observers_.erase(obs); |
| 420 ack_tracker_.OnObserverRemoved(obs); | |
| 421 MaybeFinishFrame(); | |
| 422 if (observers_.empty()) { | 308 if (observers_.empty()) { |
| 423 last_begin_frame_args_ = BeginFrameArgs(); | 309 last_begin_frame_args_ = BeginFrameArgs(); |
| 424 client_->OnNeedsBeginFrames(false); | 310 client_->OnNeedsBeginFrames(false); |
| 425 } | 311 } |
| 426 } | 312 } |
| 427 | 313 |
| 428 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | 314 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, |
| 429 const BeginFrameAck& ack) { | 315 const BeginFrameAck& ack) {} |
| 430 ack_tracker_.OnObserverFinishedFrame(obs, ack); | |
| 431 MaybeFinishFrame(); | |
| 432 } | |
| 433 | 316 |
| 434 bool ExternalBeginFrameSource::IsThrottled() const { | 317 bool ExternalBeginFrameSource::IsThrottled() const { |
| 435 return true; | 318 return true; |
| 436 } | 319 } |
| 437 | 320 |
| 438 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { | 321 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { |
| 439 if (paused_ == paused) | 322 if (paused_ == paused) |
| 440 return; | 323 return; |
| 441 paused_ = paused; | 324 paused_ = paused; |
| 442 std::unordered_set<BeginFrameObserver*> observers(observers_); | 325 std::unordered_set<BeginFrameObserver*> observers(observers_); |
| 443 for (auto* obs : observers) | 326 for (auto* obs : observers) |
| 444 obs->OnBeginFrameSourcePausedChanged(paused_); | 327 obs->OnBeginFrameSourcePausedChanged(paused_); |
| 445 } | 328 } |
| 446 | 329 |
| 447 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { | 330 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { |
| 448 if (frame_active_) | |
| 449 FinishFrame(); | |
| 450 | |
| 451 frame_active_ = true; | |
| 452 last_begin_frame_args_ = args; | 331 last_begin_frame_args_ = args; |
| 453 ack_tracker_.OnBeginFrame(args); | |
| 454 std::unordered_set<BeginFrameObserver*> observers(observers_); | 332 std::unordered_set<BeginFrameObserver*> observers(observers_); |
| 455 for (auto* obs : observers) { | 333 for (auto* obs : observers) { |
| 456 // It is possible that the source in which |args| originate changes, or that | 334 // It is possible that the source in which |args| originate changes, or that |
| 457 // our hookup to this source changes, so we have to check for continuity. | 335 // our hookup to this source changes, so we have to check for continuity. |
| 458 // See also https://crbug.com/690127 for what may happen without this check. | 336 // See also https://crbug.com/690127 for what may happen without this check. |
| 459 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | 337 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); |
| 460 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) { | 338 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) { |
| 461 DCHECK((args.source_id != last_args.source_id) || | 339 DCHECK((args.source_id != last_args.source_id) || |
| 462 (args.sequence_number > last_args.sequence_number)) | 340 (args.sequence_number > last_args.sequence_number)) |
| 463 << "current " << args.AsValue()->ToString() << ", last " | 341 << "current " << args.AsValue()->ToString() << ", last " |
| 464 << last_args.AsValue()->ToString(); | 342 << last_args.AsValue()->ToString(); |
| 465 obs->OnBeginFrame(args); | 343 obs->OnBeginFrame(args); |
| 466 } | 344 } |
| 467 } | 345 } |
| 468 MaybeFinishFrame(); | |
| 469 } | |
| 470 | |
| 471 void ExternalBeginFrameSource::MaybeFinishFrame() { | |
| 472 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame()) | |
| 473 return; | |
| 474 FinishFrame(); | |
| 475 } | |
| 476 | |
| 477 void ExternalBeginFrameSource::FinishFrame() { | |
| 478 frame_active_ = false; | |
| 479 | |
| 480 BeginFrameAck ack(last_begin_frame_args_.source_id, | |
| 481 last_begin_frame_args_.sequence_number, | |
| 482 ack_tracker_.LatestConfirmedSequenceNumber(), | |
| 483 ack_tracker_.AnyObserversHadDamage()); | |
| 484 client_->OnDidFinishFrame(ack); | |
| 485 } | 346 } |
| 486 | 347 |
| 487 } // namespace cc | 348 } // namespace cc |
| OLD | NEW |