begin_frame_tracker.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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
  3. // found in the LICENSE file.
  4. #include "cc/scheduler/begin_frame_tracker.h"
  5. #include "base/trace_event/trace_event.h"
  6. #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
  7. namespace cc {
  8. BeginFrameTracker::BeginFrameTracker(const base::Location& location)
  9. : location_(location),
  10. location_string_(location.ToString()),
  11. current_finished_at_(base::TimeTicks() + base::Microseconds(-1)) {}
  12. BeginFrameTracker::~BeginFrameTracker() = default;
  13. void BeginFrameTracker::Start(const viz::BeginFrameArgs& new_args) {
  14. // Trace the frame time being passed between BeginFrameTrackers.
  15. TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
  16. "BeginFrameArgs",
  17. new_args.frame_time.since_origin().InMicroseconds(),
  18. TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
  19. "location", location_string_);
  20. // Trace this specific begin frame tracker Start/Finish times.
  21. TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN2(
  22. TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
  23. location_string_.c_str(),
  24. TRACE_ID_WITH_SCOPE(location_string_.c_str(),
  25. new_args.frame_time.since_origin().InMicroseconds()),
  26. "new args", new_args.AsValue(), "current args", current_args_.AsValue());
  27. // Check the new viz::BeginFrameArgs are valid and monotonically increasing.
  28. DCHECK(new_args.IsValid());
  29. DCHECK_LE(current_args_.frame_time, new_args.frame_time);
  30. DCHECK(HasFinished())
  31. << "Tried to start a new frame before finishing an existing frame.";
  32. current_updated_at_ = base::TimeTicks::Now();
  33. current_args_ = new_args;
  34. current_finished_at_ = base::TimeTicks();
  35. // TODO(mithro): Add UMA tracking of delta between current_updated_at_ time
  36. // and the new_args.frame_time argument. This will give us how long after a
  37. // viz::BeginFrameArgs message was created before we started processing it.
  38. }
  39. const viz::BeginFrameArgs& BeginFrameTracker::Current() const {
  40. DCHECK(!HasFinished())
  41. << "Tried to use viz::BeginFrameArgs after marking the frame finished.";
  42. DCHECK(current_args_.IsValid())
  43. << "Tried to use viz::BeginFrameArgs before starting a frame!";
  44. return current_args_;
  45. }
  46. void BeginFrameTracker::Finish() {
  47. DCHECK(!HasFinished()) << "Tried to finish an already finished frame";
  48. current_finished_at_ = base::TimeTicks::Now();
  49. TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(
  50. TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
  51. location_string_.c_str(),
  52. TRACE_ID_WITH_SCOPE(
  53. location_string_.c_str(),
  54. current_args_.frame_time.since_origin().InMicroseconds()));
  55. }
  56. const viz::BeginFrameArgs& BeginFrameTracker::Last() const {
  57. DCHECK(current_args_.IsValid())
  58. << "Tried to use last viz::BeginFrameArgs before starting a frame!";
  59. DCHECK(HasFinished())
  60. << "Tried to use last viz::BeginFrameArgs before the frame is finished.";
  61. return current_args_;
  62. }
  63. base::TimeDelta BeginFrameTracker::Interval() const {
  64. base::TimeDelta interval = current_args_.interval;
  65. // Normal interval will be ~16ms, 200Hz (5ms) screens are the fastest
  66. // easily available so anything less than that is likely an error.
  67. if (interval < base::Milliseconds(1)) {
  68. interval = viz::BeginFrameArgs::DefaultInterval();
  69. }
  70. return interval;
  71. }
  72. void BeginFrameTracker::AsProtozeroInto(
  73. perfetto::EventContext& ctx,
  74. base::TimeTicks now,
  75. perfetto::protos::pbzero::BeginImplFrameArgs* state) const {
  76. state->set_updated_at_us(current_updated_at_.since_origin().InMicroseconds());
  77. state->set_finished_at_us(
  78. current_finished_at_.since_origin().InMicroseconds());
  79. if (HasFinished()) {
  80. state->set_state(
  81. perfetto::protos::pbzero::BeginImplFrameArgs::BEGIN_FRAME_FINISHED);
  82. current_args_.AsProtozeroInto(ctx, state->set_current_args());
  83. } else {
  84. state->set_state(
  85. perfetto::protos::pbzero::BeginImplFrameArgs::BEGIN_FRAME_USING);
  86. current_args_.AsProtozeroInto(ctx, state->set_last_args());
  87. }
  88. base::TimeTicks frame_time = current_args_.frame_time;
  89. base::TimeTicks deadline = current_args_.deadline;
  90. base::TimeDelta interval = current_args_.interval;
  91. auto* timestamps = state->set_timestamps_in_us();
  92. timestamps->set_interval_delta(interval.InMicroseconds());
  93. timestamps->set_now_to_deadline_delta((deadline - now).InMicroseconds());
  94. timestamps->set_frame_time_to_now_delta((now - frame_time).InMicroseconds());
  95. timestamps->set_frame_time_to_deadline_delta(
  96. (deadline - frame_time).InMicroseconds());
  97. timestamps->set_now(now.since_origin().InMicroseconds());
  98. timestamps->set_frame_time(frame_time.since_origin().InMicroseconds());
  99. timestamps->set_deadline(deadline.since_origin().InMicroseconds());
  100. }
  101. const viz::BeginFrameArgs& BeginFrameTracker::DangerousMethodCurrentOrLast()
  102. const {
  103. if (!HasFinished()) {
  104. return Current();
  105. } else {
  106. return Last();
  107. }
  108. }
  109. } // namespace cc