Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: cc/scheduler/begin_frame_source.cc

Issue 2888043004: [cc] Add and plumb CFS::DidNotProduceFrame. (Closed)
Patch Set: address nits, rename to DidNotProduceFrame. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/scheduler/begin_frame_source.h ('k') | cc/scheduler/begin_frame_source_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « cc/scheduler/begin_frame_source.h ('k') | cc/scheduler/begin_frame_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698