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 |