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 |