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