blob: e72bd57464618df7681cdd9863b4ea7252989674 [file] [log] [blame]
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:371// Copyright 2019 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
behdad5fb48ea22019-08-12 18:15:365#include "cc/metrics/frame_sequence_tracker.h"
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:376
Sadrul Habib Chowdhury66ff2722020-06-24 17:47:017#include <algorithm>
8#include <memory>
9#include <string>
10#include <utility>
11
Xiyuan Xia728d1cf562020-04-20 23:10:3312#include "base/bind.h"
Lei Zhang812c5392021-05-18 04:44:3213#include "base/containers/contains.h"
Lei Zhangc34fd3472021-06-30 19:37:5514#include "base/containers/cxx20_erase.h"
Hans Wennborg66d784de2020-06-17 20:23:0315#include "base/logging.h"
Sadrul Habib Chowdhurydb3d7be72019-07-13 03:27:3216#include "base/metrics/histogram.h"
17#include "base/metrics/histogram_macros.h"
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3718#include "base/trace_event/trace_event.h"
19#include "base/trace_event/traced_value.h"
20#include "components/viz/common/frame_sinks/begin_frame_args.h"
21#include "components/viz/common/quads/compositor_frame_metadata.h"
22#include "ui/gfx/presentation_feedback.h"
23
Mingjing Zhang2879aa892019-11-01 02:54:5424// This macro is used with DCHECK to provide addition debug info.
Mingjing Zhang94314962019-11-05 02:59:2025#if DCHECK_IS_ON()
Mingjing Zhangc0ce5412019-11-07 22:00:0726#define TRACKER_TRACE_STREAM frame_sequence_trace_
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1827#define TRACKER_DCHECK_MSG \
Xida Chen3114cbb2020-04-21 01:57:0728 " in " << GetFrameSequenceTrackerTypeName(this->type()) \
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1829 << " tracker: " << frame_sequence_trace_.str() << " (" \
Mingjing Zhangc0ce5412019-11-07 22:00:0730 << frame_sequence_trace_.str().size() << ")";
Mingjing Zhang94314962019-11-05 02:59:2031#else
Mingjing Zhangc0ce5412019-11-07 22:00:0732#define TRACKER_TRACE_STREAM EAT_STREAM_PARAMETERS
Mingjing Zhang94314962019-11-05 02:59:2033#define TRACKER_DCHECK_MSG ""
34#endif
Mingjing Zhang2879aa892019-11-01 02:54:5435
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3736namespace cc {
37
Sadrul Habib Chowdhuryb5335662020-06-16 18:17:4038using ThreadType = FrameSequenceMetrics::ThreadType;
39
Xida Chen89e19212020-04-28 14:43:4540// In the |TRACKER_TRACE_STREAM|, we mod the numbers such as frame sequence
41// number, or frame token, such that the debug string is not too long.
42constexpr int kDebugStrMod = 1000;
43
behdada108d812019-11-20 17:22:3944const char* FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1845 FrameSequenceTrackerType type) {
46 switch (type) {
47 case FrameSequenceTrackerType::kCompositorAnimation:
behdada108d812019-11-20 17:22:3948 return "CompositorAnimation";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1849 case FrameSequenceTrackerType::kMainThreadAnimation:
behdada108d812019-11-20 17:22:3950 return "MainThreadAnimation";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1851 case FrameSequenceTrackerType::kPinchZoom:
behdada108d812019-11-20 17:22:3952 return "PinchZoom";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1853 case FrameSequenceTrackerType::kRAF:
behdada108d812019-11-20 17:22:3954 return "RAF";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1855 case FrameSequenceTrackerType::kTouchScroll:
behdada108d812019-11-20 17:22:3956 return "TouchScroll";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1857 case FrameSequenceTrackerType::kVideo:
behdada108d812019-11-20 17:22:3958 return "Video";
Sadrul Habib Chowdhury1f264532020-01-14 21:00:1859 case FrameSequenceTrackerType::kWheelScroll:
behdada108d812019-11-20 17:22:3960 return "WheelScroll";
Sadrul Habib Chowdhuryaa3dccfd2020-03-12 00:41:5861 case FrameSequenceTrackerType::kScrollbarScroll:
62 return "ScrollbarScroll";
Xiyuan Xiaab73cc02020-03-30 22:36:4363 case FrameSequenceTrackerType::kCustom:
64 return "Custom";
Xida Chen9d689d82020-11-05 22:26:3565 case FrameSequenceTrackerType::kCanvasAnimation:
66 return "CanvasAnimation";
Xida Chen3b1ae1d2020-09-24 14:48:3967 case FrameSequenceTrackerType::kJSAnimation:
68 return "JSAnimation";
Sadrul Habib Chowdhuryaa3dccfd2020-03-12 00:41:5869 case FrameSequenceTrackerType::kMaxType:
behdada108d812019-11-20 17:22:3970 return "";
71 }
72}
Xida Chen78ba8b72019-08-30 14:49:2573
Xida Chen4ede1d692019-11-22 18:00:4874FrameSequenceTracker::FrameSequenceTracker(
75 FrameSequenceTrackerType type,
Xiyuan Xia728d1cf562020-04-20 23:10:3376 ThroughputUkmReporter* throughput_ukm_reporter)
Xida Chen3114cbb2020-04-21 01:57:0777 : custom_sequence_id_(-1),
Sadrul Habib Chowdhury6c901cd52020-06-10 00:51:0078 metrics_(
79 std::make_unique<FrameSequenceMetrics>(type,
80 throughput_ukm_reporter)) {
Xida Chen3114cbb2020-04-21 01:57:0781 DCHECK_LT(type, FrameSequenceTrackerType::kMaxType);
82 DCHECK(type != FrameSequenceTrackerType::kCustom);
Xida Chenb75b312702020-12-17 23:37:4583 // TODO(crbug.com/1158439): remove the trace event once the validation is
84 // completed.
85 TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
86 "cc,benchmark", "TrackerValidation", TRACE_ID_LOCAL(this),
87 base::TimeTicks::Now(), "name", GetFrameSequenceTrackerTypeName(type));
Xiyuan Xia728d1cf562020-04-20 23:10:3388}
89
90FrameSequenceTracker::FrameSequenceTracker(
91 int custom_sequence_id,
92 FrameSequenceMetrics::CustomReporter custom_reporter)
Xida Chen3114cbb2020-04-21 01:57:0793 : custom_sequence_id_(custom_sequence_id),
94 metrics_(std::make_unique<FrameSequenceMetrics>(
95 FrameSequenceTrackerType::kCustom,
Sadrul Habib Chowdhury6c901cd52020-06-10 00:51:0096 /*ukm_reporter=*/nullptr)) {
Xiyuan Xia728d1cf562020-04-20 23:10:3397 DCHECK_GT(custom_sequence_id_, 0);
98 metrics_->SetCustomReporter(std::move(custom_reporter));
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:3799}
100
Xida Chenc89c1c92020-07-26 00:42:04101FrameSequenceTracker::~FrameSequenceTracker() {
Xida Chenb75b312702020-12-17 23:37:45102 TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
103 "cc,benchmark", "TrackerValidation", TRACE_ID_LOCAL(this),
104 base::TimeTicks::Now());
Xida Chenc89c1c92020-07-26 00:42:04105 CleanUp();
106}
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31107
Xida Chen620072032020-01-10 17:21:35108void FrameSequenceTracker::ScheduleTerminate() {
Xida Chen8f5fc492020-04-02 21:55:04109 // If the last frame has ended and there is no frame awaiting presentation,
110 // then it is ready to terminate.
111 if (!is_inside_frame_ && last_submitted_frame_ == 0)
112 termination_status_ = TerminationStatus::kReadyForTermination;
113 else
114 termination_status_ = TerminationStatus::kScheduledForTermination;
Xida Chen620072032020-01-10 17:21:35115}
116
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37117void FrameSequenceTracker::ReportBeginImplFrame(
118 const viz::BeginFrameArgs& args) {
119 if (termination_status_ != TerminationStatus::kActive)
120 return;
121
behdad2adc4232019-12-18 18:11:39122 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50123 return;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13124
Xida Chen89e19212020-04-28 14:43:45125 TRACKER_TRACE_STREAM << "b(" << args.frame_id.sequence_number % kDebugStrMod
126 << ")";
Sadrul Habib Chowdhury2f848d22019-12-23 16:34:09127
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29128 DCHECK(!is_inside_frame_) << TRACKER_DCHECK_MSG;
129 is_inside_frame_ = true;
Xida Chen8f5fc492020-04-02 21:55:04130#if DCHECK_IS_ON()
Xida Chend56033c2019-12-05 13:31:41131 if (args.type == viz::BeginFrameArgs::NORMAL)
behdad2adc4232019-12-18 18:11:39132 impl_frames_.insert(args.frame_id);
Xida Chend56033c2019-12-05 13:31:41133#endif
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47134
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57135 DCHECK_EQ(last_started_impl_sequence_, 0u) << TRACKER_DCHECK_MSG;
Xida Chen620072032020-01-10 17:21:35136 last_started_impl_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12137 if (reset_all_state_) {
138 begin_impl_frame_data_ = {};
139 begin_main_frame_data_ = {};
140 reset_all_state_ = false;
141 }
142
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47143 DCHECK(!frame_had_no_compositor_damage_) << TRACKER_DCHECK_MSG;
144 DCHECK(!compositor_frame_submitted_) << TRACKER_DCHECK_MSG;
145
behdad2adc4232019-12-18 18:11:39146 UpdateTrackedFrameData(&begin_impl_frame_data_, args.frame_id.source_id,
yjliu9d3df972021-04-08 17:03:49147 args.frame_id.sequence_number,
148 args.frames_throttled_since_last);
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28149 impl_throughput().frames_expected +=
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37150 begin_impl_frame_data_.previous_sequence_delta;
Xida Chen675c2d72020-01-16 13:06:48151#if DCHECK_IS_ON()
152 ++impl_throughput().frames_received;
153#endif
Xida Chen1102307b2019-10-11 17:03:15154
155 if (first_frame_timestamp_.is_null())
156 first_frame_timestamp_ = args.frame_time;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37157}
158
159void FrameSequenceTracker::ReportBeginMainFrame(
160 const viz::BeginFrameArgs& args) {
161 if (termination_status_ != TerminationStatus::kActive)
162 return;
163
behdad2adc4232019-12-18 18:11:39164 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50165 return;
166
Xida Chen89e19212020-04-28 14:43:45167 TRACKER_TRACE_STREAM << "B("
168 << begin_main_frame_data_.previous_sequence %
169 kDebugStrMod
170 << "," << args.frame_id.sequence_number % kDebugStrMod
171 << ")";
Sadrul Habib Chowdhurye49c0a62019-12-22 04:36:22172
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57173 if (first_received_main_sequence_ &&
174 first_received_main_sequence_ > args.frame_id.sequence_number) {
Xida Chend56033c2019-12-05 13:31:41175 return;
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57176 }
177
178 if (!first_received_main_sequence_ &&
179 ShouldIgnoreSequence(args.frame_id.sequence_number)) {
180 return;
181 }
Xida Chend56033c2019-12-05 13:31:41182
183#if DCHECK_IS_ON()
184 if (args.type == viz::BeginFrameArgs::NORMAL) {
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57185 DCHECK(impl_frames_.contains(args.frame_id)) << TRACKER_DCHECK_MSG;
Xida Chend56033c2019-12-05 13:31:41186 }
187#endif
188
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57189 DCHECK_EQ(awaiting_main_response_sequence_, 0u) << TRACKER_DCHECK_MSG;
190 last_processed_main_sequence_latency_ = 0;
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34191 awaiting_main_response_sequence_ = args.frame_id.sequence_number;
192
behdad2adc4232019-12-18 18:11:39193 UpdateTrackedFrameData(&begin_main_frame_data_, args.frame_id.source_id,
yjliu9d3df972021-04-08 17:03:49194 args.frame_id.sequence_number,
195 args.frames_throttled_since_last);
Sadrul Habib Chowdhury1b9fea6a2019-12-18 02:26:02196 if (!first_received_main_sequence_ ||
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34197 first_received_main_sequence_ <= last_no_main_damage_sequence_) {
behdad2adc4232019-12-18 18:11:39198 first_received_main_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34199 }
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28200 main_throughput().frames_expected +=
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37201 begin_main_frame_data_.previous_sequence_delta;
Xida Chen8ee29c9a2020-01-30 18:59:23202 previous_begin_main_sequence_ = current_begin_main_sequence_;
203 current_begin_main_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37204}
205
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34206void FrameSequenceTracker::ReportMainFrameProcessed(
207 const viz::BeginFrameArgs& args) {
208 if (termination_status_ != TerminationStatus::kActive)
209 return;
210
211 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
212 return;
213
Xida Chen89e19212020-04-28 14:43:45214 TRACKER_TRACE_STREAM << "E(" << args.frame_id.sequence_number % kDebugStrMod
215 << ")";
Xida Chen8ee29c9a2020-01-30 18:59:23216
217 const bool previous_main_frame_submitted_or_no_damage =
218 previous_begin_main_sequence_ != 0 &&
219 (last_submitted_main_sequence_ == previous_begin_main_sequence_ ||
220 last_no_main_damage_sequence_ == previous_begin_main_sequence_);
221 if (last_processed_main_sequence_ != 0 &&
222 !had_impl_frame_submitted_between_commits_ &&
223 !previous_main_frame_submitted_or_no_damage) {
224 DCHECK_GE(main_throughput().frames_expected,
225 begin_main_frame_data_.previous_sequence_delta)
226 << TRACKER_DCHECK_MSG;
227 main_throughput().frames_expected -=
228 begin_main_frame_data_.previous_sequence_delta;
229 last_no_main_damage_sequence_ = previous_begin_main_sequence_;
230 }
231 had_impl_frame_submitted_between_commits_ = false;
232
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34233 if (first_received_main_sequence_ &&
234 args.frame_id.sequence_number >= first_received_main_sequence_) {
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57235 if (awaiting_main_response_sequence_) {
236 DCHECK_EQ(awaiting_main_response_sequence_, args.frame_id.sequence_number)
237 << TRACKER_DCHECK_MSG;
238 }
239 DCHECK_EQ(last_processed_main_sequence_latency_, 0u) << TRACKER_DCHECK_MSG;
240 last_processed_main_sequence_ = args.frame_id.sequence_number;
241 last_processed_main_sequence_latency_ =
242 std::max(last_started_impl_sequence_, last_processed_impl_sequence_) -
243 args.frame_id.sequence_number;
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34244 awaiting_main_response_sequence_ = 0;
245 }
246}
247
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37248void FrameSequenceTracker::ReportSubmitFrame(
249 uint32_t frame_token,
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31250 bool has_missing_content,
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37251 const viz::BeginFrameAck& ack,
252 const viz::BeginFrameArgs& origin_args) {
Xida Chen8f5fc492020-04-02 21:55:04253 DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
Xida Chen139a8f982020-04-21 19:34:14254
255 // TODO(crbug.com/1072482): find a proper way to terminate a tracker.
Xida Chen2c92ba92020-04-30 01:15:21256 // Right now, we define a magical number |frames_to_terminate_tracker| = 3,
257 // which means that if this frame_token is more than 3 frames compared with
Xida Chen139a8f982020-04-21 19:34:14258 // the last submitted frame, then we assume that the last submitted frame is
259 // not going to be presented, and thus terminate this tracker.
Xida Chen2c92ba92020-04-30 01:15:21260 const uint32_t frames_to_terminate_tracker = 3;
Xida Chen139a8f982020-04-21 19:34:14261 if (termination_status_ == TerminationStatus::kScheduledForTermination &&
Xida Chen9d403eb2020-04-25 00:23:26262 last_submitted_frame_ != 0 &&
Xida Chen139a8f982020-04-21 19:34:14263 viz::FrameTokenGT(frame_token,
264 last_submitted_frame_ + frames_to_terminate_tracker)) {
265 termination_status_ = TerminationStatus::kReadyForTermination;
266 return;
267 }
268
Xida Chen8f5fc492020-04-02 21:55:04269 if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id) ||
behdad2adc4232019-12-18 18:11:39270 ShouldIgnoreSequence(ack.frame_id.sequence_number)) {
Xida Chend56033c2019-12-05 13:31:41271 ignored_frame_tokens_.insert(frame_token);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37272 return;
273 }
274
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29275#if DCHECK_IS_ON()
276 DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG;
Xida Chen675c2d72020-01-16 13:06:48277 DCHECK_LT(impl_throughput().frames_processed,
278 impl_throughput().frames_received)
279 << TRACKER_DCHECK_MSG;
280 ++impl_throughput().frames_processed;
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29281#endif
Sadrul Habib Chowdhurye49c0a62019-12-22 04:36:22282
Xida Chen620072032020-01-10 17:21:35283 last_processed_impl_sequence_ = ack.frame_id.sequence_number;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37284 if (first_submitted_frame_ == 0)
285 first_submitted_frame_ = frame_token;
286 last_submitted_frame_ = frame_token;
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47287 compositor_frame_submitted_ = true;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37288
Xida Chen89e19212020-04-28 14:43:45289 TRACKER_TRACE_STREAM << "s(" << frame_token % kDebugStrMod << ")";
Xida Chen8ee29c9a2020-01-30 18:59:23290 had_impl_frame_submitted_between_commits_ = true;
Mingjing Zhang0241cc422020-10-02 21:27:12291 metrics()->NotifySubmitForJankReporter(
292 FrameSequenceMetrics::ThreadType::kCompositor, frame_token,
293 ack.frame_id.sequence_number);
Xida Chenbe102af2020-03-10 00:52:34294
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13295 const bool main_changes_after_sequence_started =
296 first_received_main_sequence_ &&
behdad2adc4232019-12-18 18:11:39297 origin_args.frame_id.sequence_number >= first_received_main_sequence_;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13298 const bool main_changes_include_new_changes =
299 last_submitted_main_sequence_ == 0 ||
behdad2adc4232019-12-18 18:11:39300 origin_args.frame_id.sequence_number > last_submitted_main_sequence_;
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13301 const bool main_change_had_no_damage =
302 last_no_main_damage_sequence_ != 0 &&
behdad2adc4232019-12-18 18:11:39303 origin_args.frame_id.sequence_number == last_no_main_damage_sequence_;
Xida Chen8f5fc492020-04-02 21:55:04304 const bool origin_args_is_valid = origin_args.frame_id.sequence_number <=
305 begin_main_frame_data_.previous_sequence;
Mingjing Zhang94314962019-11-05 02:59:20306
Xida Chen8f5fc492020-04-02 21:55:04307 if (!ShouldIgnoreBeginFrameSource(origin_args.frame_id.source_id) &&
308 origin_args_is_valid) {
Xida Chenbc14a112020-03-30 18:22:58309 if (main_changes_after_sequence_started &&
310 main_changes_include_new_changes && !main_change_had_no_damage) {
311 submitted_frame_had_new_main_content_ = true;
Xida Chen89e19212020-04-28 14:43:45312 TRACKER_TRACE_STREAM << "S("
313 << origin_args.frame_id.sequence_number %
314 kDebugStrMod
Xida Chenbc14a112020-03-30 18:22:58315 << ")";
Mingjing Zhang0241cc422020-10-02 21:27:12316 metrics()->NotifySubmitForJankReporter(
317 FrameSequenceMetrics::ThreadType::kMain, frame_token,
318 origin_args.frame_id.sequence_number);
Sadrul Habib Chowdhurydc34c8b2019-12-16 18:39:13319
Xida Chenbc14a112020-03-30 18:22:58320 last_submitted_main_sequence_ = origin_args.frame_id.sequence_number;
321 main_frames_.push_back(frame_token);
322 DCHECK_GE(main_throughput().frames_expected, main_frames_.size())
323 << TRACKER_DCHECK_MSG;
Xida Chenbc14a112020-03-30 18:22:58324 }
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37325 }
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31326
327 if (has_missing_content) {
328 checkerboarding_.frames.push_back(frame_token);
329 }
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37330}
331
Sadrul Habib Chowdhury61e02662020-01-31 20:55:33332void FrameSequenceTracker::ReportFrameEnd(
333 const viz::BeginFrameArgs& args,
334 const viz::BeginFrameArgs& main_args) {
Xida Chen8f5fc492020-04-02 21:55:04335 DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29336
behdad2adc4232019-12-18 18:11:39337 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29338 return;
339
Xida Chen89e19212020-04-28 14:43:45340 TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number % kDebugStrMod
341 << ","
342 << main_args.frame_id.sequence_number % kDebugStrMod
343 << ")";
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47344
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12345 bool should_ignore_sequence =
346 ShouldIgnoreSequence(args.frame_id.sequence_number);
347 if (reset_all_state_) {
348 begin_impl_frame_data_ = {};
349 begin_main_frame_data_ = {};
350 reset_all_state_ = false;
351 }
352
353 if (should_ignore_sequence) {
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12354 is_inside_frame_ = false;
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12355 return;
356 }
357
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57358 if (compositor_frame_submitted_ && submitted_frame_had_new_main_content_ &&
359 last_processed_main_sequence_latency_) {
360 // If a compositor frame was submitted with new content from the
361 // main-thread, then make sure the latency gets accounted for.
362 main_throughput().frames_expected += last_processed_main_sequence_latency_;
363 }
364
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47365 // It is possible that the compositor claims there was no damage from the
366 // compositor, but before the frame ends, it submits a compositor frame (e.g.
367 // with some damage from main). In such cases, the compositor is still
368 // responsible for processing the update, and therefore the 'no damage' claim
369 // is ignored.
370 if (frame_had_no_compositor_damage_ && !compositor_frame_submitted_) {
371 DCHECK_GT(impl_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG;
372 DCHECK_GT(impl_throughput().frames_expected,
373 impl_throughput().frames_produced)
374 << TRACKER_DCHECK_MSG;
Matthew Crabill79be85f2020-09-16 19:02:58375 DCHECK_GE(impl_throughput().frames_produced,
376 impl_throughput().frames_ontime)
377 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47378 --impl_throughput().frames_expected;
Mingjing Zhang0241cc422020-10-02 21:27:12379 metrics()->NotifyNoUpdateForJankReporter(
380 FrameSequenceMetrics::ThreadType::kCompositor,
381 args.frame_id.sequence_number, args.interval);
Xida Chen675c2d72020-01-16 13:06:48382#if DCHECK_IS_ON()
Xida Chen675c2d72020-01-16 13:06:48383 ++impl_throughput().frames_processed;
Xida Chen4bde850d2020-01-22 20:25:40384 // If these two are the same, it means that each impl frame is either
385 // no-damage or submitted. That's expected, so we don't need those in the
386 // output of DCHECK.
387 if (impl_throughput().frames_processed == impl_throughput().frames_received)
388 ignored_trace_char_count_ = frame_sequence_trace_.str().size();
389 else
390 NOTREACHED() << TRACKER_DCHECK_MSG;
Xida Chen675c2d72020-01-16 13:06:48391#endif
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47392 begin_impl_frame_data_.previous_sequence = 0;
393 }
Xida Chen8f5fc492020-04-02 21:55:04394 // last_submitted_frame_ == 0 means the last impl frame has been presented.
395 if (termination_status_ == TerminationStatus::kScheduledForTermination &&
396 last_submitted_frame_ == 0)
397 termination_status_ = TerminationStatus::kReadyForTermination;
398
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47399 frame_had_no_compositor_damage_ = false;
400 compositor_frame_submitted_ = false;
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57401 submitted_frame_had_new_main_content_ = false;
402 last_processed_main_sequence_latency_ = 0;
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47403
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29404 DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG;
405 is_inside_frame_ = false;
Xida Chen620072032020-01-10 17:21:35406
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57407 DCHECK_EQ(last_started_impl_sequence_, last_processed_impl_sequence_)
408 << TRACKER_DCHECK_MSG;
409 last_started_impl_sequence_ = 0;
Sadrul Habib Chowdhury7fe10ea2019-12-11 01:59:29410}
411
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37412void FrameSequenceTracker::ReportFramePresented(
413 uint32_t frame_token,
414 const gfx::PresentationFeedback& feedback) {
Xida Chenc9e3b622020-04-17 17:29:11415 // TODO(xidachen): We should early exit if |last_submitted_frame_| = 0, as it
416 // means that we are presenting the same frame_token again.
417 const bool submitted_frame_since_last_presentation = !!last_submitted_frame_;
Xida Chen8f5fc492020-04-02 21:55:04418 // !viz::FrameTokenGT(a, b) is equivalent to b >= a.
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37419 const bool frame_token_acks_last_frame =
Xida Chen8f5fc492020-04-02 21:55:04420 !viz::FrameTokenGT(last_submitted_frame_, frame_token);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37421
Xida Chenc9e3b622020-04-17 17:29:11422 // Even if the presentation timestamp is null, we set last_submitted_frame_ to
423 // 0 such that the tracker can be terminated.
424 if (last_submitted_frame_ && frame_token_acks_last_frame)
425 last_submitted_frame_ = 0;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37426 // Update termination status if this is scheduled for termination, and it is
427 // not waiting for any frames, or it has received the presentation-feedback
428 // for the latest frame it is tracking.
Xida Chen8f5fc492020-04-02 21:55:04429 //
430 // We should always wait for an impl frame to end, that is, ReportFrameEnd.
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37431 if (termination_status_ == TerminationStatus::kScheduledForTermination &&
Xida Chenc9e3b622020-04-17 17:29:11432 last_submitted_frame_ == 0 && !is_inside_frame_) {
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37433 termination_status_ = TerminationStatus::kReadyForTermination;
434 }
435
436 if (first_submitted_frame_ == 0 ||
437 viz::FrameTokenGT(first_submitted_frame_, frame_token)) {
438 // We are getting presentation feedback for frames that were submitted
439 // before this sequence started. So ignore these.
440 return;
441 }
442
Xida Chen89e19212020-04-28 14:43:45443 TRACKER_TRACE_STREAM << "P(" << frame_token % kDebugStrMod << ")";
Sadrul Habib Chowdhury2f848d22019-12-23 16:34:09444
Xida Chen8f5fc492020-04-02 21:55:04445 base::EraseIf(ignored_frame_tokens_, [frame_token](const uint32_t& token) {
446 return viz::FrameTokenGT(frame_token, token);
447 });
Xida Chenc9e3b622020-04-17 17:29:11448 if (ignored_frame_tokens_.contains(frame_token))
449 return;
Xida Chend56033c2019-12-05 13:31:41450
Xida Chenbc14a112020-03-30 18:22:58451 uint32_t impl_frames_produced = 0;
452 uint32_t main_frames_produced = 0;
Matthew Crabill79be85f2020-09-16 19:02:58453 uint32_t impl_frames_ontime = 0;
454 uint32_t main_frames_ontime = 0;
455
Mingjing Zhang45ebbbe52021-01-07 17:42:35456 const auto vsync_interval =
Matthew Crabill79be85f2020-09-16 19:02:58457 (feedback.interval.is_zero() ? viz::BeginFrameArgs::DefaultInterval()
Mingjing Zhang45ebbbe52021-01-07 17:42:35458 : feedback.interval);
Matthew Crabill79be85f2020-09-16 19:02:58459 DCHECK(!vsync_interval.is_zero()) << TRACKER_DCHECK_MSG;
460 base::TimeTicks safe_deadline_for_frame =
Mingjing Zhang45ebbbe52021-01-07 17:42:35461 last_frame_presentation_timestamp_ + vsync_interval * 1.5;
Sadrul Habib Chowdhury6d7b07d762020-03-13 15:42:08462
Sadrul Habib Chowdhuryd5f58812020-06-11 21:30:52463 const bool was_presented = !feedback.failed();
Xida Chenc9e3b622020-04-17 17:29:11464 if (was_presented && submitted_frame_since_last_presentation) {
Matthew Crabill79be85f2020-09-16 19:02:58465 if (!last_frame_presentation_timestamp_.is_null() &&
466 (safe_deadline_for_frame < feedback.timestamp)) {
467 DCHECK_LE(impl_throughput().frames_ontime,
468 impl_throughput().frames_produced)
469 << TRACKER_DCHECK_MSG;
470 ++impl_throughput().frames_ontime;
471 ++impl_frames_ontime;
472 }
473
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28474 DCHECK_LT(impl_throughput().frames_produced,
475 impl_throughput().frames_expected)
Mingjing Zhang2879aa892019-11-01 02:54:54476 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28477 ++impl_throughput().frames_produced;
Xida Chenbc14a112020-03-30 18:22:58478 ++impl_frames_produced;
Sadrul Habib Chowdhuryb5335662020-06-16 18:17:40479 if (metrics()->GetEffectiveThread() == ThreadType::kCompositor) {
480 metrics()->AdvanceTrace(feedback.timestamp);
481 }
Mingjing Zhang45946b22020-08-14 23:18:18482
483 metrics()->ComputeJank(FrameSequenceMetrics::ThreadType::kCompositor,
Mingjing Zhang45ebbbe52021-01-07 17:42:35484 frame_token, feedback.timestamp, vsync_interval);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37485 }
486
Xida Chenbe102af2020-03-10 00:52:34487 if (was_presented) {
488 // This presentation includes the visual update from all main frame tokens
489 // <= |frame_token|.
490 const unsigned size_before_erase = main_frames_.size();
491 while (!main_frames_.empty() &&
492 !viz::FrameTokenGT(main_frames_.front(), frame_token)) {
493 main_frames_.pop_front();
494 }
495 if (main_frames_.size() < size_before_erase) {
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28496 DCHECK_LT(main_throughput().frames_produced,
497 main_throughput().frames_expected)
Mingjing Zhang94314962019-11-05 02:59:20498 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28499 ++main_throughput().frames_produced;
Xida Chenbc14a112020-03-30 18:22:58500 ++main_frames_produced;
Sadrul Habib Chowdhuryb5335662020-06-16 18:17:40501 if (metrics()->GetEffectiveThread() == ThreadType::kMain) {
502 metrics()->AdvanceTrace(feedback.timestamp);
503 }
Mingjing Zhang45946b22020-08-14 23:18:18504
505 metrics()->ComputeJank(FrameSequenceMetrics::ThreadType::kMain,
Mingjing Zhang45ebbbe52021-01-07 17:42:35506 frame_token, feedback.timestamp, vsync_interval);
Xida Chenbc14a112020-03-30 18:22:58507 }
Matthew Crabill79be85f2020-09-16 19:02:58508 if (main_frames_.size() < size_before_erase) {
509 if (!last_frame_presentation_timestamp_.is_null() &&
510 (safe_deadline_for_frame < feedback.timestamp)) {
511 DCHECK_LE(main_throughput().frames_ontime,
512 main_throughput().frames_produced)
513 << TRACKER_DCHECK_MSG;
514 ++main_throughput().frames_ontime;
515 ++main_frames_ontime;
516 }
517 }
Matthew Crabill79be85f2020-09-16 19:02:58518 last_frame_presentation_timestamp_ = feedback.timestamp;
519
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31520 if (checkerboarding_.last_frame_had_checkerboarding) {
Mingjing Zhang2879aa892019-11-01 02:54:54521 DCHECK(!checkerboarding_.last_frame_timestamp.is_null())
522 << TRACKER_DCHECK_MSG;
523 DCHECK(!feedback.timestamp.is_null()) << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31524
525 // |feedback.timestamp| is the timestamp when the latest frame was
526 // presented. |checkerboarding_.last_frame_timestamp| is the timestamp
527 // when the previous frame (which had checkerboarding) was presented. Use
528 // |feedback.interval| to compute the number of vsyncs that have passed
529 // between the two frames (since that is how many times the user saw that
530 // checkerboarded frame).
531 base::TimeDelta difference =
532 feedback.timestamp - checkerboarding_.last_frame_timestamp;
533 const auto& interval = feedback.interval.is_zero()
534 ? viz::BeginFrameArgs::DefaultInterval()
535 : feedback.interval;
Mingjing Zhang2879aa892019-11-01 02:54:54536 DCHECK(!interval.is_zero()) << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31537 constexpr base::TimeDelta kEpsilon = base::TimeDelta::FromMilliseconds(1);
Peter Kastingd0bcff92020-08-01 21:50:58538 int64_t frames = (difference + kEpsilon).IntDiv(interval);
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45539 metrics_->add_checkerboarded_frames(frames);
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31540 }
541
542 const bool frame_had_checkerboarding =
543 base::Contains(checkerboarding_.frames, frame_token);
544 checkerboarding_.last_frame_had_checkerboarding = frame_had_checkerboarding;
545 checkerboarding_.last_frame_timestamp = feedback.timestamp;
546 }
547
548 while (!checkerboarding_.frames.empty() &&
549 !viz::FrameTokenGT(checkerboarding_.frames.front(), frame_token)) {
550 checkerboarding_.frames.pop_front();
551 }
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37552}
553
554void FrameSequenceTracker::ReportImplFrameCausedNoDamage(
555 const viz::BeginFrameAck& ack) {
Xida Chen8f5fc492020-04-02 21:55:04556 DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37557
behdad2adc4232019-12-18 18:11:39558 if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50559 return;
560
Xida Chen89e19212020-04-28 14:43:45561 TRACKER_TRACE_STREAM << "n(" << ack.frame_id.sequence_number % kDebugStrMod
562 << ")";
Sadrul Habib Chowdhurye49c0a62019-12-22 04:36:22563
Xida Chen8f5fc492020-04-02 21:55:04564 // This tracker would be scheduled to terminate, and this frame doesn't belong
565 // to that tracker.
behdad2adc4232019-12-18 18:11:39566 if (ShouldIgnoreSequence(ack.frame_id.sequence_number))
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37567 return;
Sadrul Habib Chowdhurye49c0a62019-12-22 04:36:22568
Sadrul Habib Chowdhury1c1af9f2019-12-20 03:52:46569 last_processed_impl_sequence_ = ack.frame_id.sequence_number;
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47570 // If there is no damage for this frame (and no frame is submitted), then the
571 // impl-sequence needs to be reset. However, this should be done after the
572 // processing the frame is complete (i.e. in ReportFrameEnd()), so that other
573 // notifications (e.g. 'no main damage' etc.) can be handled correctly.
574 DCHECK_EQ(begin_impl_frame_data_.previous_sequence,
575 ack.frame_id.sequence_number);
576 frame_had_no_compositor_damage_ = true;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37577}
578
579void FrameSequenceTracker::ReportMainFrameCausedNoDamage(
580 const viz::BeginFrameArgs& args) {
581 if (termination_status_ != TerminationStatus::kActive)
582 return;
583
behdad2adc4232019-12-18 18:11:39584 if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
Sadrul Habib Chowdhury23919172019-07-22 23:58:50585 return;
586
Xida Chen89e19212020-04-28 14:43:45587 TRACKER_TRACE_STREAM << "N("
588 << begin_main_frame_data_.previous_sequence %
589 kDebugStrMod
590 << "," << args.frame_id.sequence_number % kDebugStrMod
591 << ")";
Sadrul Habib Chowdhury2f848d22019-12-23 16:34:09592
Sadrul Habib Chowdhury90aa1fd2020-01-13 16:36:17593 if (!first_received_main_sequence_ ||
594 first_received_main_sequence_ > args.frame_id.sequence_number) {
Xida Chend56033c2019-12-05 13:31:41595 return;
Sadrul Habib Chowdhury90aa1fd2020-01-13 16:36:17596 }
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37597
Sadrul Habib Chowdhurya962eb32019-12-23 02:21:47598 if (last_no_main_damage_sequence_ == args.frame_id.sequence_number)
599 return;
Sadrul Habib Chowdhurye49c0a62019-12-22 04:36:22600
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57601 // It is possible for |awaiting_main_response_sequence_| to be zero here if a
602 // commit had already happened before (e.g. B(x)E(x)N(x)). So check that case
603 // here.
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57604 if (awaiting_main_response_sequence_) {
605 DCHECK_EQ(awaiting_main_response_sequence_, args.frame_id.sequence_number)
606 << TRACKER_DCHECK_MSG;
607 } else {
608 DCHECK_EQ(last_processed_main_sequence_, args.frame_id.sequence_number)
609 << TRACKER_DCHECK_MSG;
610 }
Sadrul Habib Chowdhuryc072db72020-01-16 02:52:34611 awaiting_main_response_sequence_ = 0;
612
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28613 DCHECK_GT(main_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG;
614 DCHECK_GT(main_throughput().frames_expected,
615 main_throughput().frames_produced)
Mingjing Zhang2879aa892019-11-01 02:54:54616 << TRACKER_DCHECK_MSG;
Matthew Crabill79be85f2020-09-16 19:02:58617 DCHECK_GE(main_throughput().frames_produced, main_throughput().frames_ontime)
618 << TRACKER_DCHECK_MSG;
behdad2adc4232019-12-18 18:11:39619 last_no_main_damage_sequence_ = args.frame_id.sequence_number;
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28620 --main_throughput().frames_expected;
Mingjing Zhang0241cc422020-10-02 21:27:12621 metrics()->NotifyNoUpdateForJankReporter(
622 FrameSequenceMetrics::ThreadType::kMain, args.frame_id.sequence_number,
623 args.interval);
624
Sadrul Habib Chowdhuryc537f2f42019-12-05 19:52:28625 DCHECK_GE(main_throughput().frames_expected, main_frames_.size())
Mingjing Zhang2879aa892019-11-01 02:54:54626 << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37627
Xida Chen432fefd52020-03-17 23:20:03628 // Could be 0 if there were a pause frame production.
629 if (begin_main_frame_data_.previous_sequence != 0) {
630 DCHECK_EQ(begin_main_frame_data_.previous_sequence,
631 args.frame_id.sequence_number)
632 << TRACKER_DCHECK_MSG;
633 }
634 begin_main_frame_data_.previous_sequence = 0;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37635}
636
637void FrameSequenceTracker::PauseFrameProduction() {
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12638 // The states need to be reset, so that the tracker ignores the vsyncs until
639 // the next received begin-frame. However, defer doing that until the frame
640 // ends (or a new frame starts), so that in case a frame is in-progress,
641 // subsequent notifications for that frame can be handled correctly.
Sadrul Habib Chowdhury1c1af9f2019-12-20 03:52:46642 TRACKER_TRACE_STREAM << 'R';
Sadrul Habib Chowdhury634b8e012019-12-23 13:46:12643 reset_all_state_ = true;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37644}
645
yjliu9d3df972021-04-08 17:03:49646void FrameSequenceTracker::UpdateTrackedFrameData(
647 TrackedFrameData* frame_data,
648 uint64_t source_id,
649 uint64_t sequence_number,
650 uint64_t throttled_frame_count) {
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37651 if (frame_data->previous_sequence &&
652 frame_data->previous_source == source_id) {
yjliu9d3df972021-04-08 17:03:49653 uint32_t current_latency =
654 sequence_number - frame_data->previous_sequence - throttled_frame_count;
Sadrul Habib Chowdhury1e285552020-01-22 02:46:57655 DCHECK_GT(current_latency, 0u) << TRACKER_DCHECK_MSG;
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37656 frame_data->previous_sequence_delta = current_latency;
657 } else {
658 frame_data->previous_sequence_delta = 1;
659 }
660 frame_data->previous_source = source_id;
661 frame_data->previous_sequence = sequence_number;
662}
663
Sadrul Habib Chowdhury23919172019-07-22 23:58:50664bool FrameSequenceTracker::ShouldIgnoreBeginFrameSource(
665 uint64_t source_id) const {
666 if (begin_impl_frame_data_.previous_source == 0)
Sadrul Habib Chowdhury1c1af9f2019-12-20 03:52:46667 return source_id == viz::BeginFrameArgs::kManualSourceId;
Sadrul Habib Chowdhury23919172019-07-22 23:58:50668 return source_id != begin_impl_frame_data_.previous_source;
669}
670
Xida Chen8f5fc492020-04-02 21:55:04671// This check handles two cases:
672// 1. When there is a call to ReportBeginMainFrame, or ReportSubmitFrame, or
673// ReportFramePresented, there must be a ReportBeginImplFrame for that sequence.
674// Otherwise, the begin_impl_frame_data_.previous_sequence would be 0.
675// 2. A tracker is scheduled to terminate, then any new request to handle a new
676// impl frame whose sequence_number > begin_impl_frame_data_.previous_sequence
677// should be ignored.
678// Note that sequence_number < begin_impl_frame_data_.previous_sequence cannot
679// happen.
Xida Chend56033c2019-12-05 13:31:41680bool FrameSequenceTracker::ShouldIgnoreSequence(
681 uint64_t sequence_number) const {
Xida Chen8f5fc492020-04-02 21:55:04682 return sequence_number != begin_impl_frame_data_.previous_sequence;
Xida Chend56033c2019-12-05 13:31:41683}
684
Xida Chen1102307b2019-10-11 17:03:15685bool FrameSequenceTracker::ShouldReportMetricsNow(
686 const viz::BeginFrameArgs& args) const {
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45687 return metrics_->HasEnoughDataForReporting() &&
688 !first_frame_timestamp_.is_null() &&
689 args.frame_time - first_frame_timestamp_ >= time_delta_to_report_;
690}
691
692std::unique_ptr<FrameSequenceMetrics> FrameSequenceTracker::TakeMetrics() {
Xida Chen8f5fc492020-04-02 21:55:04693#if DCHECK_IS_ON()
694 DCHECK_EQ(impl_throughput().frames_received,
695 impl_throughput().frames_processed)
696 << frame_sequence_trace_.str().substr(ignored_trace_char_count_);
697#endif
Sadrul Habib Chowdhury590a32f2019-12-06 20:08:45698 return std::move(metrics_);
Xida Chen1102307b2019-10-11 17:03:15699}
700
Xida Chenc89c1c92020-07-26 00:42:04701void FrameSequenceTracker::CleanUp() {
702 if (metrics_)
703 metrics_->ReportLeftoverData();
704}
705
Sadrul Habib Chowdhury40a4d8c2019-09-05 03:02:31706FrameSequenceTracker::CheckerboardingData::CheckerboardingData() = default;
707FrameSequenceTracker::CheckerboardingData::~CheckerboardingData() = default;
708
Sadrul Habib Chowdhuryab4d350f2019-07-13 00:17:37709} // namespace cc